ÿØÿà JFIF    ÿÛ „  ( %!1"%)+...383-7(-.+  -%%--------+------------/----------------------------ÿÀ  ¶" ÿÄ     ÿÄ @    !1AQaq‘¡"±ÁÑð2’BRráS‚ñ3b¢CT²Ò #cÿÄ    ÿÄ '   1!AQ2a"‘±#ÿÚ   ? ò(/p‘—–¢·,M|¯G»R£üešT. ôŸEoCFñ‡ 4ÔkåóxR|µÁ¨ÓDà!Ç´µ˜‡p ÍQ‹§!þž^õWsŒy  åÁ§$á«%ºq˜™JyyË0y«^Ϗ -3ÃÏËÈ£Æ\P’ä„s&•‹Üs üô'àWt¹pñCp$bÚF`·7.^)¾!)ÒÙ˜–ÅÏš^h¾ø³·ìe±ŒaeÖ—Í,e=B}Jéߦ$$½—šÙÜCC¯¶è8β–Åkèwx LÉngT±æ¹£Ócœ¿Í/©Éÿ ‰ÚCÒ­mq;Tt¶–}0"zÖPcd1š­¤tˆ„ÐÓâqú[™öUCŠ2޿د­É(¸ßúçšmW,Ò ºf‹Ån™ÄLêÁ8üÁkÁ€L¥ÍuJ1œôrÂSŒÓöt!7EUíïb)AËi¬â-ÙHk8òÁiXYwÅ)O^"ÇØriÛô{»wRUKÙÏÚlÓ¬€‚’שT ] ªb—ÊîKC^×M“xùäñz¬zJ× {4[¹M'IÆeH1LCWÕ]œûº WDæà°OÅ‚¹c²ÞuA–rL`HšpCez‡V’— Ž‚Ë„–ñ­'µR0ÕÖ=À:±G»C\nÆÉ5*¢ †3šhQ4ýÒi$Õ1"Ü]¢p-q3zcQ$ªö¨¥æf›‘»´ÝÚHá„e²JÇ–iÊ:·à¬Øc5Åk»Laª*wi [0Ówk ¦a¦0Õ²ÅÅ‚T¸’³q:Æ<¹ú Ò˜Æ}2VE•Ѐp¡Ô3Úº …h³^LJºçì¥Ánó|˜ÖˆÎˆ+« ¦dø‘Mº–d\ªDðÛ„Ì×LÝ——Ð9Ç|•FèçVm™¨€™3õS–9Äå¢<̉Ìm¢±`·º˜&Z²ž Ë®D«¶»6™‰©­HÈ Àá«h­i³04æ’hxœi3ï¨(ÓL·†‹¶ËpŒ ƒÜÒ? :õdsÀ –3æÓ·Üjâ¬9—]8n¼&]I F£¼…ì–—Œ0v°LǐÅfÛ2TÖ’aµ˜N@ÖBSÏ^à´4-±°b×nÈÈœÆD=KdŒø…ÄÈK,›ÖR§fjü$^ÔÎ!„6^ s:Üun\ôkCÞò÷<—Lúl Í›G¹ÀPá¼Nc¡šÒ…ÙWͳœ±vÊáЄ×9‹P‰cEØ‘™›µŸP<×g1 º©Ø¬wiÁ^l5× I/';Ë+´Z‡ÓÄFÕp[Èð’ HÄ ó 9¬Dl4“é±Ï”V=^Hð;žLädÉa‚°Ë,#/Ž~²BÔÛ QãñQtIeórVB,ÏÂf‹4#Μc‹É3ZIÖ Œ¢¥·üxa‡Ãçè„jŠ[5 Ä!U?,3žÎ×…ðdÓ÷háŠA‰ìÄ4÷ÃÜZÃE{‰®+W\ZÍE[‰»µk»MÝ­`¢©†˜ÃV‹-f¢¡†¢a«eŠ%«Y¨©q%jâd,Ôq`) ¤¦…šˆ ¦E>0Ùb²t–Ÿ  ÷jsςҒKÈcø(é›;k(’#ôŒQ ™C> õ³M9óºÆµ¤çâ;uÀ)5>RÔ¸fÓ~Ȧ—’-$fe«"FâUˆÊwµPÏu w+"åÉó¨6s™Û9(À¨ù©hE°½†n`m~“@©›p!Vkhµ Á1šbEqqÊ@ºèl›2 –Yã%‘‚hÛ{a¶‡ÅÞM²¬çL34®Çl]®‹ŽØŒm'RÜe35æöˆ­Á­ cP9šeÁköo´L³Ì=p8]”‡B¶,šº|ɏdzXˆØk*ÇÚ{#ñ‰pã(€¶‡9ý'šÜ³½¯kƒ†Â’ëSOƒ•Å®H6+a¢µˆ‹Y¨b˜b+XˆÖ!°u!¢"µˆˆn2ˆ Å0Ä`Å Ô®c(ÓÜGº•Ä»Œ âWî%q.áÐÄ÷î%umÍ£+ÜQ,Vn¦-GphU¸¢X­&,Gt ·K¢ÅÅ·¥RÄÊÉbKn N­R2g$VµÕó Qr#–ÓZUÏð0ÎtÙÀœz ëöo“Îk¯n„T°"SÞ+³/…€½"ižãO%Í%&Δâ‘ËØ´IˆÓ°Ë‰ÞM3.™yçÁzit›`4C`k¢¼á!álÄï sÂ[×!¤l¾æo"ƒIÔ'@ªu)3›ô®“@Z à¾] üœ'‡4¸PÞkÁ-qÄH‰ÓÍBd´ÿ —¹°ÄA&ÊUC„öz‚‚RæŠtf¬>˜ÑidšEçÑL÷áý¡V±h§­c¿¥¨ƒ@g¼…Ýö^ÞËc.ž„æ“I[ ª+·zÐÒÚ,½Ð»¶€C›7jk$๖€Ž¾ÅÙpp¶ÍþéΤ ½ØÎŒq ñpæžÅ¥#Øâ49ÃÂK^MYV“,¶Éz_òæ:…;Õ«¦I3âJ£¤û5$7Èxün\â]Êe¯(Ÿ&Ž‹¶2<6Ćf× æ¢ƱqWı[(ÙÂŽç‚T7¨@ÈÉÍß‚ïÙ"&3TYlGށ†)†#5ŠA©^T2ÆÁ†)©†©†¤yGXÁ†©"†)©¼ÅV WS†#©]R–r‹q5ÕbâWþBh¯u+ªÅÄ×ü„nÑ^êkªÁj‰jeœWˆÕÕ`µDµ2Ì+Ä µDµµ5Ô{¤Þ0RF’H÷AÛ<ÊÁ§ ƈæ0Ñ£ê4 öÚµ[¬/1²€â<-¬šö²r×0o×w ´xÐÒË„ g01¬„åEM蛇Ã\6µE›‘fÙO k÷CºnÓ1`iîÒ² áÂ!ÑLÄÿ ³¬\õ*:M=Ç»c‹2[‰ØsÕLò\ŒK L^™üÄN\¶#» Ç\……ßïIœÉ$¸ÎñÍ®ÔHÇ Ûí/´>Li”„†g^$ 7NÍÑÑ2M2ªNg=k½Ð}Ÿl6‡ —JWˆ”ÞéT·+µ¦üÂFè¢Vs6ýÆ4»2+2IÝ9ô9®ÇGÙÇ1+Ä8;*Õ§ž½D*îÑWÚçá3Ma¤·ˆ¥t}š²Ü…Q+Æüµ8HíS”üxGéÁˆ¦Ël„éÈ 5 µÄƒ6äÜ(kIš¯S†fÖ&¸®×v|Äyˆ*禌Éù@7-®Ä[]ÎÖ¿ê`º…=:…žJVnݳvðÖKE¼‚ »mà ÷f®:Ë ™–4rð¡4` ܹçž~‹C=œ…¾Ïj|VDtK.ƒ"9 Ï ­–éXá³6WÒïIL-Ї Ç PK*\J9 pix/icon.svgnu[ PK*\?S-lib.phpnu[. /** * Callbacks. * * @package core_h5p * @copyright 2019 Bas Brands * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); use core_h5p\local\library\autoloader; /** * Serve the files from the core_h5p file areas. * * @package core_h5p * @category files * * @param stdClass $course the course object * @param stdClass $cm the course module object * @param stdClass $context the newmodule's context * @param string $filearea the name of the file area * @param array $args extra arguments (itemid, path) * @param bool $forcedownload whether or not force download * @param array $options additional options affecting the file serving * * @return bool Returns false if we don't find a file. */ function core_h5p_pluginfile($course, $cm, $context, string $filearea, array $args, bool $forcedownload, array $options = []): bool { global $DB; // Require classes from H5P third party library autoloader::register(); $filesettingsset = false; switch ($filearea) { default: return false; // Invalid file area. case \core_h5p\file_storage::LIBRARY_FILEAREA: if ($context->contextlevel != CONTEXT_SYSTEM) { return false; // Invalid context because the libraries are loaded always in the context system. } $itemid = null; // The files that can be delivered to this function are unfortunately out of our control. Some of the // references are embedded into the JavaScript of the files and we have no ability to inject an item id. // We also don't know the location of the item id when we do include it, so we look for the first numeric // value and try to serve that file. foreach ($args as $key => $value) { if (is_numeric($value)) { $itemid = $value; unset($args[$key]); break; } } if (!isset($itemid)) { // We didn't find an item id to use, so we fall back to retrieving the record using all the other // fields. The combination of component, filearea, filepath, and filename is enough for a unique // record. $filename = array_pop($args); $filepath = '/' . implode('/', $args) . '/'; $itemid = $DB->get_field('files', 'itemid', [ 'component' => \core_h5p\file_storage::COMPONENT, 'filearea' => \core_h5p\file_storage::LIBRARY_FILEAREA, 'filepath' => $filepath, 'filename' => $filename ]); $filesettingsset = true; } break; case \core_h5p\file_storage::CONTENT_FILEAREA: if ($context->contextlevel != CONTEXT_SYSTEM) { return false; // Invalid context because the content files are loaded always in the context system. } $itemid = array_shift($args); break; case \core_h5p\file_storage::CACHED_ASSETS_FILEAREA: case \core_h5p\file_storage::EXPORT_FILEAREA: case \core_h5p\file_storage::CSS_FILEAREA: $itemid = 0; break; } if (!$filesettingsset) { $filename = array_pop($args); $filepath = (!$args ? '/' : '/' . implode('/', $args) . '/'); } $fs = get_file_storage(); $file = $fs->get_file($context->id, \core_h5p\file_storage::COMPONENT, $filearea, $itemid, $filepath, $filename); if (!$file) { return false; // No such file. } send_stored_file($file, null, 0, $forcedownload, $options); return true; } PK*\BUclasses/external.phpnu[. namespace core_h5p; use core_external\external_api; use core_external\external_files; use core_external\external_function_parameters; use core_external\external_single_structure; use core_external\external_value; use core_external\external_warnings; /** * This is the external API for this component. * * @package core_h5p * @copyright 2019 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class external extends external_api { /** * get_trusted_h5p_file parameters. * * @since Moodle 3.8 * @return external_function_parameters */ public static function get_trusted_h5p_file_parameters() { return new external_function_parameters( [ 'url' => new external_value(PARAM_URL, 'H5P file url.', VALUE_REQUIRED), 'frame' => new external_value(PARAM_INT, 'The frame allow to show the bar options below the content', VALUE_DEFAULT, 0), 'export' => new external_value(PARAM_INT, 'The export allow to download the package', VALUE_DEFAULT, 0), 'embed' => new external_value(PARAM_INT, 'The embed allow to copy the code to your site', VALUE_DEFAULT, 0), 'copyright' => new external_value(PARAM_INT, 'The copyright option', VALUE_DEFAULT, 0) ] ); } /** * Return the H5P file trusted. * * The Mobile App needs to work with an H5P package which can trust. * And this H5P package is only trusted by the Mobile App once it's been processed * by the core checking the right caps, validating the H5P package * and doing any clean-up process involved. * * @since Moodle 3.8 * @param string $url H5P file url * @param int $frame The frame allow to show the bar options below the content * @param int $export The export allow to download the package * @param int $embed The embed allow to copy the code to your site * @param int $copyright The copyright option * @return array * @throws \moodle_exception */ public static function get_trusted_h5p_file(string $url, int $frame, int $export, int $embed, int $copyright) { $result = []; $warnings = []; $params = external_api::validate_parameters(self::get_trusted_h5p_file_parameters(), [ 'url' => $url, 'frame' => $frame, 'export' => $export, 'embed' => $embed, 'copyright' => $copyright ]); $url = $params['url']; $config = new \stdClass(); $config->frame = $params['frame']; $config->export = $params['export']; $config->embed = $params['embed']; $config->copyright = $params['copyright']; try { $h5pplayer = new player($url, $config); $messages = $h5pplayer->get_messages(); } catch (\moodle_exception $e) { $messages = (object) [ 'code' => $e->getCode(), ]; // To mantain the coherence between web coding error and Mobile coding errors. // We need to return the same message error to Mobile. // The 'out_al_local_url called on a non-local URL' error is provided by the \moodle_exception. // We have to translate to h5pinvalidurl which is the same coding error showed in web. if ($e->errorcode === 'codingerror' && $e->a === 'out_as_local_url called on a non-local URL') { $messages->exception = get_string('h5pinvalidurl', 'core_h5p'); } else { $messages->exception = $e->getMessage(); } } if (empty($messages->error) && empty($messages->exception)) { // Add H5P assets to the page. $h5pplayer->add_assets_to_page(); // Check if there is some error when adding assets to the page. $messages = $h5pplayer->get_messages(); if (empty($messages->error)) { $fileh5p = $h5pplayer->get_export_file(); $result[] = $fileh5p; } } if (!empty($messages->error)) { foreach ($messages->error as $error) { // We have to apply clean_param because warningcode is a PARAM_ALPHANUM. // And H5P has some error code like 'total-size-too-large'. $warnings[] = [ 'item' => $url, 'warningcode' => clean_param($error->code, PARAM_ALPHANUM), 'message' => $error->message ]; } } else if (!empty($messages->exception)) { $warnings[] = [ 'item' => $url, 'warningcode' => $messages->code, 'message' => $messages->exception ]; } return [ 'files' => $result, 'warnings' => $warnings ]; } /** * get_trusted_h5p_file return * * @since Moodle 3.8 * @return \core_external\external_description */ public static function get_trusted_h5p_file_returns() { return new external_single_structure( [ 'files' => new external_files('H5P file trusted.'), 'warnings' => new external_warnings() ] ); } } PK*\#classes/api.phpnu[. /** * Contains API class for the H5P area. * * @package core_h5p * @copyright 2020 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; use core\lock\lock_config; use Moodle\H5PCore; /** * Contains API class for the H5P area. * * @copyright 2020 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class api { /** * Delete a library and also all the libraries depending on it and the H5P contents using it. For the H5P content, only the * database entries in {h5p} are removed (the .h5p files are not removed in order to let users to deploy them again). * * @param factory $factory The H5P factory. * @param \stdClass $library The library to delete. */ public static function delete_library(factory $factory, \stdClass $library): void { global $DB; // Get the H5P contents using this library, to remove them from DB. The .h5p files won't be removed // so they will be displayed by the player next time a user with the proper permissions accesses it. $sql = 'SELECT DISTINCT hcl.h5pid FROM {h5p_contents_libraries} hcl WHERE hcl.libraryid = :libraryid'; $params = ['libraryid' => $library->id]; $h5pcontents = $DB->get_records_sql($sql, $params); foreach ($h5pcontents as $h5pcontent) { $factory->get_framework()->deleteContentData($h5pcontent->h5pid); } $fs = $factory->get_core()->fs; $framework = $factory->get_framework(); // Delete the library from the file system. $fs->delete_library(array('libraryId' => $library->id)); // Delete also the cache assets to rebuild them next time. $framework->deleteCachedAssets($library->id); // Remove library data from database. $DB->delete_records('h5p_library_dependencies', array('libraryid' => $library->id)); $DB->delete_records('h5p_libraries', array('id' => $library->id)); // Remove the library from the cache. $libscache = \cache::make('core', 'h5p_libraries'); $libarray = [ 'machineName' => $library->machinename, 'majorVersion' => $library->majorversion, 'minorVersion' => $library->minorversion, ]; $libstring = H5PCore::libraryToString($libarray); $librarykey = helper::get_cache_librarykey($libstring); $libscache->delete($librarykey); // Remove the libraries using this library. $requiredlibraries = self::get_dependent_libraries($library->id); foreach ($requiredlibraries as $requiredlibrary) { self::delete_library($factory, $requiredlibrary); } } /** * Get all the libraries using a defined library. * * @param int $libraryid The library to get its dependencies. * @return array List of libraryid with all the libraries required by a defined library. */ public static function get_dependent_libraries(int $libraryid): array { global $DB; $sql = 'SELECT * FROM {h5p_libraries} WHERE id IN (SELECT DISTINCT hl.id FROM {h5p_library_dependencies} hld JOIN {h5p_libraries} hl ON hl.id = hld.libraryid WHERE hld.requiredlibraryid = :libraryid)'; $params = ['libraryid' => $libraryid]; return $DB->get_records_sql($sql, $params); } /** * Get a library from an identifier. * * @param int $libraryid The library identifier. * @return \stdClass The library object having the library identifier defined. * @throws dml_exception A DML specific exception is thrown if the libraryid doesn't exist. */ public static function get_library(int $libraryid): \stdClass { global $DB; return $DB->get_record('h5p_libraries', ['id' => $libraryid], '*', MUST_EXIST); } /** * Returns a library as an object with properties that correspond to the fetched row's field names. * * @param array $params An associative array with the values of the machinename, majorversion and minorversion fields. * @param bool $configurable A library that has semantics so it can be configured in the editor. * @param string $fields Library attributes to retrieve. * * @return \stdClass|null An object with one attribute for each field name in $fields param. */ public static function get_library_details(array $params, bool $configurable, string $fields = ''): ?\stdClass { global $DB; $select = "machinename = :machinename AND majorversion = :majorversion AND minorversion = :minorversion"; if ($configurable) { $select .= " AND semantics IS NOT NULL"; } $fields = $fields ?: '*'; $record = $DB->get_record_select('h5p_libraries', $select, $params, $fields); return $record ?: null; } /** * Get all the H5P content type libraries versions. * * @param string|null $fields Library fields to return. * * @return array An array with an object for each content type library installed. */ public static function get_contenttype_libraries(?string $fields = ''): array { global $DB; $libraries = []; $fields = $fields ?: '*'; $select = "runnable = :runnable AND semantics IS NOT NULL"; $params = ['runnable' => 1]; $sort = 'title, majorversion DESC, minorversion DESC'; $records = $DB->get_records_select('h5p_libraries', $select, $params, $sort, $fields); $added = []; foreach ($records as $library) { // Remove unique index. unset($library->id); // Convert snakes to camels. $library->majorVersion = (int) $library->majorversion; unset($library->major_version); $library->minorVersion = (int) $library->minorversion; unset($library->minorversion); $library->metadataSettings = json_decode($library->metadatasettings ?? ''); // If we already add this library means that it is an old version,as the previous query was sorted by version. if (isset($added[$library->name])) { $library->isOld = true; } else { $added[$library->name] = true; } // Add new library. $libraries[] = $library; } return $libraries; } /** * Get the H5P DB instance id for a H5P pluginfile URL. If it doesn't exist, it's not created. * * @param string $url H5P pluginfile URL. * @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions * @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they * might be controlled before calling this method. * * @return array of [file, stdClass|false]: * - file local file for this $url. * - stdClass is an H5P object or false if there isn't any H5P with this URL. */ public static function get_content_from_pluginfile_url(string $url, bool $preventredirect = true, bool $skipcapcheck = false): array { global $DB; // Deconstruct the URL and get the pathname associated. if ($skipcapcheck || self::can_access_pluginfile_hash($url, $preventredirect)) { $pathnamehash = self::get_pluginfile_hash($url); } if (!$pathnamehash) { return [false, false]; } // Get the file. $fs = get_file_storage(); $file = $fs->get_file_by_hash($pathnamehash); if (!$file) { return [false, false]; } $h5p = $DB->get_record('h5p', ['pathnamehash' => $pathnamehash]); return [$file, $h5p]; } /** * Get the original file and H5P DB instance for a given H5P pluginfile URL. If it doesn't exist, it's not created. * If the file has been added as a reference, this method will return the original linked file. * * @param string $url H5P pluginfile URL. * @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions. * @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they * might be controlled before calling this method. * * @return array of [\stored_file|false, \stdClass|false, \stored_file|false]: * - \stored_file: original local file for the given url (if it has been added as a reference, this method * will return the linked file) or false if there isn't any H5P file with this URL. * - \stdClass: an H5P object or false if there isn't any H5P with this URL. * - \stored_file: file associated to the given url (if it's different from original) or false when both files * (original and file) are the same. * @since Moodle 4.0 */ public static function get_original_content_from_pluginfile_url(string $url, bool $preventredirect = true, bool $skipcapcheck = false): array { $file = false; list($originalfile, $h5p) = self::get_content_from_pluginfile_url($url, $preventredirect, $skipcapcheck); if ($originalfile) { if ($reference = $originalfile->get_reference()) { $file = $originalfile; // If the file has been added as a reference to any other file, get it. $fs = new \file_storage(); $referenced = \file_storage::unpack_reference($reference); $originalfile = $fs->get_file( $referenced['contextid'], $referenced['component'], $referenced['filearea'], $referenced['itemid'], $referenced['filepath'], $referenced['filename'] ); $h5p = self::get_content_from_pathnamehash($originalfile->get_pathnamehash()); if (empty($h5p)) { $h5p = false; } } } return [$originalfile, $h5p, $file]; } /** * Check if the user can edit an H5P file. It will return true in the following situations: * - The user is the author of the file. * - The component is different from user (i.e. private files). * - If the component is contentbank, the user can edit this file (calling the ContentBank API). * - If the component is mod_xxx or block_xxx, the user has the addinstance capability. * - If the component implements the can_edit_content in the h5p\canedit class and the callback to this method returns true. * * @param \stored_file $file The H5P file to check. * * @return boolean Whether the user can edit or not the given file. * @since Moodle 4.0 */ public static function can_edit_content(\stored_file $file): bool { global $USER; list($type, $component) = \core_component::normalize_component($file->get_component()); // Private files. $currentuserisauthor = $file->get_userid() == $USER->id; $isuserfile = $component === 'user'; if ($currentuserisauthor && $isuserfile) { // The user can edit the content because it's a private user file and she is the owner. return true; } // Check if the plugin where the file belongs implements the custom can_edit_content method and call it if that's the case. $classname = '\\' . $file->get_component() . '\\h5p\\canedit'; $methodname = 'can_edit_content'; if (method_exists($classname, $methodname)) { return $classname::{$methodname}($file); } // For mod/block files, check if the user has the addinstance capability of the component where the file belongs. if ($type === 'mod' || $type === 'block') { // For any other component, check whether the user can add/edit them. $context = \context::instance_by_id($file->get_contextid()); $plugins = \core_component::get_plugin_list($type); $isvalid = array_key_exists($component, $plugins); if ($isvalid && has_capability("$type/$component:addinstance", $context)) { // The user can edit the content because she has the capability for creating instances where the file belongs. return true; } } // For contentbank files, use the API to check if the user has access. if ($component == 'contentbank') { $cb = new \core_contentbank\contentbank(); $content = $cb->get_content_from_id($file->get_itemid()); $contenttype = $content->get_content_type_instance(); if ($contenttype instanceof \contenttype_h5p\contenttype) { // Only H5P contenttypes should be considered here. if ($contenttype->can_edit($content)) { // The user has permissions to edit the H5P in the content bank. return true; } } } return false; } /** * Create, if it doesn't exist, the H5P DB instance id for a H5P pluginfile URL. If it exists: * - If the content is not the same, remove the existing content and re-deploy the H5P content again. * - If the content is the same, returns the H5P identifier. * * @param string $url H5P pluginfile URL. * @param stdClass $config Configuration for H5P buttons. * @param factory $factory The \core_h5p\factory object * @param stdClass $messages The error, exception and info messages, raised while preparing and running an H5P content. * @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions * @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they * might be controlled before calling this method. * * @return array of [file, h5pid]: * - file local file for this $url. * - h5pid is the H5P identifier or false if there isn't any H5P with this URL. */ public static function create_content_from_pluginfile_url(string $url, \stdClass $config, factory $factory, \stdClass &$messages, bool $preventredirect = true, bool $skipcapcheck = false): array { global $USER; $core = $factory->get_core(); list($file, $h5p) = self::get_content_from_pluginfile_url($url, $preventredirect, $skipcapcheck); if (!$file) { $core->h5pF->setErrorMessage(get_string('h5pfilenotfound', 'core_h5p')); return [false, false]; } $contenthash = $file->get_contenthash(); if ($h5p && $h5p->contenthash != $contenthash) { // The content exists and it is different from the one deployed previously. The existing one should be removed before // deploying the new version. self::delete_content($h5p, $factory); $h5p = false; } $context = \context::instance_by_id($file->get_contextid()); if ($h5p) { // The H5P content has been deployed previously. // If the main library for this H5P content is disabled, the content won't be displayed. $mainlibrary = (object) ['id' => $h5p->mainlibraryid]; if (!self::is_library_enabled($mainlibrary)) { $core->h5pF->setErrorMessage(get_string('mainlibrarydisabled', 'core_h5p')); return [$file, false]; } else { $displayoptions = helper::get_display_options($core, $config); // Check if the user can set the displayoptions. if ($displayoptions != $h5p->displayoptions && has_capability('moodle/h5p:setdisplayoptions', $context)) { // If displayoptions has changed and user has permission to modify it, update this information in DB. $core->h5pF->updateContentFields($h5p->id, ['displayoptions' => $displayoptions]); } return [$file, $h5p->id]; } } else { // The H5P content hasn't been deployed previously. // Check if the user uploading the H5P content is "trustable". If the file hasn't been uploaded by a user with this // capability, the content won't be deployed and an error message will be displayed. if (!helper::can_deploy_package($file)) { $core->h5pF->setErrorMessage(get_string('nopermissiontodeploy', 'core_h5p')); return [$file, false]; } // The H5P content can be only deployed if the author of the .h5p file can update libraries or if all the // content-type libraries exist, to avoid users without the h5p:updatelibraries capability upload malicious content. $onlyupdatelibs = !helper::can_update_library($file); // Start lock to prevent synchronous access to save the same H5P. $lockfactory = lock_config::get_lock_factory('core_h5p'); $lockkey = 'core_h5p_' . $file->get_pathnamehash(); if ($lock = $lockfactory->get_lock($lockkey, 10)) { try { // Validate and store the H5P content before displaying it. $h5pid = helper::save_h5p($factory, $file, $config, $onlyupdatelibs, false); } finally { $lock->release(); } } else { $core->h5pF->setErrorMessage(get_string('lockh5pdeploy', 'core_h5p')); return [$file, false]; }; if (!$h5pid && $file->get_userid() != $USER->id && has_capability('moodle/h5p:updatelibraries', $context)) { // The user has permission to update libraries but the package has been uploaded by a different // user without this permission. Check if there is some missing required library error. $missingliberror = false; $messages = helper::get_messages($messages, $factory); if (!empty($messages->error)) { foreach ($messages->error as $error) { if ($error->code == 'missing-required-library') { $missingliberror = true; break; } } } if ($missingliberror) { // The message about the permissions to upload libraries should be removed. $infomsg = "Note that the libraries may exist in the file you uploaded, but you're not allowed to upload " . "new libraries. Contact the site administrator about this."; if (($key = array_search($infomsg, $messages->info)) !== false) { unset($messages->info[$key]); } // No library will be installed and an error will be displayed, because this content is not trustable. $core->h5pF->setInfoMessage(get_string('notrustablefile', 'core_h5p')); } return [$file, false]; } return [$file, $h5pid]; } } /** * Delete an H5P package. * * @param stdClass $content The H5P package to delete with, at least content['id]. * @param factory $factory The \core_h5p\factory object */ public static function delete_content(\stdClass $content, factory $factory): void { $h5pstorage = $factory->get_storage(); // Add an empty slug to the content if it's not defined, because the H5P library requires this field exists. // It's not used when deleting a package, so the real slug value is not required at this point. $content->slug = $content->slug ?? ''; $h5pstorage->deletePackage( (array) $content); } /** * Delete an H5P package deployed from the defined $url. * * @param string $url pluginfile URL of the H5P package to delete. * @param factory $factory The \core_h5p\factory object */ public static function delete_content_from_pluginfile_url(string $url, factory $factory): void { global $DB; // Get the H5P to delete. $pathnamehash = self::get_pluginfile_hash($url); $h5p = $DB->get_record('h5p', ['pathnamehash' => $pathnamehash]); if ($h5p) { self::delete_content($h5p, $factory); } } /** * If user can access pathnamehash from an H5P internal URL. * * @param string $url H5P pluginfile URL poiting to an H5P file. * @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions * * @return bool if user can access pluginfile hash. * @throws \moodle_exception * @throws \coding_exception * @throws \require_login_exception */ protected static function can_access_pluginfile_hash(string $url, bool $preventredirect = true): bool { global $USER, $CFG; // Decode the URL before start processing it. $url = new \moodle_url(urldecode($url)); // Remove params from the URL (such as the 'forcedownload=1'), to avoid errors. $url->remove_params(array_keys($url->params())); $path = $url->out_as_local_url(); // We only need the slasharguments. $path = substr($path, strpos($path, '.php/') + 5); $parts = explode('/', $path); // If the request is made by tokenpluginfile.php we need to avoid userprivateaccesskey. if (strpos($url, '/tokenpluginfile.php')) { array_shift($parts); } // Get the contextid, component and filearea. $contextid = array_shift($parts); $component = array_shift($parts); $filearea = array_shift($parts); // Get the context. try { list($context, $course, $cm) = get_context_info_array($contextid); } catch (\moodle_exception $e) { throw new \moodle_exception('invalidcontextid', 'core_h5p'); } // For CONTEXT_USER, such as the private files, raise an exception if the owner of the file is not the current user. if ($context->contextlevel == CONTEXT_USER && $USER->id !== $context->instanceid) { throw new \moodle_exception('h5pprivatefile', 'core_h5p'); } if (!is_siteadmin($USER)) { // For CONTEXT_COURSECAT No login necessary - unless login forced everywhere. if ($context->contextlevel == CONTEXT_COURSECAT) { if ($CFG->forcelogin) { require_login(null, true, null, false, true); } } // For CONTEXT_BLOCK. if ($context->contextlevel == CONTEXT_BLOCK) { if ($context->get_course_context(false)) { // If block is in course context, then check if user has capability to access course. require_course_login($course, true, null, false, true); } else if ($CFG->forcelogin) { // No login necessary - unless login forced everywhere. require_login(null, true, null, false, true); } else { // Get parent context and see if user have proper permission. $parentcontext = $context->get_parent_context(); if ($parentcontext->contextlevel === CONTEXT_COURSECAT) { // Check if category is visible and user can view this category. if (!\core_course_category::get($parentcontext->instanceid, IGNORE_MISSING)) { send_file_not_found(); } } else if ($parentcontext->contextlevel === CONTEXT_USER && $parentcontext->instanceid != $USER->id) { // The block is in the context of a user, it is only visible to the user who it belongs to. send_file_not_found(); } if ($filearea !== 'content') { send_file_not_found(); } } } // For CONTEXT_MODULE and CONTEXT_COURSE check if the user is enrolled in the course. // And for CONTEXT_MODULE has permissions view this .h5p file. if ($context->contextlevel == CONTEXT_MODULE || $context->contextlevel == CONTEXT_COURSE) { // Require login to the course first (without login to the module). require_course_login($course, true, null, !$preventredirect, $preventredirect); // Now check if module is available OR it is restricted but the intro is shown on the course page. if ($context->contextlevel == CONTEXT_MODULE) { $cminfo = \cm_info::create($cm); if (!$cminfo->uservisible) { if (!$cm->showdescription || !$cminfo->is_visible_on_course_page()) { // Module intro is not visible on the course page and module is not available, show access error. require_course_login($course, true, $cminfo, !$preventredirect, $preventredirect); } } } } } return true; } /** * Get the pathnamehash from an H5P internal URL. * * @param string $url H5P pluginfile URL poiting to an H5P file. * * @return string|false pathnamehash for the file in the internal URL. * * @throws \moodle_exception */ protected static function get_pluginfile_hash(string $url) { // Decode the URL before start processing it. $url = new \moodle_url(urldecode($url)); // Remove params from the URL (such as the 'forcedownload=1'), to avoid errors. $url->remove_params(array_keys($url->params())); $path = $url->out_as_local_url(); // We only need the slasharguments. $path = substr($path, strpos($path, '.php/') + 5); $parts = explode('/', $path); $filename = array_pop($parts); // If the request is made by tokenpluginfile.php we need to avoid userprivateaccesskey. if (strpos($url, '/tokenpluginfile.php')) { array_shift($parts); } // Get the contextid, component and filearea. $contextid = array_shift($parts); $component = array_shift($parts); $filearea = array_shift($parts); // Ignore draft files, because they are considered temporary files, so shouldn't be displayed. if ($filearea == 'draft') { return false; } // Get the context. try { list($context, $course, $cm) = get_context_info_array($contextid); } catch (\moodle_exception $e) { throw new \moodle_exception('invalidcontextid', 'core_h5p'); } // Some components, such as mod_page or mod_resource, add the revision to the URL to prevent caching problems. // So the URL contains this revision number as itemid but a 0 is always stored in the files table. // In order to get the proper hash, a callback should be done (looking for those exceptions). $pathdata = null; if ($context->contextlevel == CONTEXT_MODULE || $context->contextlevel == CONTEXT_BLOCK) { $pathdata = component_callback($component, 'get_path_from_pluginfile', [$filearea, $parts], null); } if (null === $pathdata) { // Look for the components and fileareas which have empty itemid defined in xxx_pluginfile. $hasnullitemid = false; $hasnullitemid = $hasnullitemid || ($component === 'user' && ($filearea === 'private' || $filearea === 'profile')); $hasnullitemid = $hasnullitemid || (substr($component, 0, 4) === 'mod_' && $filearea === 'intro'); $hasnullitemid = $hasnullitemid || ($component === 'course' && ($filearea === 'summary' || $filearea === 'overviewfiles')); $hasnullitemid = $hasnullitemid || ($component === 'coursecat' && $filearea === 'description'); $hasnullitemid = $hasnullitemid || ($component === 'backup' && ($filearea === 'course' || $filearea === 'activity' || $filearea === 'automated')); if ($hasnullitemid) { $itemid = 0; } else { $itemid = array_shift($parts); } if (empty($parts)) { $filepath = '/'; } else { $filepath = '/' . implode('/', $parts) . '/'; } } else { // The itemid and filepath have been returned by the component callback. [ 'itemid' => $itemid, 'filepath' => $filepath, ] = $pathdata; } $fs = get_file_storage(); $pathnamehash = $fs->get_pathname_hash($contextid, $component, $filearea, $itemid, $filepath, $filename); return $pathnamehash; } /** * Returns the H5P content object corresponding to an H5P content file. * * @param string $pathnamehash The pathnamehash of the file associated to an H5P content. * * @return null|\stdClass H5P content object or null if not found. */ public static function get_content_from_pathnamehash(string $pathnamehash): ?\stdClass { global $DB; $h5p = $DB->get_record('h5p', ['pathnamehash' => $pathnamehash]); return ($h5p) ? $h5p : null; } /** * Return the H5P export information file when the file has been deployed. * Otherwise, return null if H5P file: * i) has not been deployed. * ii) has changed the content. * * The information returned will be: * - filename, filepath, mimetype, filesize, timemodified and fileurl. * * @param int $contextid ContextId of the H5P activity. * @param factory $factory The \core_h5p\factory object. * @param string $component component * @param string $filearea file area * @return array|null Return file info otherwise null. */ public static function get_export_info_from_context_id(int $contextid, factory $factory, string $component, string $filearea): ?array { $core = $factory->get_core(); $fs = get_file_storage(); $files = $fs->get_area_files($contextid, $component, $filearea, 0, 'id', false); $file = reset($files); if ($h5p = self::get_content_from_pathnamehash($file->get_pathnamehash())) { if ($h5p->contenthash == $file->get_contenthash()) { $content = $core->loadContent($h5p->id); $slug = $content['slug'] ? $content['slug'] . '-' : ''; $filename = "{$slug}{$content['id']}.h5p"; $deployedfile = helper::get_export_info($filename, null, $factory); return $deployedfile; } } return null; } /** * Enable or disable a library. * * @param int $libraryid The id of the library to enable/disable. * @param bool $isenabled True if the library should be enabled; false otherwise. */ public static function set_library_enabled(int $libraryid, bool $isenabled): void { global $DB; $library = $DB->get_record('h5p_libraries', ['id' => $libraryid], '*', MUST_EXIST); if ($library->runnable) { // For now, only runnable libraries can be enabled/disabled. $record = [ 'id' => $libraryid, 'enabled' => $isenabled, ]; $DB->update_record('h5p_libraries', $record); } } /** * Check whether a library is enabled or not. When machinename is passed, it will return false if any of the versions * for this machinename is disabled. * If the library doesn't exist, it will return true. * * @param \stdClass $librarydata Supported fields for library: 'id' and 'machichename'. * @return bool * @throws \moodle_exception */ public static function is_library_enabled(\stdClass $librarydata): bool { global $DB; $params = []; if (property_exists($librarydata, 'machinename')) { $params['machinename'] = $librarydata->machinename; } if (property_exists($librarydata, 'id')) { $params['id'] = $librarydata->id; } if (empty($params)) { throw new \moodle_exception("Missing 'machinename' or 'id' in librarydata parameter"); } $libraries = $DB->get_records('h5p_libraries', $params); // If any of the libraries with these values have been disabled, return false. foreach ($libraries as $id => $library) { if (!$library->enabled) { return false; } } return true; } /** * Check whether an H5P package is valid or not. * * @param \stored_file $file The file with the H5P content. * @param bool $onlyupdatelibs Whether new libraries can be installed or only the existing ones can be updated * @param bool $skipcontent Should the content be skipped (so only the libraries will be saved)? * @param factory|null $factory The \core_h5p\factory object * @param bool $deletefiletree Should the temporary files be deleted before returning? * @return bool True if the H5P file is valid (expected format, valid libraries...); false otherwise. */ public static function is_valid_package(\stored_file $file, bool $onlyupdatelibs, bool $skipcontent = false, ?factory $factory = null, bool $deletefiletree = true): bool { // This may take a long time. \core_php_time_limit::raise(); $isvalid = false; if (empty($factory)) { $factory = new factory(); } $core = $factory->get_core(); $h5pvalidator = $factory->get_validator(); // Set the H5P file path. $core->h5pF->set_file($file); $path = $core->fs->getTmpPath(); $core->h5pF->getUploadedH5pFolderPath($path); // Add manually the extension to the file to avoid the validation fails. $path .= '.h5p'; $core->h5pF->getUploadedH5pPath($path); // Copy the .h5p file to the temporary folder. $file->copy_content_to($path); if ($h5pvalidator->isValidPackage($skipcontent, $onlyupdatelibs)) { if ($skipcontent) { $isvalid = true; } else if (!empty($h5pvalidator->h5pC->mainJsonData['mainLibrary'])) { $mainlibrary = (object) ['machinename' => $h5pvalidator->h5pC->mainJsonData['mainLibrary']]; if (self::is_library_enabled($mainlibrary)) { $isvalid = true; } else { // If the main library of the package is disabled, the H5P content will be considered invalid. $core->h5pF->setErrorMessage(get_string('mainlibrarydisabled', 'core_h5p')); } } } if ($deletefiletree) { // Remove temp content folder. H5PCore::deleteFileTree($path); } return $isvalid; } } PK*\XXXXclasses/player.phpnu[. /** * H5P player class. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; defined('MOODLE_INTERNAL') || die(); use core_h5p\local\library\autoloader; use core_xapi\handler; use core_xapi\local\state; use core_xapi\local\statement\item_activity; use core_xapi\local\statement\item_agent; use core_xapi\xapi_exception; /** * H5P player class, for displaying any local H5P content. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class player { /** * @var string The local H5P URL containing the .h5p file to display. */ private $url; /** * @var core The H5PCore object. */ private $core; /** * @var int H5P DB id. */ private $h5pid; /** * @var array JavaScript requirements for this H5P. */ private $jsrequires = []; /** * @var array CSS requirements for this H5P. */ private $cssrequires = []; /** * @var array H5P content to display. */ private $content; /** * @var string optional component name to send xAPI statements. */ private $component; /** * @var string Type of embed object, div or iframe. */ private $embedtype; /** * @var context The context object where the .h5p belongs. */ private $context; /** * @var factory The \core_h5p\factory object. */ private $factory; /** * @var stdClass The error, exception and info messages, raised while preparing and running the player. */ private $messages; /** * @var bool Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions. */ private $preventredirect; /** * Inits the H5P player for rendering the content. * * @param string $url Local URL of the H5P file to display. * @param \stdClass $config Configuration for H5P buttons. * @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions * @param string $component optional moodle component to sent xAPI tracking * @param bool $skipcapcheck Whether capabilities should be checked or not to get the pluginfile URL because sometimes they * might be controlled before calling this method. */ public function __construct(string $url, \stdClass $config, bool $preventredirect = true, string $component = '', bool $skipcapcheck = false) { if (empty($url)) { throw new \moodle_exception('h5pinvalidurl', 'core_h5p'); } $this->url = new \moodle_url($url); $this->preventredirect = $preventredirect; $this->factory = new \core_h5p\factory(); $this->messages = new \stdClass(); $this->component = $component; // Create \core_h5p\core instance. $this->core = $this->factory->get_core(); // Get the H5P identifier linked to this URL. list($file, $this->h5pid) = api::create_content_from_pluginfile_url( $url, $config, $this->factory, $this->messages, $this->preventredirect, $skipcapcheck ); if ($file) { $this->context = \context::instance_by_id($file->get_contextid()); if ($this->h5pid) { // Load the content of the H5P content associated to this $url. $this->content = $this->core->loadContent($this->h5pid); // Get the embedtype to use for displaying the H5P content. $this->embedtype = core::determineEmbedType($this->content['embedType'], $this->content['library']['embedTypes']); } } } /** * Get the encoded URL for embeding this H5P content. * * @param string $url Local URL of the H5P file to display. * @param \stdClass $config Configuration for H5P buttons. * @param bool $preventredirect Set to true in scripts that can not redirect (CLI, RSS feeds, etc.), throws exceptions * @param string $component optional moodle component to sent xAPI tracking * @param bool $displayedit Whether the edit button should be displayed below the H5P content. * @param \action_link[] $extraactions Extra actions to display above the H5P content. * * @return string The embedable code to display a H5P file. */ public static function display( string $url, \stdClass $config, bool $preventredirect = true, string $component = '', bool $displayedit = false, array $extraactions = [], ): string { global $OUTPUT, $CFG; $params = [ 'url' => $url, 'preventredirect' => $preventredirect, 'component' => $component, ]; $optparams = ['frame', 'export', 'embed', 'copyright']; foreach ($optparams as $optparam) { if (!empty($config->$optparam)) { $params[$optparam] = $config->$optparam; } } $fileurl = new \moodle_url('/h5p/embed.php', $params); $template = new \stdClass(); $template->embedurl = $fileurl->out(false); if ($displayedit) { list($originalfile, $h5p) = api::get_original_content_from_pluginfile_url($url, $preventredirect, true); if ($originalfile) { // Check if the user can edit this content. if (api::can_edit_content($originalfile)) { $template->editurl = (new \moodle_url('/h5p/edit.php', ['url' => $url]))->out(false); } } } $template->extraactions = []; foreach ($extraactions as $action) { $template->extraactions[] = $action->export_for_template($OUTPUT); } $result = $OUTPUT->render_from_template('core_h5p/h5pembed', $template); $result .= self::get_resize_code(); return $result; } /** * Get the error messages stored in our H5P framework. * * @return stdClass with framework error messages. */ public function get_messages(): \stdClass { return helper::get_messages($this->messages, $this->factory); } /** * Create the H5PIntegration variable that will be included in the page. This variable is used as the * main H5P config variable. */ public function add_assets_to_page() { global $PAGE, $USER; $cid = $this->get_cid(); $systemcontext = \context_system::instance(); $disable = array_key_exists('disable', $this->content) ? $this->content['disable'] : core::DISABLE_NONE; $displayoptions = $this->core->getDisplayOptionsForView($disable, $this->h5pid); $contenturl = \moodle_url::make_pluginfile_url($systemcontext->id, \core_h5p\file_storage::COMPONENT, \core_h5p\file_storage::CONTENT_FILEAREA, $this->h5pid, null, null); $exporturl = $this->get_export_settings($displayoptions[ core::DISPLAY_OPTION_DOWNLOAD ]); $xapiobject = item_activity::create_from_id($this->context->id); $contentsettings = [ 'library' => core::libraryToString($this->content['library']), 'fullScreen' => $this->content['library']['fullscreen'], 'exportUrl' => ($exporturl instanceof \moodle_url) ? $exporturl->out(false) : '', 'embedCode' => $this->get_embed_code($this->url->out(), $displayoptions[ core::DISPLAY_OPTION_EMBED ]), 'resizeCode' => self::get_resize_code(), 'title' => $this->content['slug'], 'displayOptions' => $displayoptions, 'url' => $xapiobject->get_data()->id, 'contentUrl' => $contenturl->out(), 'metadata' => $this->content['metadata'], 'contentUserData' => [0 => ['state' => $this->get_state_data($xapiobject)]], ]; // Get the core H5P assets, needed by the H5P classes to render the H5P content. $settings = $this->get_assets(); $settings['contents'][$cid] = array_merge($settings['contents'][$cid], $contentsettings); // Print JavaScript settings to page. $PAGE->requires->data_for_js('H5PIntegration', $settings, true); } /** * Get the stored xAPI state to use as user data. * * @param item_activity $xapiobject * @return string The state data to pass to the player frontend */ private function get_state_data(item_activity $xapiobject): string { global $USER; // Initialize the H5P content with the saved state (if it's enabled and the user has some stored state). $emptystatedata = '{}'; $savestate = (bool) get_config($this->component, 'enablesavestate'); if (!$savestate) { return $emptystatedata; } $xapihandler = handler::create($this->component); if (!$xapihandler) { return $emptystatedata; } // The component implements the xAPI handler, so the state can be loaded. $state = new state( item_agent::create_from_user($USER), $xapiobject, 'state', null, null ); try { $state = $xapihandler->load_state($state); if (!$state) { // Check if the state has been restored from a backup for the current user. $state = new state( item_agent::create_from_user($USER), $xapiobject, 'restored', null, null ); $state = $xapihandler->load_state($state); if ($state && !is_null($state->get_state_data())) { // A restored state has been found. It will be replaced with one with the proper stateid and statedata. $xapihandler->delete_state($state); $state = new state( item_agent::create_from_user($USER), $xapiobject, 'state', $state->jsonSerialize(), null ); $xapihandler->save_state($state); } } if (!$state) { return $emptystatedata; } if (is_null($state->get_state_data())) { // The state content should be reset because, for instance, the content has changed. return 'RESET'; } $statedata = $state->jsonSerialize(); if (is_null($statedata)) { return $emptystatedata; } if (property_exists($statedata, 'h5p')) { // As the H5P state doesn't always use JSON, we have added this h5p object to jsonize it. return $statedata->h5p; } } catch (xapi_exception $exception) { return $emptystatedata; } return $emptystatedata; } /** * Outputs H5P wrapper HTML. * * @return string The HTML code to display this H5P content. */ public function output(): string { global $OUTPUT, $USER; $template = new \stdClass(); $template->h5pid = $this->h5pid; if ($this->embedtype === 'div') { $h5phtml = $OUTPUT->render_from_template('core_h5p/h5pdiv', $template); } else { $h5phtml = $OUTPUT->render_from_template('core_h5p/h5piframe', $template); } // Trigger capability_assigned event. \core_h5p\event\h5p_viewed::create([ 'objectid' => $this->h5pid, 'userid' => $USER->id, 'context' => $this->get_context(), 'other' => [ 'url' => $this->url->out(), 'time' => time() ] ])->trigger(); return $h5phtml; } /** * Get the title of the H5P content to display. * * @return string the title */ public function get_title(): string { return $this->content['title']; } /** * Get the context where the .h5p file belongs. * * @return context The context. */ public function get_context(): \context { return $this->context; } /** * Delete an H5P package. * * @param stdClass $content The H5P package to delete. */ private function delete_h5p(\stdClass $content) { $h5pstorage = $this->factory->get_storage(); // Add an empty slug to the content if it's not defined, because the H5P library requires this field exists. // It's not used when deleting a package, so the real slug value is not required at this point. $content->slug = $content->slug ?? ''; $h5pstorage->deletePackage( (array) $content); } /** * Export path for settings * * @param bool $downloadenabled Whether the option to export the H5P content is enabled. * * @return \moodle_url|null The URL of the exported file. */ private function get_export_settings(bool $downloadenabled): ?\moodle_url { if (!$downloadenabled) { return null; } $systemcontext = \context_system::instance(); $slug = $this->content['slug'] ? $this->content['slug'] . '-' : ''; $filename = "{$slug}{$this->content['id']}.h5p"; // We have to build the right URL. // Depending the request was made through webservice/pluginfile.php or pluginfile.php. if (strpos($this->url, '/webservice/pluginfile.php')) { $url = \moodle_url::make_webservice_pluginfile_url( $systemcontext->id, \core_h5p\file_storage::COMPONENT, \core_h5p\file_storage::EXPORT_FILEAREA, '', '', $filename ); } else { // If the request is made by tokenpluginfile.php we need to indicates to generate a token for current user. $includetoken = false; if (strpos($this->url, '/tokenpluginfile.php')) { $includetoken = true; } $url = \moodle_url::make_pluginfile_url( $systemcontext->id, \core_h5p\file_storage::COMPONENT, \core_h5p\file_storage::EXPORT_FILEAREA, '', '', $filename, false, $includetoken ); } // Get the required info from the export file to be able to get the export file by third apps. $file = helper::get_export_info($filename, $url); if ($file) { $url->param('modified', $file['timemodified']); } return $url; } /** * Get the identifier for the H5P content, to be used in the arrays as index. * * @return string The identifier. */ private function get_cid(): string { return 'cid-' . $this->h5pid; } /** * Get the core H5P assets, including all core H5P JavaScript and CSS. * * @return Array core H5P assets. */ private function get_assets(): array { // Get core assets. $settings = helper::get_core_assets($this->component); // Added here because in the helper we don't have the h5p content id. $settings['moodleLibraryPaths'] = $this->core->get_dependency_roots($this->h5pid); // Add also the Moodle component where the results will be tracked. $settings['moodleComponent'] = $this->component; if (!empty($settings['moodleComponent'])) { $settings['reportingIsEnabled'] = true; } $cid = $this->get_cid(); // The filterParameters function should be called before getting the dependencyfiles because it rebuild content // dependency cache and export file. $settings['contents'][$cid]['jsonContent'] = $this->get_filtered_parameters(); $files = $this->get_dependency_files(); if ($this->embedtype === 'div') { $systemcontext = \context_system::instance(); $h5ppath = "/pluginfile.php/{$systemcontext->id}/core_h5p"; // Schedule JavaScripts for loading through Moodle. foreach ($files['scripts'] as $script) { $url = $script->path . $script->version; // Add URL prefix if not external. $isexternal = strpos($script->path, '://'); if ($isexternal === false) { $url = $h5ppath . $url; } $settings['loadedJs'][] = $url; $this->jsrequires[] = new \moodle_url($isexternal ? $url : $CFG->wwwroot . $url); } // Schedule stylesheets for loading through Moodle. foreach ($files['styles'] as $style) { $url = $style->path . $style->version; // Add URL prefix if not external. $isexternal = strpos($style->path, '://'); if ($isexternal === false) { $url = $h5ppath . $url; } $settings['loadedCss'][] = $url; $this->cssrequires[] = new \moodle_url($isexternal ? $url : $CFG->wwwroot . $url); } } else { // JavaScripts and stylesheets will be loaded through h5p.js. $settings['contents'][$cid]['scripts'] = $this->core->getAssetsUrls($files['scripts']); $settings['contents'][$cid]['styles'] = $this->core->getAssetsUrls($files['styles']); } return $settings; } /** * Get filtered parameters, modifying them by the renderer if the theme implements the h5p_alter_filtered_parameters function. * * @return string Filtered parameters. */ private function get_filtered_parameters(): string { global $PAGE; $safeparams = $this->core->filterParameters($this->content); $decodedparams = json_decode($safeparams); $h5poutput = $PAGE->get_renderer('core_h5p'); $h5poutput->h5p_alter_filtered_parameters( $decodedparams, $this->content['library']['name'], $this->content['library']['majorVersion'], $this->content['library']['minorVersion'] ); $safeparams = json_encode($decodedparams); return $safeparams; } /** * Finds library dependencies of view * * @return array Files that the view has dependencies to */ private function get_dependency_files(): array { global $PAGE; $preloadeddeps = $this->core->loadContentDependencies($this->h5pid, 'preloaded'); $files = $this->core->getDependenciesFiles($preloadeddeps); // Add additional asset files if required. $h5poutput = $PAGE->get_renderer('core_h5p'); $h5poutput->h5p_alter_scripts($files['scripts'], $preloadeddeps, $this->embedtype); $h5poutput->h5p_alter_styles($files['styles'], $preloadeddeps, $this->embedtype); return $files; } /** * Resizing script for settings * * @return string The HTML code with the resize script. */ private static function get_resize_code(): string { global $OUTPUT; $template = new \stdClass(); $template->resizeurl = autoloader::get_h5p_core_library_url('js/h5p-resizer.js'); return $OUTPUT->render_from_template('core_h5p/h5presize', $template); } /** * Embed code for settings * * @param string $url The URL of the .h5p file. * @param bool $embedenabled Whether the option to embed the H5P content is enabled. * * @return string The HTML code to reuse this H5P content in a different place. */ private function get_embed_code(string $url, bool $embedenabled): string { global $OUTPUT; if ( ! $embedenabled) { return ''; } $template = new \stdClass(); $template->embedurl = self::get_embed_url($url, $this->component)->out(false); return $OUTPUT->render_from_template('core_h5p/h5pembed', $template); } /** * Get the encoded URL for embeding this H5P content. * @param string $url The URL of the .h5p file. * @param string $component optional Moodle component to send xAPI tracking * * @return \moodle_url The embed URL. */ public static function get_embed_url(string $url, string $component = ''): \moodle_url { $params = ['url' => $url]; if (!empty($component)) { // If component is not empty, it will be passed too, in order to allow tracking too. $params['component'] = $component; } return new \moodle_url('/h5p/embed.php', $params); } /** * Return the info export file for Mobile App. * * @return array or null */ public function get_export_file(): ?array { // Get the export url. $exporturl = $this->get_export_settings(true); // Get the filename of the export url. $path = $exporturl->out_as_local_url(); // Check if the URL has parameters. $parts = explode('?', $path); $path = array_shift($parts); $parts = explode('/', $path); $filename = array_pop($parts); // Get the required info from the export file to be able to get the export file by third apps. $file = helper::get_export_info($filename, $exporturl); return $file; } } PK*\z#:m m !classes/form/editcontent_form.phpnu[. namespace core_h5p\form; use core_h5p\editor; /** * Form to edit an existing H5P content. * * @package core_h5p * @copyright 2020 Victor Deniz * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class editcontent_form extends \moodleform { /** @var editor H5P editor object */ private $editor; /** * The form definition. */ public function definition() { $mform = $this->_form; $id = $this->_customdata['id'] ?? null; $contenturl = $this->_customdata['contenturl'] ?? null; $returnurl = $this->_customdata['returnurl'] ?? null; $editor = new editor(); if ($id) { $mform->addElement('hidden', 'id', $id); $mform->setType('id', PARAM_INT); $editor->set_content($id); } if ($contenturl) { $mform->addElement('hidden', 'url', $contenturl); $mform->setType('url', PARAM_LOCALURL); } if ($returnurl) { $mform->addElement('hidden', 'returnurl', $returnurl); $mform->setType('returnurl', PARAM_LOCALURL); } $this->editor = $editor; $mformid = 'h5peditor'; $mform->setAttributes(array('id' => $mformid) + $mform->getAttributes()); $this->set_display_vertical(); $this->add_action_buttons(); $editor->add_editor_to_form($mform); $this->add_action_buttons(); } /** * Updates an H5P content. * * @param \stdClass $data Object with all the H5P data. * * @return void */ public function save_h5p(\stdClass $data): void { $this->editor->save_content($data); } } PK*\hO%classes/form/uploadlibraries_form.phpnu[. /** * Upload an h5p content to update the content libraries. * * @package core_h5p * @copyright 2019 Amaia Anabitarte * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\form; defined('MOODLE_INTERNAL') || die(); /** * Upload a zip or h5p content to update the content libraries. * * @copyright 2019 Amaia Anabitarte * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class uploadlibraries_form extends \moodleform { /** * Form definition. */ public function definition() { $mform = $this->_form; $mform->addElement('header', 'settingsheader', get_string('uploadlibraries', 'core_h5p')); $filemanageroptions = array( 'accepted_types' => array('.h5p', '.zip'), 'maxbytes' => 0, 'maxfiles' => 1, 'subdirs' => 0 ); $mform->addElement('filepicker', 'h5ppackage', get_string('h5ppackage', 'core_h5p'), null, $filemanageroptions); $mform->addHelpButton('h5ppackage', 'h5ppackage', 'core_h5p'); $mform->addRule('h5ppackage', null, 'required'); $mform->addElement('submit', 'uploadlibraries', get_string('uploadlibraries', 'core_h5p')); } } PK*\6RRclasses/privacy/provider.phpnu[. namespace tiny_h5p\privacy; /** * Privacy Subsystem implementation for the H5P plugin for TinyMCE. * * @package tiny_h5p * @copyright 2022 Andrew Lyons * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { public static function get_reason(): string { return 'privacy:metadata'; } } PK*\ϟs$classes/local/library/autoloader.phpnu[. /** * H5P autoloader management class. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\local\library; /** * H5P autoloader management class. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class autoloader { /** * Returns the list of plugins that can work as H5P library handlers (have class PLUGINNAME\local\library\handler) * @return array with the format: pluginname => class */ public static function get_all_handlers(): array { $handlers = []; $plugins = \core_component::get_plugin_list_with_class('h5plib', 'local\library\handler') + \core_component::get_plugin_list_with_class('h5plib', 'local_library_handler'); // Allow plugins to have the class either with namespace or without (useful for unittest). foreach ($plugins as $pname => $class) { $handlers[$pname] = $class; } return $handlers; } /** * Returns the default H5P library handler class. * * @return string|null H5P library handler class */ public static function get_default_handler(): ?string { $default = null; $handlers = self::get_all_handlers(); if (!empty($handlers)) { // The default handler will be the first value in the list. $default = array_shift($handlers); } return $default; } /** * Returns the default H5P library handler. * * @return string|null H5P library handler */ public static function get_default_handler_library(): ?string { $default = null; $handlers = self::get_all_handlers(); if (!empty($handlers)) { // The default handler will be the first in the list. $keys = array_keys($handlers); $default = array_shift($keys); } return $default; } /** * Returns the current H5P library handler class. * * @return string H5P library handler class * @throws \moodle_exception */ public static function get_handler_classname(): string { global $CFG; $handlers = self::get_all_handlers(); if (!empty($CFG->h5plibraryhandler)) { if (isset($handlers[$CFG->h5plibraryhandler])) { return $handlers[$CFG->h5plibraryhandler]; } } // If no handler has been defined, return the default one. $defaulthandler = self::get_default_handler(); if (empty($defaulthandler)) { // If there is no default handler, throw an exception. throw new \moodle_exception('noh5plibhandlerdefined', 'core_h5p'); } return $defaulthandler; } /** * Get the current version of the H5P core library. * * @return string */ public static function get_h5p_version(): string { return component_class_callback(self::get_handler_classname(), 'get_h5p_version', []); } /** * Get a URL for the current H5P Core Library. * * @param string $filepath The path within the h5p root * @param array $params these params override current params or add new * @return null|moodle_url */ public static function get_h5p_core_library_url(?string $filepath = null, ?array $params = null): ?\moodle_url { return component_class_callback(self::get_handler_classname(), 'get_h5p_core_library_url', [$filepath, $params]); } /** * Get a URL for the current H5P Editor Library. * * @param string $filepath The path within the h5p root. * @param array $params These params override current params or add new. * @return null|\moodle_url The moodle_url instance to a file in the H5P Editor library. */ public static function get_h5p_editor_library_url(?string $filepath = null, ?array $params = null): ?\moodle_url { return component_class_callback(self::get_handler_classname(), 'get_h5p_editor_library_url', [$filepath, $params]); } /** * Get the base path for the current H5P Editor Library. * * @param string $filepath The path within the h5p root. * @return string Path to a file in the H5P Editor library. */ public static function get_h5p_editor_library_base(?string $filepath = null): string { return component_class_callback(self::get_handler_classname(), 'get_h5p_editor_library_base', [$filepath]); } /** * Returns a localized string, if it exists in the h5plib plugin and the value it's different from the English version. * * @param string $identifier The key identifier for the localized string * @param string $language Language to get the localized string. * @return string|null The localized string or null if it doesn't exist in this H5P library plugin. */ public static function get_h5p_string(string $identifier, string $language): ?string { return component_class_callback(self::get_handler_classname(), 'get_h5p_string', [$identifier, $language]); } /** * Register the H5P autoloader. */ public static function register(): void { component_class_callback(self::get_handler_classname(), 'register', []); } } PK*\Wz&8mm!classes/local/library/handler.phpnu[. /** * Base class for library handlers. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\local\library; defined('MOODLE_INTERNAL') || die(); /** * Base class for library handlers. * * If a new H5P libraries handler plugin has to be created, it has to define class * PLUGINNAME\local\library\handler that extends \core_h5p\local\library\handler. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ abstract class handler { /** * Get the current version of the H5P core library. * * @return string */ abstract public static function get_h5p_version(): string; /** * Get the base path for the H5P Libraries. * * @return null|string */ public static function get_h5p_library_base(): ?string { $h5pversion = static::get_h5p_version(); return "/h5p/h5plib/v{$h5pversion}/joubel"; } /** * Get the base path for the current H5P Core Library. * * @param string $filepath The path within the H5P root * @return null|string */ public static function get_h5p_core_library_base(?string $filepath = null): ?string { return static::get_h5p_library_base() . "/core/{$filepath}"; } /** * Get the base path for the current H5P Editor Library. * * @param null|string $filepath The path within the H5P root. * @return string Path to a file in the H5P Editor library. */ public static function get_h5p_editor_library_base(?string $filepath = null): string { return static::get_h5p_library_base() . "/editor/{$filepath}"; } /** * Register the H5P autoloader. */ public static function register(): void { // Prepend H5P libraries in order to guarantee they are loaded first. Plugins using same libraries will need to use a // different namespace if they want to use a different version. spl_autoload_register([static::class, 'autoload'], true, true); } /** * SPL Autoloading function for H5P. * * @param string $classname The name of the class to load */ public static function autoload($classname): void { global $CFG; $classes = static::get_class_list(); if (isset($classes[$classname])) { if (file_exists($CFG->dirroot . static::get_h5p_core_library_base($classes[$classname]))) { require_once($CFG->dirroot . static::get_h5p_core_library_base($classes[$classname])); } else { require_once($CFG->dirroot . static::get_h5p_editor_library_base($classes[$classname])); } } } /** * Get a URL for the current H5P Core Library. * * @param string $filepath The path within the h5p root * @param array $params these params override current params or add new * @return null|\moodle_url */ public static function get_h5p_core_library_url(?string $filepath = null, ?array $params = null): ?\moodle_url { return new \moodle_url(static::get_h5p_core_library_base($filepath), $params); } /** * Get a URL for the current H5P Editor Library. * * @param string $filepath The path within the h5p root. * @param array $params These params override current params or add new. * @return null|\moodle_url The moodle_url to a file in the H5P Editor library. */ public static function get_h5p_editor_library_url(?string $filepath = null, ?array $params = null): ?\moodle_url { return new \moodle_url(static::get_h5p_editor_library_base($filepath), $params); } /** * Returns a localized string, if it exists in the h5plib plugin and the value it's different from the English version. * * @param string $identifier The key identifier for the localized string * @param string $language Language to get the localized string. * @return string|null The localized string or null if it doesn't exist in this H5P library plugin. */ public static function get_h5p_string(string $identifier, string $language): ?string { $value = null; $h5pversion = static::get_h5p_version(); $component = 'h5plib_v' . $h5pversion; // Composed code languages, such as 'Spanish, Mexican' are different in H5P and Moodle: // - In H5P, they use '-' to separate language from the country. For instance: es-mx. // - However, in Moodle, they have '_' instead of '-'. For instance: es_mx. $language = str_replace('-', '_', $language); if (get_string_manager()->string_exists($identifier, $component)) { $defaultmoodlelang = 'en'; // In Moodle, all the English strings always will exist because they have to be declared in order to let users // to translate them. That's why, this method will only replace existing key if the value is different from // the English version and the current language is not English. $string = new \lang_string($identifier, $component); if ($language === $defaultmoodlelang || $string->out($language) !== $string->out($defaultmoodlelang)) { $value = $string->out($language); } } return $value; } /** * Return the list of classes with their location within the joubel directory. * * @return array */ protected static function get_class_list(): array { return [ 'Moodle\H5PCore' => 'h5p.classes.php', 'Moodle\H5PFrameworkInterface' => 'h5p.classes.php', 'Moodle\H5PContentValidator' => 'h5p.classes.php', 'Moodle\H5PValidator' => 'h5p.classes.php', 'Moodle\H5PStorage' => 'h5p.classes.php', 'Moodle\H5PDevelopment' => 'h5p-development.class.php', 'Moodle\H5PFileStorage' => 'h5p-file-storage.interface.php', 'Moodle\H5PDefaultStorage' => 'h5p-default-storage.class.php', 'Moodle\H5PMetadata' => 'h5p-metadata.class.php', 'Moodle\H5peditor' => 'h5peditor.class.php', 'Moodle\H5peditorStorage' => 'h5peditor-storage.interface.php', 'Moodle\H5PEditorAjaxInterface' => 'h5peditor-ajax.interface.php', 'Moodle\H5PEditorAjax' => 'h5peditor-ajax.class.php', 'Moodle\H5peditorFile' => 'h5peditor-file.class.php', ]; } } PK*\66classes/framework.phpnu[. namespace core_h5p; use core_xapi\handler; use core_xapi\xapi_exception; use Moodle\H5PFrameworkInterface; use Moodle\H5PCore; // phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod /** * Moodle's implementation of the H5P framework interface. * * @package core_h5p * @copyright 2019 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class framework implements H5PFrameworkInterface { /** @var string The path to the last uploaded h5p */ private $lastuploadedfolder; /** @var string The path to the last uploaded h5p file */ private $lastuploadedfile; /** @var \stored_file The .h5p file */ private $file; /** * Returns info for the current platform. * Implements getPlatformInfo. * * @return array An associative array containing: * - name: The name of the platform, for instance "Moodle" * - version: The version of the platform, for instance "3.8" * - h5pVersion: The version of the H5P component */ public function getPlatformInfo() { global $CFG; return array( 'name' => 'Moodle', 'version' => $CFG->version, 'h5pVersion' => $CFG->version, ); } /** * Fetches a file from a remote server using HTTP GET * Implements fetchExternalData. * * @param string $url Where you want to get or send data. * @param array $data Data to post to the URL. * @param bool $blocking Set to 'FALSE' to instantly time out (fire and forget). * @param string $stream Path to where the file should be saved. * @param bool $fulldata Return additional response data such as headers and potentially other data * @param array $headers Headers to send * @param array $files Files to send * @param string $method * * @return string|array The content (response body), or an array with data. NULL if something went wrong */ public function fetchExternalData($url, $data = null, $blocking = true, $stream = null, $fulldata = false, $headers = [], $files = [], $method = 'POST') { if ($stream === null) { // Download file. set_time_limit(0); // Get the extension of the remote file. $parsedurl = parse_url($url); $ext = pathinfo($parsedurl['path'], PATHINFO_EXTENSION); // Generate local tmp file path. $fs = new \core_h5p\file_storage(); $localfolder = $fs->getTmpPath(); $stream = $localfolder; // Add the remote file's extension to the temp file. if ($ext) { $stream .= '.' . $ext; } $this->getUploadedH5pFolderPath($localfolder); $this->getUploadedH5pPath($stream); } $response = download_file_content($url, null, $data, true, 300, 20, false, $stream); if (empty($response->error) && ($response->status != '404')) { return $response->results; } else { $this->setErrorMessage($response->error, 'failed-fetching-external-data'); } } /** * Set the tutorial URL for a library. All versions of the library is set. * Implements setLibraryTutorialUrl. * * @param string $libraryname * @param string $url */ public function setLibraryTutorialUrl($libraryname, $url) { global $DB; $sql = 'UPDATE {h5p_libraries} SET tutorial = :tutorial WHERE machinename = :machinename'; $params = [ 'tutorial' => $url, 'machinename' => $libraryname, ]; $DB->execute($sql, $params); } /** * Set an error message. * Implements setErrorMessage. * * @param string $message The error message * @param string $code An optional code */ public function setErrorMessage($message, $code = null) { if ($message !== null) { $this->set_message('error', $message, $code); } } /** * Set an info message. * Implements setInfoMessage. * * @param string $message The info message */ public function setInfoMessage($message) { if ($message !== null) { $this->set_message('info', $message); } } /** * Return messages. * Implements getMessages. * * @param string $type The message type, e.g. 'info' or 'error' * @return string[] Array of messages */ public function getMessages($type) { global $SESSION; // Return and reset messages. $messages = array(); if (isset($SESSION->core_h5p_messages[$type])) { $messages = $SESSION->core_h5p_messages[$type]; unset($SESSION->core_h5p_messages[$type]); if (empty($SESSION->core_h5p_messages)) { unset($SESSION->core_h5p_messages); } } return $messages; } /** * Translation function. * The purpose of this function is to map the strings used in the core h5p methods * and replace them with the translated ones. If a translation for a particular string * is not available, the default message (key) will be returned. * Implements t. * * @param string $message The english string to be translated * @param array $replacements An associative array of replacements to make after translation * @return string Translated string or the english string if a translation is not available */ public function t($message, $replacements = array()) { // Create mapping. $translationsmap = [ 'The file you uploaded is not a valid HTML5 Package (It does not have the .h5p file extension)' => 'noextension', 'The file you uploaded is not a valid HTML5 Package (We are unable to unzip it)' => 'nounzip', 'The main h5p.json file is not valid' => 'nojson', 'Library directory name must match machineName or machineName-majorVersion.minorVersion (from library.json).' . ' (Directory: %directoryName , machineName: %machineName, majorVersion: %majorVersion, minorVersion:' . ' %minorVersion)' => 'librarydirectoryerror', 'A valid content folder is missing' => 'missingcontentfolder', 'A valid main h5p.json file is missing' => 'invalidmainjson', 'Missing required library @library' => 'missinglibrary', "Note that the libraries may exist in the file you uploaded, but you're not allowed to upload new libraries." . ' Contact the site administrator about this.' => 'missinguploadpermissions', 'Invalid library name: %name' => 'invalidlibraryname', 'Could not find library.json file with valid json format for library %name' => 'missinglibraryjson', 'Invalid semantics.json file has been included in the library %name' => 'invalidsemanticsjson', 'Invalid language file %file in library %library' => 'invalidlanguagefile', 'Invalid language file %languageFile has been included in the library %name' => 'invalidlanguagefile2', 'The file "%file" is missing from library: "%name"' => 'missinglibraryfile', 'The system was unable to install the %component component from the package, it requires a newer' . ' version of the H5P plugin. This site is currently running version %current, whereas the required version' . ' is %required or higher. You should consider upgrading and then try again.' => 'missingcoreversion', "Invalid data provided for %property in %library. Boolean expected." => 'invalidlibrarydataboolean', "Invalid data provided for %property in %library" => 'invalidlibrarydata', "Can't read the property %property in %library" => 'invalidlibraryproperty', 'The required property %property is missing from %library' => 'missinglibraryproperty', 'Illegal option %option in %library' => 'invalidlibraryoption', 'Added %new new H5P library and updated %old old one.' => 'addedandupdatedss', 'Added %new new H5P library and updated %old old ones.' => 'addedandupdatedsp', 'Added %new new H5P libraries and updated %old old one.' => 'addedandupdatedps', 'Added %new new H5P libraries and updated %old old ones.' => 'addedandupdatedpp', 'Added %new new H5P library.' => 'addednewlibrary', 'Added %new new H5P libraries.' => 'addednewlibraries', 'Updated %old H5P library.' => 'updatedlibrary', 'Updated %old H5P libraries.' => 'updatedlibraries', 'Missing dependency @dep required by @lib.' => 'missingdependency', 'Provided string is not valid according to regexp in semantics. (value: "%value", regexp: "%regexp")' => 'invalidstring', 'File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.' => 'invalidfile', 'Invalid selected option in multi-select.' => 'invalidmultiselectoption', 'Invalid selected option in select.' => 'invalidselectoption', 'H5P internal error: unknown content type "@type" in semantics. Removing content!' => 'invalidsemanticstype', 'Copyright information' => 'copyrightinfo', 'Title' => 'title', 'Author' => 'author', 'Year(s)' => 'years', 'Year' => 'year', 'Source' => 'source', 'License' => 'license', 'Undisclosed' => 'undisclosed', 'General Public License v3' => 'gpl', 'Public Domain' => 'pd', 'Public Domain Dedication and Licence' => 'pddl', 'Public Domain Mark' => 'pdm', 'Public Domain Mark (PDM)' => 'pdm', 'Copyright' => 'copyrightstring', 'The mbstring PHP extension is not loaded. H5P need this to function properly' => 'missingmbstring', 'The version of the H5P library %machineName used in this content is not valid. Content contains %contentLibrary, ' . 'but it should be %semanticsLibrary.' => 'wrongversion', 'The H5P library %library used in the content is not valid' => 'invalidlibrarynamed', 'Fullscreen' => 'fullscreen', 'Disable fullscreen' => 'disablefullscreen', 'Download' => 'download', 'Rights of use' => 'copyright', 'Embed' => 'embed', 'Size' => 'size', 'Show advanced' => 'showadvanced', 'Hide advanced' => 'hideadvanced', 'Include this script on your website if you want dynamic sizing of the embedded content:' => 'resizescript', 'Close' => 'close', 'Thumbnail' => 'thumbnail', 'No copyright information available for this content.' => 'nocopyright', 'Download this content as a H5P file.' => 'downloadtitle', 'View copyright information for this content.' => 'copyrighttitle', 'View the embed code for this content.' => 'embedtitle', 'Visit H5P.org to check out more cool content.' => 'h5ptitle', 'This content has changed since you last used it.' => 'contentchanged', "You'll be starting over." => 'startingover', 'by' => 'by', 'Show more' => 'showmore', 'Show less' => 'showless', 'Sublevel' => 'sublevel', 'Confirm action' => 'confirmdialogheader', 'Please confirm that you wish to proceed. This action is not reversible.' => 'confirmdialogbody', 'Cancel' => 'cancellabel', 'Confirm' => 'confirmlabel', '4.0 International' => 'licenseCC40', '3.0 Unported' => 'licenseCC30', '2.5 Generic' => 'licenseCC25', '2.0 Generic' => 'licenseCC20', '1.0 Generic' => 'licenseCC10', 'General Public License' => 'licenseGPL', 'Version 3' => 'licenseV3', 'Version 2' => 'licenseV2', 'Version 1' => 'licenseV1', 'CC0 1.0 Universal (CC0 1.0) Public Domain Dedication' => 'licenseCC010', 'CC0 1.0 Universal' => 'licenseCC010U', 'License Version' => 'licenseversion', 'Creative Commons' => 'creativecommons', 'Attribution' => 'ccattribution', 'Attribution (CC BY)' => 'ccattribution', 'Attribution-ShareAlike' => 'ccattributionsa', 'Attribution-ShareAlike (CC BY-SA)' => 'ccattributionsa', 'Attribution-NoDerivs' => 'ccattributionnd', 'Attribution-NoDerivs (CC BY-ND)' => 'ccattributionnd', 'Attribution-NonCommercial' => 'ccattributionnc', 'Attribution-NonCommercial (CC BY-NC)' => 'ccattributionnc', 'Attribution-NonCommercial-ShareAlike' => 'ccattributionncsa', 'Attribution-NonCommercial-ShareAlike (CC BY-NC-SA)' => 'ccattributionncsa', 'Attribution-NonCommercial-NoDerivs' => 'ccattributionncnd', 'Attribution-NonCommercial-NoDerivs (CC BY-NC-ND)' => 'ccattributionncnd', 'Public Domain Dedication (CC0)' => 'ccpdd', 'Years (from)' => 'yearsfrom', 'Years (to)' => 'yearsto', "Author's name" => 'authorname', "Author's role" => 'authorrole', 'Editor' => 'editor', 'Licensee' => 'licensee', 'Originator' => 'originator', 'Any additional information about the license' => 'additionallicenseinfo', 'License Extras' => 'licenseextras', 'Changelog' => 'changelog', 'Content Type' => 'contenttype', 'Date' => 'date', 'Changed by' => 'changedby', 'Description of change' => 'changedescription', 'Photo cropped, text changed, etc.' => 'changeplaceholder', 'Author comments' => 'authorcomments', 'Comments for the editor of the content (This text will not be published as a part of copyright info)' => 'authorcommentsdescription', 'Reuse' => 'reuse', 'Reuse Content' => 'reuseContent', 'Reuse this content.' => 'reuseDescription', 'Content is copied to the clipboard' => 'contentCopied', 'Connection lost. Results will be stored and sent when you regain connection.' => 'connectionLost', 'Connection reestablished.' => 'connectionReestablished', 'Attempting to submit stored results.' => 'resubmitScores', 'Your connection to the server was lost' => 'offlineDialogHeader', 'We were unable to send information about your completion of this task. Please check your internet connection.' => 'offlineDialogBody', 'Retrying in :num....' => 'offlineDialogRetryMessage', 'Retry now' => 'offlineDialogRetryButtonLabel', 'Successfully submitted results.' => 'offlineSuccessfulSubmit', 'One of the files inside the package exceeds the maximum file size allowed. (%file %used > %max)' => 'fileExceedsMaxSize', 'The total size of the unpacked files exceeds the maximum size allowed. (%used > %max)' => 'unpackedFilesExceedsMaxSize', 'Unable to read file from the package: %fileName' => 'couldNotReadFileFromZip', 'Unable to parse JSON from the package: %fileName' => 'couldNotParseJSONFromZip', 'A problem with the server write access was detected. Please make sure that your server can write to your data folder.' => 'nowriteaccess', 'H5P hub communication has been disabled because one or more H5P requirements failed.' => 'hubcommunicationdisabled', 'Site could not be registered with the hub. Please contact your site administrator.' => 'sitecouldnotberegistered', 'The H5P Hub has been disabled until this problem can be resolved. You may still upload libraries through the "H5P Libraries" page.' => 'hubisdisableduploadlibraries', 'When you have revised your server setup you may re-enable H5P hub communication in H5P Settings.' => 'reviseserversetupandretry', 'You have been provided a unique key that identifies you with the Hub when receiving new updates. The key is available for viewing in the "H5P Settings" page.' => 'sitekeyregistered', 'Your PHP max post size is quite small. With your current setup, you may not upload files larger than {$a->%number} MB. This might be a problem when trying to upload H5Ps, images and videos. Please consider to increase it to more than 5MB' => 'maxpostsizetoosmall', 'Your PHP max upload size is bigger than your max post size. This is known to cause issues in some installations.' => 'uploadsizelargerthanpostsize', 'Your PHP max upload size is quite small. With your current setup, you may not upload files larger than {$a->%number} MB. This might be a problem when trying to upload H5Ps, images and videos. Please consider to increase it to more than 5MB.' => 'maxuploadsizetoosmall', 'Your PHP version does not support ZipArchive.' => 'noziparchive', 'Your PHP version is outdated. H5P requires version 5.2 to function properly. Version 5.6 or later is recommended.' => 'oldphpversion', 'Your server does not have SSL enabled. SSL should be enabled to ensure a secure connection with the H5P hub.' => 'sslnotenabled', 'Your site was successfully registered with the H5P Hub.' => 'successfullyregisteredwithhub', 'Sharing :title' => 'mainTitle', 'Edit info for :title' => 'editInfoTitle', 'Back' => 'back', 'Next' => 'next', 'Review info' => 'reviewInfo', 'Share' => 'share', 'Save changes' => 'saveChanges', 'Register on the H5P Hub' => 'registerOnHub', 'Save account settings' => 'updateRegistrationOnHub', 'Required Info' => 'requiredInfo', 'Optional Info' => 'optionalInfo', 'Review & Share' => 'reviewAndShare', 'Review & Save' => 'reviewAndSave', 'Shared' => 'shared', 'Step :step of :total' => 'currentStep', 'All content details can be edited after sharing' => 'sharingNote', 'Select a license for your content' => 'licenseDescription', 'Select a license version' => 'licenseVersionDescription', 'Disciplines' => 'disciplineLabel', 'You can select multiple disciplines' => 'disciplineDescription', 'You can select up to :numDisciplines disciplines' => 'disciplineLimitReachedMessage', 'Type to search for disciplines' => 'discipline:searchPlaceholder', 'in' => 'discipline:in', 'Dropdown button' => 'discipline:dropdownButton', 'Remove :chip from the list' => 'removeChip', 'Add keywords' => 'keywordsPlaceholder', 'Keywords' => 'keywords', 'You can add multiple keywords separated by commas. Press "Enter" or "Add" to confirm keywords' => 'keywordsDescription', 'Alt text' => 'altText', 'Please review the info below before you share' => 'reviewMessage', 'Sub-content (images, questions etc.) will be shared under :license unless otherwise specified in the authoring tool' => 'subContentWarning', 'Disciplines' => 'disciplines', 'Short description' => 'shortDescription', 'Long description' => 'longDescription', 'Icon' => 'icon', 'Screenshots' => 'screenshots', 'Help me choose a license' => 'helpChoosingLicense', 'Share failed.' => 'shareFailed', 'Editing failed.' => 'editingFailed', 'Something went wrong, please try to share again.' => 'shareTryAgain', 'Please wait...' => 'pleaseWait', 'Language' => 'language', 'Level' => 'level', 'Short description of your content' => 'shortDescriptionPlaceholder', 'Long description of your content' => 'longDescriptionPlaceholder', 'Description' => 'description', '640x480px. If not selected content will use category icon' => 'iconDescription', 'Add up to five screenshots of your content' => 'screenshotsDescription', 'Submitted!' => 'submitted', 'Is now submitted to H5P Hub' => 'isNowSubmitted', 'A change has been submited for' => 'changeHasBeenSubmitted', 'Your content will normally be available in the Hub within one business day.' => 'contentAvailable', 'Your content will update soon' => 'contentUpdateSoon', 'Content License Info' => 'contentLicenseTitle', 'Click on a specific license to get info about proper usage' => 'licenseDialogDescription', 'Publisher' => 'publisherFieldTitle', 'This will display as the "Publisher name" on shared content' => 'publisherFieldDescription', 'Email Address' => 'emailAddress', 'Publisher description' => 'publisherDescription', 'This will be displayed under "Publisher info" on shared content' => 'publisherDescriptionText', 'Contact Person' => 'contactPerson', 'Phone' => 'phone', 'Address' => 'address', 'City' => 'city', 'Zip' => 'zip', 'Country' => 'country', 'Organization logo or avatar' => 'logoUploadText', 'I accept the terms of use' => 'acceptTerms', 'You have successfully registered an account on the H5P Hub' => 'successfullyRegistred', 'You account details can be changed' => 'successfullyRegistredDescription', 'Your H5P Hub account settings have successfully been changed' => 'successfullyUpdated', 'here' => 'accountDetailsLinkText', 'H5P Hub Registration' => 'registrationTitle', 'An error occurred' => 'registrationFailed', 'We were not able to create an account at this point. Something went wrong. Try again later.' => 'registrationFailedDescription', ':length is the maximum number of characters' => 'maxLength', 'Keyword already exists!' => 'keywordExists', 'License details' => 'licenseDetails', 'Remove' => 'remove', 'Remove image' => 'removeImage', 'Cancel sharing' => 'cancelPublishConfirmationDialogTitle', 'Are you sure you want to cancel the sharing process?' => 'cancelPublishConfirmationDialogDescription', 'No' => 'cancelPublishConfirmationDialogCancelButtonText', 'Yes' => 'cancelPublishConfirmationDialogConfirmButtonText', 'Add' => 'add', 'Typical age' => 'age', 'The target audience of this content. Possible input formats separated by commas: "1,34-45,-50,59-".' => 'ageDescription', 'Invalid input format for Typical age. Possible input formats separated by commas: "1, 34-45, -50, -59-".' => 'invalidAge', 'H5P will reach out to the contact person in case there are any issues with the content shared by the publisher. The contact person\'s name or other information will not be published or shared with third parties' => 'contactPersonDescription', 'The email address will be used by H5P to reach out to the publisher in case of any issues with the content or in case the publisher needs to recover their account. It will not be published or shared with any third parties' => 'emailAddressDescription', 'Copyrighted material cannot be shared in the H5P Content Hub. If the content is licensed with a OER friendly license like Creative Commons, please choose the appropriate license. If not this content cannot be shared.' => 'copyrightWarning', 'Keywords already exists!' => 'keywordsExits', 'Some of these keywords already exist' => 'someKeywordsExits', 'Assistive Technologies label' => 'a11yTitle:label', 'width' => 'width', 'height' => 'height', 'Missing main library @library' => 'missingmainlibrary', 'Rotate Left' => 'rotateLeft', 'Rotate Right' => 'rotateRight', 'Crop Image' => 'cropImage', 'Confirm Crop' => 'confirmCrop', 'Cancel Crop' => 'cancelCrop', ]; if (isset($translationsmap[$message])) { return get_string($translationsmap[$message], 'core_h5p', $replacements); } debugging("String translation cannot be found. Please add a string definition for '" . $message . "' in the core_h5p component.", DEBUG_DEVELOPER); return $message; } /** * Get URL to file in the specifimake_pluginfile_urlc library. * Implements getLibraryFileUrl. * * @param string $libraryfoldername The name or path of the library's folder * @param string $filename The file name * @return string URL to file */ public function getLibraryFileUrl($libraryfoldername, $filename) { global $DB; // Remove unnecessary slashes (first and last, if present) from the path to the folder // of the library file. $libraryfilepath = trim($libraryfoldername, '/'); // Get the folder name of the library from the path. // The first element should represent the folder name of the library. $libfoldername = explode('/', $libraryfilepath)[0]; $factory = new \core_h5p\factory(); $core = $factory->get_core(); // The provided folder name of the library must have a valid format (can be parsed). // The folder name is parsed with a purpose of getting the library related information // such as 'machineName', 'majorVersion' and 'minorVersion'. // This information is later used to retrieve the library ID. if (!$libdata = $core->libraryFromString($libfoldername, true)) { debugging('The provided string value "' . $libfoldername . '" is not a valid name for a library folder.', DEBUG_DEVELOPER); return; } $params = array( 'machinename' => $libdata['machineName'], 'majorversion' => $libdata['majorVersion'], 'minorversion' => $libdata['minorVersion'] ); $libraries = $DB->get_records('h5p_libraries', $params, 'patchversion DESC', 'id', 0, 1); if (!$library = reset($libraries)) { debugging('The library "' . $libfoldername . '" does not exist.', DEBUG_DEVELOPER); return; } $context = \context_system::instance(); return \moodle_url::make_pluginfile_url($context->id, 'core_h5p', 'libraries', $library->id, '/' . $libraryfilepath . '/', $filename)->out(); } /** * Get the Path to the last uploaded h5p. * Implements getUploadedH5PFolderPath. * * @param string $setpath The path to the folder of the last uploaded h5p * @return string Path to the folder where the last uploaded h5p for this session is located */ public function getUploadedH5pFolderPath($setpath = null) { if ($setpath !== null) { $this->lastuploadedfolder = $setpath; } if (!isset($this->lastuploadedfolder)) { throw new \coding_exception('Using getUploadedH5pFolderPath() before path is set'); } return $this->lastuploadedfolder; } /** * Get the path to the last uploaded h5p file. * Implements getUploadedH5PPath. * * @param string $setpath The path to the last uploaded h5p * @return string Path to the last uploaded h5p */ public function getUploadedH5pPath($setpath = null) { if ($setpath !== null) { $this->lastuploadedfile = $setpath; } if (!isset($this->lastuploadedfile)) { throw new \coding_exception('Using getUploadedH5pPath() before path is set'); } return $this->lastuploadedfile; } /** * Load addon libraries. * Implements loadAddons. * * @return array The array containing the addon libraries */ public function loadAddons() { global $DB; $addons = array(); $records = $DB->get_records_sql( "SELECT l1.id AS library_id, l1.machinename AS machine_name, l1.majorversion AS major_version, l1.minorversion AS minor_version, l1.patchversion AS patch_version, l1.addto AS add_to, l1.preloadedjs AS preloaded_js, l1.preloadedcss AS preloaded_css FROM {h5p_libraries} l1 LEFT JOIN {h5p_libraries} l2 ON l1.machinename = l2.machinename AND (l1.majorversion < l2.majorversion OR (l1.majorversion = l2.majorversion AND l1.minorversion < l2.minorversion)) WHERE l1.addto IS NOT NULL AND l2.machinename IS NULL"); // NOTE: These are treated as library objects but are missing the following properties: // title, droplibrarycss, fullscreen, runnable, semantics. // Extract num from records. foreach ($records as $addon) { $addons[] = H5PCore::snakeToCamel($addon); } return $addons; } /** * Load config for libraries. * Implements getLibraryConfig. * * @param array|null $libraries List of libraries * @return array|null The library config if it exists, null otherwise */ public function getLibraryConfig($libraries = null) { global $CFG; return isset($CFG->core_h5p_library_config) ? $CFG->core_h5p_library_config : null; } /** * Get a list of the current installed libraries. * Implements loadLibraries. * * @return array Associative array containing one entry per machine name. * For each machineName there is a list of libraries(with different versions). */ public function loadLibraries() { global $DB; $results = $DB->get_records('h5p_libraries', [], 'title ASC, majorversion ASC, minorversion ASC', 'id, machinename AS machine_name, majorversion AS major_version, minorversion AS minor_version, patchversion AS patch_version, runnable, title, enabled'); $libraries = array(); foreach ($results as $library) { $libraries[$library->machine_name][] = $library; } return $libraries; } /** * Returns the URL to the library admin page. * Implements getAdminUrl. * * @return string URL to admin page */ public function getAdminUrl() { // Not supported. } /** * Return the library's ID. * Implements getLibraryId. * * @param string $machinename The librarys machine name * @param string $majorversion Major version number for library (optional) * @param string $minorversion Minor version number for library (optional) * @return int|bool Identifier, or false if non-existent */ public function getLibraryId($machinename, $majorversion = null, $minorversion = null) { global $DB; $params = array( 'machinename' => $machinename ); if ($majorversion !== null) { $params['majorversion'] = $majorversion; } if ($minorversion !== null) { $params['minorversion'] = $minorversion; } $libraries = $DB->get_records('h5p_libraries', $params, 'majorversion DESC, minorversion DESC, patchversion DESC', 'id', 0, 1); // Get the latest version which matches the input parameters. if ($libraries) { $library = reset($libraries); return $library->id ?? false; } return false; } /** * Get allowed file extension list. * Implements getWhitelist. * * The default extension list is part of h5p, but admins should be allowed to modify it. * * @param boolean $islibrary TRUE if this is the whitelist for a library. FALSE if it is the whitelist * for the content folder we are getting. * @param string $defaultcontentwhitelist A string of file extensions separated by whitespace. * @param string $defaultlibrarywhitelist A string of file extensions separated by whitespace. * @return string A string containing the allowed file extensions separated by whitespace. */ public function getWhitelist($islibrary, $defaultcontentwhitelist, $defaultlibrarywhitelist) { return $defaultcontentwhitelist . ($islibrary ? ' ' . $defaultlibrarywhitelist : ''); } /** * Is the library a patched version of an existing library? * Implements isPatchedLibrary. * * @param array $library An associative array containing: * - machineName: The library machine name * - majorVersion: The librarys major version * - minorVersion: The librarys minor version * - patchVersion: The librarys patch version * @return boolean TRUE if the library is a patched version of an existing library FALSE otherwise */ public function isPatchedLibrary($library) { global $DB; $sql = "SELECT id FROM {h5p_libraries} WHERE machinename = :machinename AND majorversion = :majorversion AND minorversion = :minorversion AND patchversion < :patchversion"; $library = $DB->get_records_sql( $sql, array( 'machinename' => $library['machineName'], 'majorversion' => $library['majorVersion'], 'minorversion' => $library['minorVersion'], 'patchversion' => $library['patchVersion'] ), 0, 1 ); return !empty($library); } /** * Is H5P in development mode? * Implements isInDevMode. * * @return boolean TRUE if H5P development mode is active FALSE otherwise */ public function isInDevMode() { return false; // Not supported (Files in moodle not editable). } /** * Is the current user allowed to update libraries? * Implements mayUpdateLibraries. * * @return boolean TRUE if the user is allowed to update libraries, * FALSE if the user is not allowed to update libraries. */ public function mayUpdateLibraries() { return helper::can_update_library($this->get_file()); } /** * Get the .h5p file. * * @return \stored_file The .h5p file. */ public function get_file(): \stored_file { if (!isset($this->file)) { throw new \coding_exception('Using get_file() before file is set'); } return $this->file; } /** * Set the .h5p file. * * @param stored_file $file The .h5p file. */ public function set_file(\stored_file $file): void { $this->file = $file; } /** * Store data about a library. * Implements saveLibraryData. * * Also fills in the libraryId in the libraryData object if the object is new. * * @param array $librarydata Associative array containing: * - libraryId: The id of the library if it is an existing library * - title: The library's name * - machineName: The library machineName * - majorVersion: The library's majorVersion * - minorVersion: The library's minorVersion * - patchVersion: The library's patchVersion * - runnable: 1 if the library is a content type, 0 otherwise * - fullscreen(optional): 1 if the library supports fullscreen, 0 otherwise * - embedtypes: list of supported embed types * - preloadedJs(optional): list of associative arrays containing: * - path: path to a js file relative to the library root folder * - preloadedCss(optional): list of associative arrays containing: * - path: path to css file relative to the library root folder * - dropLibraryCss(optional): list of associative arrays containing: * - machineName: machine name for the librarys that are to drop their css * - semantics(optional): Json describing the content structure for the library * - metadataSettings(optional): object containing: * - disable: 1 if metadata is disabled completely * - disableExtraTitleField: 1 if the title field is hidden in the form * @param bool $new Whether it is a new or existing library. */ public function saveLibraryData(&$librarydata, $new = true) { global $DB; // Some special properties needs some checking and converting before they can be saved. $preloadedjs = $this->library_parameter_values_to_csv($librarydata, 'preloadedJs', 'path'); $preloadedcss = $this->library_parameter_values_to_csv($librarydata, 'preloadedCss', 'path'); $droplibrarycss = $this->library_parameter_values_to_csv($librarydata, 'dropLibraryCss', 'machineName'); if (!isset($librarydata['semantics'])) { $librarydata['semantics'] = ''; } if (!isset($librarydata['fullscreen'])) { $librarydata['fullscreen'] = 0; } $embedtypes = ''; if (isset($librarydata['embedTypes'])) { $embedtypes = implode(', ', $librarydata['embedTypes']); } $library = (object) array( 'title' => $librarydata['title'], 'machinename' => $librarydata['machineName'], 'majorversion' => $librarydata['majorVersion'], 'minorversion' => $librarydata['minorVersion'], 'patchversion' => $librarydata['patchVersion'], 'runnable' => $librarydata['runnable'], 'fullscreen' => $librarydata['fullscreen'], 'embedtypes' => $embedtypes, 'preloadedjs' => $preloadedjs, 'preloadedcss' => $preloadedcss, 'droplibrarycss' => $droplibrarycss, 'semantics' => $librarydata['semantics'], 'addto' => isset($librarydata['addTo']) ? json_encode($librarydata['addTo']) : null, 'coremajor' => isset($librarydata['coreApi']['majorVersion']) ? $librarydata['coreApi']['majorVersion'] : null, 'coreminor' => isset($librarydata['coreApi']['majorVersion']) ? $librarydata['coreApi']['minorVersion'] : null, 'metadatasettings' => isset($librarydata['metadataSettings']) ? $librarydata['metadataSettings'] : null, ); if ($new) { // Create new library and keep track of id. $library->id = $DB->insert_record('h5p_libraries', $library); $librarydata['libraryId'] = $library->id; } else { // Update library data. $library->id = $librarydata['libraryId']; // Save library data. $DB->update_record('h5p_libraries', $library); // Remove old dependencies. $this->deleteLibraryDependencies($librarydata['libraryId']); } } /** * Insert new content. * Implements insertContent. * * @param array $content An associative array containing: * - id: The content id * - params: The content in json format * - library: An associative array containing: * - libraryId: The id of the main library for this content * - disable: H5P Button display options * - pathnamehash: The pathnamehash linking the record with the entry in the mdl_files table * - contenthash: The contenthash linking the record with the entry in the mdl_files table * @param int $contentmainid Main id for the content if this is a system that supports versions * @return int The ID of the newly inserted content */ public function insertContent($content, $contentmainid = null) { return $this->updateContent($content); } /** * Update old content or insert new content. * Implements updateContent. * * @param array $content An associative array containing: * - id: The content id * - params: The content in json format * - library: An associative array containing: * - libraryId: The id of the main library for this content * - disable: H5P Button display options * - pathnamehash: The pathnamehash linking the record with the entry in the mdl_files table * - contenthash: The contenthash linking the record with the entry in the mdl_files table * @param int $contentmainid Main id for the content if this is a system that supports versions * @return int The ID of the newly inserted or updated content */ public function updateContent($content, $contentmainid = null) { global $DB; // If the libraryid declared in the package is empty, get the latest version. if (empty($content['library']['libraryId'])) { $mainlibrary = $this->get_latest_library_version($content['library']['machineName']); if (empty($mainlibrary)) { // Raise an error if the main library is not defined and the latest version doesn't exist. $message = $this->t('Missing required library @library', ['@library' => $content['library']['machineName']]); $this->setErrorMessage($message, 'missing-required-library'); return false; } $content['library']['libraryId'] = $mainlibrary->id; } $content['disable'] = $content['disable'] ?? null; // Add title to 'params' to use in the editor. if (!empty($content['title'])) { $params = json_decode($content['params']); $params->title = $content['title']; $content['params'] = json_encode($params); } // Add metadata to 'params'. if (!empty($content['metadata'])) { $params = json_decode($content['params']); $params->metadata = $content['metadata']; $content['params'] = json_encode($params); } $data = [ 'jsoncontent' => $content['params'], 'displayoptions' => $content['disable'], 'mainlibraryid' => $content['library']['libraryId'], 'timemodified' => time(), 'filtered' => null, ]; if (isset($content['pathnamehash'])) { $data['pathnamehash'] = $content['pathnamehash']; } if (isset($content['contenthash'])) { $data['contenthash'] = $content['contenthash']; } if (!isset($content['id'])) { $data['pathnamehash'] = $data['pathnamehash'] ?? ''; $data['contenthash'] = $data['contenthash'] ?? ''; $data['timecreated'] = $data['timemodified']; $id = $DB->insert_record('h5p', $data); } else { $id = $data['id'] = $content['id']; $DB->update_record('h5p', $data); } return $id; } /** * Resets marked user data for the given content. * Implements resetContentUserData. * * @param int $contentid The h5p content id */ public function resetContentUserData($contentid) { global $DB; // Get the component associated to the H5P content to reset. $h5p = $DB->get_record('h5p', ['id' => $contentid]); if (!$h5p) { return; } $fs = get_file_storage(); $file = $fs->get_file_by_hash($h5p->pathnamehash); if (!$file) { return; } // Reset user data. try { $xapihandler = handler::create($file->get_component()); // Reset only entries with 'state' as stateid (the ones restored shouldn't be restored, because the H5P // content hasn't been created yet). $xapihandler->reset_states($file->get_contextid(), null, 'state'); } catch (xapi_exception $exception) { // This component doesn't support xAPI State, so no content needs to be reset. return; } } /** * Save what libraries a library is depending on. * Implements saveLibraryDependencies. * * @param int $libraryid Library Id for the library we're saving dependencies for * @param array $dependencies List of dependencies as associative arrays containing: * - machineName: The library machineName * - majorVersion: The library's majorVersion * - minorVersion: The library's minorVersion * @param string $dependencytype The type of dependency */ public function saveLibraryDependencies($libraryid, $dependencies, $dependencytype) { global $DB; foreach ($dependencies as $dependency) { // Find dependency library. $dependencylibrary = $DB->get_record('h5p_libraries', array( 'machinename' => $dependency['machineName'], 'majorversion' => $dependency['majorVersion'], 'minorversion' => $dependency['minorVersion'] ) ); // Create relation. $DB->insert_record('h5p_library_dependencies', array( 'libraryid' => $libraryid, 'requiredlibraryid' => $dependencylibrary->id, 'dependencytype' => $dependencytype )); } } /** * Give an H5P the same library dependencies as a given H5P. * Implements copyLibraryUsage. * * @param int $contentid Id identifying the content * @param int $copyfromid Id identifying the content to be copied * @param int $contentmainid Main id for the content, typically used in frameworks */ public function copyLibraryUsage($contentid, $copyfromid, $contentmainid = null) { // Currently not being called. } /** * Deletes content data. * Implements deleteContentData. * * @param int $contentid Id identifying the content */ public function deleteContentData($contentid) { global $DB; // The user content should be reset (instead of removed), because this method is called when H5P content needs // to be updated too (and the previous states must be kept, but reset). $this->resetContentUserData($contentid); // Remove content. $DB->delete_records('h5p', ['id' => $contentid]); // Remove content library dependencies. $this->deleteLibraryUsage($contentid); } /** * Delete what libraries a content item is using. * Implements deleteLibraryUsage. * * @param int $contentid Content Id of the content we'll be deleting library usage for */ public function deleteLibraryUsage($contentid) { global $DB; $DB->delete_records('h5p_contents_libraries', array('h5pid' => $contentid)); } /** * Saves what libraries the content uses. * Implements saveLibraryUsage. * * @param int $contentid Id identifying the content * @param array $librariesinuse List of libraries the content uses */ public function saveLibraryUsage($contentid, $librariesinuse) { global $DB; $droplibrarycsslist = array(); foreach ($librariesinuse as $dependency) { if (!empty($dependency['library']['dropLibraryCss'])) { $droplibrarycsslist = array_merge($droplibrarycsslist, explode(', ', $dependency['library']['dropLibraryCss'])); } } foreach ($librariesinuse as $dependency) { $dropcss = in_array($dependency['library']['machineName'], $droplibrarycsslist) ? 1 : 0; $DB->insert_record('h5p_contents_libraries', array( 'h5pid' => $contentid, 'libraryid' => $dependency['library']['libraryId'], 'dependencytype' => $dependency['type'], 'dropcss' => $dropcss, 'weight' => $dependency['weight'] )); } } /** * Get number of content/nodes using a library, and the number of dependencies to other libraries. * Implements getLibraryUsage. * * @param int $id Library identifier * @param boolean $skipcontent Optional. Set as true to get number of content instances for library * @return array The array contains two elements, keyed by 'content' and 'libraries'. * Each element contains a number */ public function getLibraryUsage($id, $skipcontent = false) { global $DB; if ($skipcontent) { $content = -1; } else { $sql = "SELECT COUNT(distinct c.id) FROM {h5p_libraries} l JOIN {h5p_contents_libraries} cl ON l.id = cl.libraryid JOIN {h5p} c ON cl.h5pid = c.id WHERE l.id = :libraryid"; $sqlargs = array( 'libraryid' => $id ); $content = $DB->count_records_sql($sql, $sqlargs); } $libraries = $DB->count_records('h5p_library_dependencies', ['requiredlibraryid' => $id]); return array( 'content' => $content, 'libraries' => $libraries, ); } /** * Loads a library. * Implements loadLibrary. * * @param string $machinename The library's machine name * @param int $majorversion The library's major version * @param int $minorversion The library's minor version * @return array|bool Returns FALSE if the library does not exist * Otherwise an associative array containing: * - libraryId: The id of the library if it is an existing library, * - title: The library's name, * - machineName: The library machineName * - majorVersion: The library's majorVersion * - minorVersion: The library's minorVersion * - patchVersion: The library's patchVersion * - runnable: 1 if the library is a content type, 0 otherwise * - fullscreen: 1 if the library supports fullscreen, 0 otherwise * - embedTypes: list of supported embed types * - preloadedJs: comma separated string with js file paths * - preloadedCss: comma separated sting with css file paths * - dropLibraryCss: list of associative arrays containing: * - machineName: machine name for the librarys that are to drop their css * - semantics: Json describing the content structure for the library * - preloadedDependencies(optional): list of associative arrays containing: * - machineName: Machine name for a library this library is depending on * - majorVersion: Major version for a library this library is depending on * - minorVersion: Minor for a library this library is depending on * - dynamicDependencies(optional): list of associative arrays containing: * - machineName: Machine name for a library this library is depending on * - majorVersion: Major version for a library this library is depending on * - minorVersion: Minor for a library this library is depending on */ public function loadLibrary($machinename, $majorversion, $minorversion) { global $DB; $library = $DB->get_record('h5p_libraries', array( 'machinename' => $machinename, 'majorversion' => $majorversion, 'minorversion' => $minorversion )); if (!$library) { return false; } $librarydata = array( 'libraryId' => $library->id, 'title' => $library->title, 'machineName' => $library->machinename, 'majorVersion' => $library->majorversion, 'minorVersion' => $library->minorversion, 'patchVersion' => $library->patchversion, 'runnable' => $library->runnable, 'fullscreen' => $library->fullscreen, 'embedTypes' => $library->embedtypes, 'preloadedJs' => $library->preloadedjs, 'preloadedCss' => $library->preloadedcss, 'dropLibraryCss' => $library->droplibrarycss, 'semantics' => $library->semantics ); $sql = 'SELECT hl.id, hl.machinename, hl.majorversion, hl.minorversion, hll.dependencytype FROM {h5p_library_dependencies} hll JOIN {h5p_libraries} hl ON hll.requiredlibraryid = hl.id WHERE hll.libraryid = :libraryid ORDER BY hl.id ASC'; $sqlargs = array( 'libraryid' => $library->id ); $dependencies = $DB->get_records_sql($sql, $sqlargs); foreach ($dependencies as $dependency) { $librarydata[$dependency->dependencytype . 'Dependencies'][] = array( 'machineName' => $dependency->machinename, 'majorVersion' => $dependency->majorversion, 'minorVersion' => $dependency->minorversion ); } return $librarydata; } /** * Loads library semantics. * Implements loadLibrarySemantics. * * @param string $name Machine name for the library * @param int $majorversion The library's major version * @param int $minorversion The library's minor version * @return string The library's semantics as json */ public function loadLibrarySemantics($name, $majorversion, $minorversion) { global $DB; $semantics = $DB->get_field('h5p_libraries', 'semantics', array( 'machinename' => $name, 'majorversion' => $majorversion, 'minorversion' => $minorversion ) ); return ($semantics === false ? null : $semantics); } /** * Makes it possible to alter the semantics, adding custom fields, etc. * Implements alterLibrarySemantics. * * @param array $semantics Associative array representing the semantics * @param string $name The library's machine name * @param int $majorversion The library's major version * @param int $minorversion The library's minor version */ public function alterLibrarySemantics(&$semantics, $name, $majorversion, $minorversion) { global $PAGE; $renderer = $PAGE->get_renderer('core_h5p'); $renderer->h5p_alter_semantics($semantics, $name, $majorversion, $minorversion); } /** * Delete all dependencies belonging to given library. * Implements deleteLibraryDependencies. * * @param int $libraryid Library identifier */ public function deleteLibraryDependencies($libraryid) { global $DB; $DB->delete_records('h5p_library_dependencies', array('libraryid' => $libraryid)); } /** * Start an atomic operation against the dependency storage. * Implements lockDependencyStorage. */ public function lockDependencyStorage() { // Library development mode not supported. } /** * Start an atomic operation against the dependency storage. * Implements unlockDependencyStorage. */ public function unlockDependencyStorage() { // Library development mode not supported. } /** * Delete a library from database and file system. * Implements deleteLibrary. * * @param \stdClass $library Library object with id, name, major version and minor version */ public function deleteLibrary($library) { $factory = new \core_h5p\factory(); \core_h5p\api::delete_library($factory, $library); } /** * Load content. * Implements loadContent. * * @param int $id Content identifier * @return array Associative array containing: * - id: Identifier for the content * - params: json content as string * - embedType: list of supported embed types * - disable: H5P Button display options * - title: H5P content title * - slug: Human readable content identifier that is unique * - libraryId: Id for the main library * - libraryName: The library machine name * - libraryMajorVersion: The library's majorVersion * - libraryMinorVersion: The library's minorVersion * - libraryEmbedTypes: CSV of the main library's embed types * - libraryFullscreen: 1 if fullscreen is supported. 0 otherwise * - metadata: The content's metadata */ public function loadContent($id) { global $DB; $sql = "SELECT hc.id, hc.jsoncontent, hc.displayoptions, hl.id AS libraryid, hl.machinename, hl.title, hl.majorversion, hl.minorversion, hl.fullscreen, hl.embedtypes, hl.semantics, hc.filtered, hc.pathnamehash FROM {h5p} hc JOIN {h5p_libraries} hl ON hl.id = hc.mainlibraryid WHERE hc.id = :h5pid"; $sqlargs = array( 'h5pid' => $id ); $data = $DB->get_record_sql($sql, $sqlargs); // Return null if not found. if ($data === false) { return null; } // Some databases do not support camelCase, so we need to manually // map the values to the camelCase names used by the H5P core. $content = array( 'id' => $data->id, 'params' => $data->jsoncontent, // It has been decided that the embedtype will be always set to 'iframe' (at least for now) because the 'div' // may cause conflicts with CSS and JS in some cases. 'embedType' => 'iframe', 'disable' => $data->displayoptions, 'title' => $data->title, 'slug' => H5PCore::slugify($data->title) . '-' . $data->id, 'filtered' => $data->filtered, 'libraryId' => $data->libraryid, 'libraryName' => $data->machinename, 'libraryMajorVersion' => $data->majorversion, 'libraryMinorVersion' => $data->minorversion, 'libraryEmbedTypes' => $data->embedtypes, 'libraryFullscreen' => $data->fullscreen, 'metadata' => '', 'pathnamehash' => $data->pathnamehash ); $params = json_decode($data->jsoncontent); if (empty($params->metadata)) { $params->metadata = new \stdClass(); } // Add title to metadata. if (!empty($params->title) && empty($params->metadata->title)) { $params->metadata->title = $params->title; } $content['metadata'] = $params->metadata; $content['params'] = json_encode($params->params ?? $params); return $content; } /** * Load dependencies for the given content of the given type. * Implements loadContentDependencies. * * @param int $id Content identifier * @param int $type The dependency type * @return array List of associative arrays containing: * - libraryId: The id of the library if it is an existing library * - machineName: The library machineName * - majorVersion: The library's majorVersion * - minorVersion: The library's minorVersion * - patchVersion: The library's patchVersion * - preloadedJs(optional): comma separated string with js file paths * - preloadedCss(optional): comma separated sting with css file paths * - dropCss(optional): csv of machine names * - dependencyType: The dependency type */ public function loadContentDependencies($id, $type = null) { global $DB; $query = "SELECT hcl.id AS unidepid, hl.id AS library_id, hl.machinename AS machine_name, hl.majorversion AS major_version, hl.minorversion AS minor_version, hl.patchversion AS patch_version, hl.preloadedcss AS preloaded_css, hl.preloadedjs AS preloaded_js, hcl.dropcss AS drop_css, hcl.dependencytype as dependency_type FROM {h5p_contents_libraries} hcl JOIN {h5p_libraries} hl ON hcl.libraryid = hl.id WHERE hcl.h5pid = :h5pid"; $queryargs = array( 'h5pid' => $id ); if ($type !== null) { $query .= " AND hcl.dependencytype = :dependencytype"; $queryargs['dependencytype'] = $type; } $query .= " ORDER BY hcl.weight"; $data = $DB->get_records_sql($query, $queryargs); $dependencies = array(); foreach ($data as $dependency) { unset($dependency->unidepid); $dependencies[$dependency->machine_name] = H5PCore::snakeToCamel($dependency); } return $dependencies; } /** * Get stored setting. * Implements getOption. * * To avoid updating the cache libraries when using the Hub selector, * {@see \Moodle\H5PEditorAjax::isContentTypeCacheUpdated}, the setting content_type_cache_updated_at * always return the current time. * * @param string $name Identifier for the setting * @param string $default Optional default value if settings is not set * @return mixed Return Whatever has been stored as the setting */ public function getOption($name, $default = false) { if ($name == core::DISPLAY_OPTION_DOWNLOAD || $name == core::DISPLAY_OPTION_EMBED) { // For now, the download and the embed displayoptions are disabled by default, so only will be rendered when // defined in the displayoptions DB field. // This check should be removed if they are added as new H5P settings, to let admins to define the default value. return \Moodle\H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF; } // To avoid update the libraries cache using the Hub selector. if ($name == 'content_type_cache_updated_at') { return time(); } $value = get_config('core_h5p', $name); if ($value === false) { return $default; } return $value; } /** * Stores the given setting. * For example when did we last check h5p.org for updates to our libraries. * Implements setOption. * * @param string $name Identifier for the setting * @param mixed $value Data Whatever we want to store as the setting */ public function setOption($name, $value) { set_config($name, $value, 'core_h5p'); } /** * This will update selected fields on the given content. * Implements updateContentFields(). * * @param int $id Content identifier * @param array $fields Content fields, e.g. filtered */ public function updateContentFields($id, $fields) { global $DB; $content = new \stdClass(); $content->id = $id; foreach ($fields as $name => $value) { // Skip 'slug' as it currently does not exist in the h5p content table. if ($name == 'slug') { continue; } $content->$name = $value; } $DB->update_record('h5p', $content); } /** * Will clear filtered params for all the content that uses the specified. * libraries. This means that the content dependencies will have to be rebuilt and the parameters re-filtered. * Implements clearFilteredParameters(). * * @param array $libraryids Array of library ids */ public function clearFilteredParameters($libraryids) { global $DB; if (empty($libraryids)) { return; } list($insql, $inparams) = $DB->get_in_or_equal($libraryids); $DB->set_field_select('h5p', 'filtered', null, "mainlibraryid $insql", $inparams); } /** * Get number of contents that has to get their content dependencies rebuilt. * and parameters re-filtered. * Implements getNumNotFiltered(). * * @return int The number of contents that has to get their content dependencies rebuilt * and parameters re-filtered */ public function getNumNotFiltered() { global $DB; $sql = "SELECT COUNT(id) FROM {h5p} WHERE " . $DB->sql_compare_text('filtered') . " IS NULL"; return $DB->count_records_sql($sql); } /** * Get number of contents using library as main library. * Implements getNumContent(). * * @param int $libraryid The library ID * @param array $skip The array of h5p content ID's that should be ignored * @return int The number of contents using library as main library */ public function getNumContent($libraryid, $skip = null) { global $DB; $notinsql = ''; $params = array(); if (!empty($skip)) { list($sql, $params) = $DB->get_in_or_equal($skip, SQL_PARAMS_NAMED, 'param', false); $notinsql = " AND id {$sql}"; } $sql = "SELECT COUNT(id) FROM {h5p} WHERE mainlibraryid = :libraryid {$notinsql}"; $params['libraryid'] = $libraryid; return $DB->count_records_sql($sql, $params); } /** * Determines if content slug is used. * Implements isContentSlugAvailable. * * @param string $slug The content slug * @return boolean Whether the content slug is used */ public function isContentSlugAvailable($slug) { // By default the slug should be available as it's currently generated as a unique // value for each h5p content (not stored in the h5p table). return true; } /** * Generates statistics from the event log per library. * Implements getLibraryStats. * * @param string $type Type of event to generate stats for * @return array Number values indexed by library name and version */ public function getLibraryStats($type) { // Event logs are not being stored. } /** * Aggregate the current number of H5P authors. * Implements getNumAuthors. * * @return int The current number of H5P authors */ public function getNumAuthors() { // Currently, H5P authors are not being stored. } /** * Stores hash keys for cached assets, aggregated JavaScripts and * stylesheets, and connects it to libraries so that we know which cache file * to delete when a library is updated. * Implements saveCachedAssets. * * @param string $key Hash key for the given libraries * @param array $libraries List of dependencies(libraries) used to create the key */ public function saveCachedAssets($key, $libraries) { global $DB; foreach ($libraries as $library) { $cachedasset = new \stdClass(); $cachedasset->libraryid = $library['libraryId']; $cachedasset->hash = $key; $DB->insert_record('h5p_libraries_cachedassets', $cachedasset); } } /** * Locate hash keys for given library and delete them. * Used when cache file are deleted. * Implements deleteCachedAssets. * * @param int $libraryid Library identifier * @return array List of hash keys removed */ public function deleteCachedAssets($libraryid) { global $DB; // Get all the keys so we can remove the files. $results = $DB->get_records('h5p_libraries_cachedassets', ['libraryid' => $libraryid]); $hashes = array_map(function($result) { return $result->hash; }, $results); if (!empty($hashes)) { list($sql, $params) = $DB->get_in_or_equal($hashes, SQL_PARAMS_NAMED); // Remove all invalid keys. $DB->delete_records_select('h5p_libraries_cachedassets', 'hash ' . $sql, $params); // Remove also the cachedassets files. $fs = new file_storage(); $fs->deleteCachedAssets($hashes); } return $hashes; } /** * Get the amount of content items associated to a library. * Implements getLibraryContentCount. * * return array The number of content items associated to a library */ public function getLibraryContentCount() { global $DB; $contentcount = array(); $sql = "SELECT h.mainlibraryid, l.machinename, l.majorversion, l.minorversion, COUNT(h.id) AS count FROM {h5p} h LEFT JOIN {h5p_libraries} l ON h.mainlibraryid = l.id GROUP BY h.mainlibraryid, l.machinename, l.majorversion, l.minorversion"; // Count content using the same content type. $res = $DB->get_records_sql($sql); // Extract results. foreach ($res as $lib) { $contentcount["{$lib->machinename} {$lib->majorversion}.{$lib->minorversion}"] = $lib->count; } return $contentcount; } /** * Will trigger after the export file is created. * Implements afterExportCreated. * * @param array $content The content * @param string $filename The file name */ public function afterExportCreated($content, $filename) { // Not being used. } /** * Check whether a user has permissions to execute an action, such as embed H5P content. * Implements hasPermission. * * @param H5PPermission $permission Permission type * @param int $id Id need by platform to determine permission * @return boolean true if the user can execute the action defined in $permission; false otherwise */ public function hasPermission($permission, $id = null) { // H5P capabilities have not been introduced. } /** * Replaces existing content type cache with the one passed in. * Implements replaceContentTypeCache. * * @param object $contenttypecache Json with an array called 'libraries' containing the new content type cache * that should replace the old one */ public function replaceContentTypeCache($contenttypecache) { // Currently, content type caches are not being stored. } /** * Checks if the given library has a higher version. * Implements libraryHasUpgrade. * * @param array $library An associative array containing: * - machineName: The library machineName * - majorVersion: The library's majorVersion * - minorVersion: The library's minorVersion * @return boolean Whether the library has a higher version */ public function libraryHasUpgrade($library) { global $DB; $sql = "SELECT id FROM {h5p_libraries} WHERE machinename = :machinename AND (majorversion > :majorversion1 OR (majorversion = :majorversion2 AND minorversion > :minorversion))"; $results = $DB->get_records_sql( $sql, array( 'machinename' => $library['machineName'], 'majorversion1' => $library['majorVersion'], 'majorversion2' => $library['majorVersion'], 'minorversion' => $library['minorVersion'] ), 0, 1 ); return !empty($results); } /** * Get current H5P language code. * * @return string Language Code */ public static function get_language() { static $map; if (empty($map)) { // Create mapping for "converting" language codes. $map = array( 'no' => 'nb' ); } // Get current language in Moodle. $language = get_html_lang_attribute_value(strtolower(\current_language())); // Try to map. return $map[$language] ?? $language; } /** * Store messages until they can be printed to the current user. * * @param string $type Type of messages, e.g. 'info', 'error', etc * @param string $newmessage The message * @param string $code The message code */ private function set_message(string $type, ?string $newmessage = null, ?string $code = null) { global $SESSION; // We expect to get out an array of strings when getting info // and an array of objects when getting errors for consistency across platforms. // This implementation should be improved for consistency across the data type returned here. if ($type === 'error') { $SESSION->core_h5p_messages[$type][] = (object) array( 'code' => $code, 'message' => $newmessage ); } else { $SESSION->core_h5p_messages[$type][] = $newmessage; } } /** * Convert list of library parameter values to csv. * * @param array $librarydata Library data as found in library.json files * @param string $key Key that should be found in $librarydata * @param string $searchparam The library parameter (Default: 'path') * @return string Library parameter values separated by ', ' */ private function library_parameter_values_to_csv(array $librarydata, string $key, string $searchparam = 'path'): string { if (isset($librarydata[$key])) { $parametervalues = array(); foreach ($librarydata[$key] as $file) { foreach ($file as $index => $value) { if ($index === $searchparam) { $parametervalues[] = $value; } } } return implode(', ', $parametervalues); } return ''; } /** * Get the latest library version. * * @param string $machinename The library's machine name * @return stdClass|null An object with the latest library version */ public function get_latest_library_version(string $machinename): ?\stdClass { global $DB; $libraries = $DB->get_records('h5p_libraries', ['machinename' => $machinename], 'majorversion DESC, minorversion DESC, patchversion DESC', '*', 0, 1); if ($libraries) { return reset($libraries); } return null; } /** * Replace content hub metadata cache * * @param JsonSerializable $metadata Metadata as received from content hub * @param string $lang Language in ISO 639-1 * * @return mixed */ public function replaceContentHubMetadataCache($metadata, $lang) { debugging('The replaceContentHubMetadataCache() method is not implemented.', DEBUG_DEVELOPER); return null; } /** * Get content hub metadata cache from db * * @param string $lang Language code in ISO 639-1 * * @return JsonSerializable Json string */ public function getContentHubMetadataCache($lang = 'en') { debugging('The getContentHubMetadataCache() method is not implemented.', DEBUG_DEVELOPER); return null; } /** * Get time of last content hub metadata check * * @param string $lang Language code iin ISO 639-1 format * * @return string|null Time in RFC7231 format */ public function getContentHubMetadataChecked($lang = 'en') { debugging('The getContentHubMetadataChecked() method is not implemented.', DEBUG_DEVELOPER); return null; } /** * Set time of last content hub metadata check * * @param int|null $time Time in RFC7231 format * @param string $lang Language code iin ISO 639-1 format * * @return bool True if successful */ public function setContentHubMetadataChecked($time, $lang = 'en') { debugging('The setContentHubMetadataChecked() method is not implemented.', DEBUG_DEVELOPER); return false; } } PK*\:CCclasses/editor.phpnu[. /** * H5P editor class. * * @package core_h5p * @copyright 2020 Victor Deniz * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; use core_h5p\local\library\autoloader; use core_h5p\output\h5peditor as editor_renderer; use Moodle\H5PCore; use Moodle\H5peditor; use stdClass; use coding_exception; use MoodleQuickForm; defined('MOODLE_INTERNAL') || die(); /** * H5P editor class, for editing local H5P content. * * @package core_h5p * @copyright 2020 Victor Deniz * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class editor { /** * @var core The H5PCore object. */ private $core; /** * @var H5peditor $h5peditor The H5P Editor object. */ private $h5peditor; /** * @var int Id of the H5P content from the h5p table. */ private $id = null; /** * @var array Existing H5P content instance before edition. */ private $oldcontent = null; /** * @var stored_file File of ane existing H5P content before edition. */ private $oldfile = null; /** * @var array File area to save the file of a new H5P content. */ private $filearea = null; /** * @var string H5P Library name */ private $library = null; /** * Inits the H5P editor. */ public function __construct() { autoloader::register(); $factory = new factory(); $this->h5peditor = $factory->get_editor(); $this->core = $factory->get_core(); } /** * Loads an existing content for edition. * * If the H5P content or its file can't be retrieved, it is not possible to edit the content. * * @param int $id Id of the H5P content from the h5p table. * * @return void */ public function set_content(int $id): void { $this->id = $id; // Load the present content. $this->oldcontent = $this->core->loadContent($id); if ($this->oldcontent === null) { throw new \moodle_exception('invalidelementid'); } // Identify the content type library. $this->library = H5PCore::libraryToString($this->oldcontent['library']); // Get current file and its file area. $pathnamehash = $this->oldcontent['pathnamehash']; $fs = get_file_storage(); $oldfile = $fs->get_file_by_hash($pathnamehash); if (!$oldfile) { throw new \moodle_exception('invalidelementid'); } $this->set_filearea( $oldfile->get_contextid(), $oldfile->get_component(), $oldfile->get_filearea(), $oldfile->get_itemid(), $oldfile->get_filepath(), $oldfile->get_filename(), $oldfile->get_userid() ); $this->oldfile = $oldfile; } /** * Sets the content type library and the file area to create a new H5P content. * * Note: this method must be used to create new content, to edit an existing * H5P content use only set_content with the ID from the H5P table. * * @param string $library Library of the H5P content type to create. * @param int $contextid Context where the file of the H5P content will be stored. * @param string $component Component where the file of the H5P content will be stored. * @param string $filearea File area where the file of the H5P content will be stored. * @param int $itemid Item id file of the H5P content. * @param string $filepath File path where the file of the H5P content will be stored. * @param null|string $filename H5P content file name. * @param null|int $userid H5P content file owner userid (default will use $USER->id). * * @return void */ public function set_library(string $library, int $contextid, string $component, string $filearea, ?int $itemid = 0, string $filepath = '/', ?string $filename = null, ?int $userid = null): void { $this->library = $library; $this->set_filearea($contextid, $component, $filearea, $itemid, $filepath, $filename, $userid); } /** * Sets the Moodle file area where the file of a new H5P content will be stored. * * @param int $contextid Context where the file of the H5P content will be stored. * @param string $component Component where the file of the H5P content will be stored. * @param string $filearea File area where the file of the H5P content will be stored. * @param int $itemid Item id file of the H5P content. * @param string $filepath File path where the file of the H5P content will be stored. * @param null|string $filename H5P content file name. * @param null|int $userid H5P content file owner userid (default will use $USER->id). * * @return void */ private function set_filearea(int $contextid, string $component, string $filearea, int $itemid, string $filepath = '/', ?string $filename = null, ?int $userid = null): void { global $USER; $this->filearea = [ 'contextid' => $contextid, 'component' => $component, 'filearea' => $filearea, 'itemid' => $itemid, 'filepath' => $filepath, 'filename' => $filename, 'userid' => $userid ?? $USER->id, ]; } /** * Adds an H5P editor to a form. * * @param MoodleQuickForm $mform Moodle Quick Form * * @return void */ public function add_editor_to_form(MoodleQuickForm $mform): void { global $PAGE; $this->add_assets_to_page(); $data = $this->data_preprocessing(); // Hidden fields used bu H5P editor. $mform->addElement('hidden', 'h5plibrary', $data->h5plibrary); $mform->setType('h5plibrary', PARAM_RAW); $mform->addElement('hidden', 'h5pparams', $data->h5pparams); $mform->setType('h5pparams', PARAM_RAW); $mform->addElement('hidden', 'h5paction'); $mform->setType('h5paction', PARAM_ALPHANUMEXT); // Render H5P editor. $ui = new editor_renderer($data); $editorhtml = $PAGE->get_renderer('core_h5p')->render($ui); $mform->addElement('html', $editorhtml); } /** * Creates or updates an H5P content. * * @param stdClass $content Object containing all the necessary data. * * @return int Content id */ public function save_content(stdClass $content): int { if (empty($content->h5pparams)) { throw new coding_exception('Missing H5P params.'); } if (!isset($content->h5plibrary)) { throw new coding_exception('Missing H5P library.'); } $content->params = $content->h5pparams; if (!empty($this->oldcontent)) { $content->id = $this->oldcontent['id']; // Get old parameters for comparison. $oldparams = json_decode($this->oldcontent['params']) ?? null; // Keep the existing display options. $content->disable = $this->oldcontent['disable']; $oldlib = $this->oldcontent['library']; } else { $oldparams = null; $oldlib = null; } // Prepare library data to be save. $content->library = H5PCore::libraryFromString($content->h5plibrary); $content->library['libraryId'] = $this->core->h5pF->getLibraryId($content->library['machineName'], $content->library['majorVersion'], $content->library['minorVersion']); // Prepare current parameters. $params = json_decode($content->params); $modified = false; if (empty($params->metadata)) { $params->metadata = new stdClass(); $modified = true; } if (empty($params->metadata->title)) { // Use a default string if not available. $params->metadata->title = 'Untitled'; $modified = true; } if (!isset($content->title)) { $content->title = $params->metadata->title; } if ($modified) { $content->params = json_encode($params); } // Save content. $content->id = $this->core->saveContent((array)$content); // Move any uploaded images or files. Determine content dependencies. $this->h5peditor->processParameters($content, $content->library, $params->params, $oldlib, $oldparams); $this->update_h5p_file($content); return $content->id; } /** * Creates or updates the H5P file and the related database data. * * @param stdClass $content Object containing all the necessary data. * * @return void */ private function update_h5p_file(stdClass $content): void { global $USER; // Keep title before filtering params. $title = $content->title; $contentarray = $this->core->loadContent($content->id); $contentarray['title'] = $title; // Generates filtered params and export file. $this->core->filterParameters($contentarray); $slug = isset($contentarray['slug']) ? $contentarray['slug'] . '-' : ''; $filename = $contentarray['id'] ?? $contentarray['title']; $filename = $slug . $filename . '.h5p'; $file = $this->core->fs->get_export_file($filename); $fs = get_file_storage(); if ($file) { $fields['contenthash'] = $file->get_contenthash(); // Create or update H5P file. if (empty($this->filearea['filename'])) { $this->filearea['filename'] = $contentarray['slug'] . '.h5p'; } if (!empty($this->oldfile)) { $this->oldfile->replace_file_with($file); $newfile = $this->oldfile; } else { $newfile = $fs->create_file_from_storedfile($this->filearea, $file); } if (empty($this->oldcontent)) { $pathnamehash = $newfile->get_pathnamehash(); } else { $pathnamehash = $this->oldcontent['pathnamehash']; } // Update hash fields in the h5p table. $fields['pathnamehash'] = $pathnamehash; $this->core->h5pF->updateContentFields($contentarray['id'], $fields); } } /** * Add required assets for displaying the editor. * * @return void * @throws coding_exception If page header is already printed. */ private function add_assets_to_page(): void { global $PAGE, $CFG; if ($PAGE->headerprinted) { throw new coding_exception('H5P assets cannot be added when header is already printed.'); } $context = \context_system::instance(); $settings = helper::get_core_assets(); // Use jQuery and styles from core. $assets = [ 'css' => $settings['core']['styles'], 'js' => $settings['core']['scripts'] ]; // Use relative URL to support both http and https. $url = autoloader::get_h5p_editor_library_url()->out(); $url = '/' . preg_replace('/^[^:]+:\/\/[^\/]+\//', '', $url); // Make sure files are reloaded for each plugin update. $cachebuster = helper::get_cache_buster(); // Add editor styles. foreach (H5peditor::$styles as $style) { $assets['css'][] = $url . $style . $cachebuster; } // Add editor JavaScript. foreach (H5peditor::$scripts as $script) { // We do not want the creator of the iframe inside the iframe. if ($script !== 'scripts/h5peditor-editor.js') { $assets['js'][] = $url . $script . $cachebuster; } } // Add JavaScript with library framework integration (editor part). $PAGE->requires->js(autoloader::get_h5p_editor_library_url('scripts/h5peditor-editor.js' . $cachebuster), true); $PAGE->requires->js(autoloader::get_h5p_editor_library_url('scripts/h5peditor-init.js' . $cachebuster), true); // Load editor translations. $language = framework::get_language(); $editorstrings = $this->get_editor_translations($language); $PAGE->requires->data_for_js('H5PEditor.language.core', $editorstrings, false); // Add JavaScript settings. $root = $CFG->wwwroot; $filespathbase = \moodle_url::make_draftfile_url(0, '', ''); $factory = new factory(); $contentvalidator = $factory->get_content_validator(); $editorajaxtoken = core::createToken(editor_ajax::EDITOR_AJAX_TOKEN); $sesskey = sesskey(); $settings['editor'] = [ 'filesPath' => $filespathbase->out(), 'fileIcon' => [ 'path' => $url . 'images/binary-file.png', 'width' => 50, 'height' => 50, ], 'ajaxPath' => $CFG->wwwroot . "/h5p/ajax.php?sesskey={$sesskey}&token={$editorajaxtoken}&action=", 'libraryUrl' => $url, 'copyrightSemantics' => $contentvalidator->getCopyrightSemantics(), 'metadataSemantics' => $contentvalidator->getMetadataSemantics(), 'assets' => $assets, 'apiVersion' => H5PCore::$coreApi, 'language' => $language, ]; if (!empty($this->id)) { $settings['editor']['nodeVersionId'] = $this->id; // Override content URL. $contenturl = "{$root}/pluginfile.php/{$context->id}/core_h5p/content/{$this->id}"; $settings['contents']['cid-' . $this->id]['contentUrl'] = $contenturl; } $PAGE->requires->data_for_js('H5PIntegration', $settings, true); } /** * Get editor translations for the defined language. * Check if the editor strings have been translated in Moodle. * If the strings exist, they will override the existing ones in the JS file. * * @param string $language The language for the translations to be returned. * @return array The editor string translations. */ private function get_editor_translations(string $language): array { global $CFG; // Add translations. $languagescript = "language/{$language}.js"; if (!file_exists("{$CFG->dirroot}" . autoloader::get_h5p_editor_library_base($languagescript))) { $languagescript = 'language/en.js'; } // Check if the editor strings have been translated in Moodle. // If the strings exist, they will override the existing ones in the JS file. // Get existing strings from current JS language file. $langcontent = file_get_contents("{$CFG->dirroot}" . autoloader::get_h5p_editor_library_base($languagescript)); // Get only the content between { } (for instance, ; at the end of the file has to be removed). $langcontent = substr($langcontent, 0, strpos($langcontent, '}', -0) + 1); $langcontent = substr($langcontent, strpos($langcontent, '{')); // Parse the JS language content and get a PHP array. $editorstrings = helper::parse_js_array($langcontent); foreach ($editorstrings as $key => $value) { $stringkey = 'editor:'.strtolower(trim($key)); $value = autoloader::get_h5p_string($stringkey, $language); if (!empty($value)) { $editorstrings[$key] = $value; } } return $editorstrings; } /** * Preprocess the data sent through the form to the H5P JS Editor Library. * * @return stdClass */ private function data_preprocessing(): stdClass { $defaultvalues = [ 'id' => $this->id, 'h5plibrary' => $this->library, ]; // In case both contentid and library have values, content(edition) takes precedence over library(creation). if (empty($this->oldcontent)) { $maincontentdata = ['params' => (object)[]]; } else { $params = $this->core->filterParameters($this->oldcontent); $maincontentdata = ['params' => json_decode($params)]; if (isset($this->oldcontent['metadata'])) { $maincontentdata['metadata'] = $this->oldcontent['metadata']; } } $defaultvalues['h5pparams'] = json_encode($maincontentdata, true); return (object) $defaultvalues; } } PK*\h4M4Mclasses/helper.phpnu[. /** * Contains helper class for the H5P area. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; use context_system; use core_h5p\local\library\autoloader; use core_user; defined('MOODLE_INTERNAL') || die(); /** * Helper class for the H5P area. * * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class helper { /** * Store an H5P file. * * @param factory $factory The \core_h5p\factory object * @param \stored_file $file Moodle file instance * @param \stdClass $config Button options config * @param bool $onlyupdatelibs Whether new libraries can be installed or only the existing ones can be updated * @param bool $skipcontent Should the content be skipped (so only the libraries will be saved)? * * @return int|false|null The H5P identifier or null if there is an error when saving or false if it's not a valid H5P package */ public static function save_h5p(factory $factory, \stored_file $file, \stdClass $config, bool $onlyupdatelibs = false, bool $skipcontent = false) { if (api::is_valid_package($file, $onlyupdatelibs, $skipcontent, $factory, false)) { $core = $factory->get_core(); $h5pvalidator = $factory->get_validator(); $h5pstorage = $factory->get_storage(); $content = [ 'pathnamehash' => $file->get_pathnamehash(), 'contenthash' => $file->get_contenthash(), ]; $options = ['disable' => self::get_display_options($core, $config)]; // Add the 'title' if exists from 'h5p.json' data to keep it for the editor. if (!empty($h5pvalidator->h5pC->mainJsonData['title'])) { $content['title'] = $h5pvalidator->h5pC->mainJsonData['title']; } // If exists, add the metadata from 'h5p.json' to avoid loosing this information. $data = $h5pvalidator->h5pC->mainJsonData; if (!empty($data)) { // The metadata fields are defined in 'joubel/core/h5p-metadata.class.php'. $metadatafields = [ 'title', 'a11yTitle', 'changes', 'authors', 'source', 'license', 'licenseVersion', 'licenseExtras', 'authorComments', 'yearFrom', 'yearTo', 'defaultLanguage', ]; $content['metadata'] = array_reduce($metadatafields, function ($array, $field) use ($data) { if (array_key_exists($field, $data)) { $array[$field] = $data[$field]; } return $array; }, []); } $h5pstorage->savePackage($content, null, $skipcontent, $options); return $h5pstorage->contentId; } return false; } /** * Get the error messages stored in our H5P framework. * * @param \stdClass $messages The error, exception and info messages, raised while preparing and running an H5P content. * @param factory $factory The \core_h5p\factory object * * @return \stdClass with framework error messages. */ public static function get_messages(\stdClass $messages, factory $factory): \stdClass { $core = $factory->get_core(); // Check if there are some errors and store them in $messages. if (empty($messages->error)) { $messages->error = $core->h5pF->getMessages('error') ?: false; } else { $messages->error = array_merge($messages->error, $core->h5pF->getMessages('error')); } if (empty($messages->info)) { $messages->info = $core->h5pF->getMessages('info') ?: false; } else { $messages->info = array_merge($messages->info, $core->h5pF->getMessages('info')); } return $messages; } /** * Get the representation of display options as int. * * @param core $core The \core_h5p\core object * @param stdClass $config Button options config * * @return int The representation of display options as int */ public static function get_display_options(core $core, \stdClass $config): int { $export = isset($config->export) ? $config->export : 0; $embed = isset($config->embed) ? $config->embed : 0; $copyright = isset($config->copyright) ? $config->copyright : 0; $frame = ($export || $embed || $copyright); if (!$frame) { $frame = isset($config->frame) ? $config->frame : 0; } $disableoptions = [ core::DISPLAY_OPTION_FRAME => $frame, core::DISPLAY_OPTION_DOWNLOAD => $export, core::DISPLAY_OPTION_EMBED => $embed, core::DISPLAY_OPTION_COPYRIGHT => $copyright, ]; return $core->getStorableDisplayOptions($disableoptions, 0); } /** * Convert the int representation of display options into stdClass * * @param core $core The \core_h5p\core object * @param int $displayint integer value representing display options * * @return int The representation of display options as int */ public static function decode_display_options(core $core, ?int $displayint = null): \stdClass { $config = new \stdClass(); if ($displayint === null) { $displayint = self::get_display_options($core, $config); } $displayarray = $core->getDisplayOptionsForEdit($displayint); $config->export = $displayarray[core::DISPLAY_OPTION_DOWNLOAD] ?? 0; $config->embed = $displayarray[core::DISPLAY_OPTION_EMBED] ?? 0; $config->copyright = $displayarray[core::DISPLAY_OPTION_COPYRIGHT] ?? 0; return $config; } /** * Checks if the author of the .h5p file is "trustable". If the file hasn't been uploaded by a user with the * required capability, the content won't be deployed, unless the user has been deleted, in this * case we check the capability against current user. * * @param stored_file $file The .h5p file to be deployed * @return bool Returns true if the file can be deployed, false otherwise. */ public static function can_deploy_package(\stored_file $file): bool { $userid = $file->get_userid(); if (null === $userid) { // If there is no userid, it is owned by the system. return true; } $context = \context::instance_by_id($file->get_contextid()); $fileuser = core_user::get_user($userid); if (empty($fileuser) || $fileuser->deleted) { $userid = null; } return has_capability('moodle/h5p:deploy', $context, $userid); } /** * Checks if the content-type libraries can be upgraded. * The H5P content-type libraries can only be upgraded if the author of the .h5p file can manage content-types or if all the * content-types exist, to avoid users without the required capability to upload malicious content. If user has been deleted * we check against current user. * * @param stored_file $file The .h5p file to be deployed * @return bool Returns true if the content-type libraries can be created/updated, false otherwise. */ public static function can_update_library(\stored_file $file): bool { $userid = $file->get_userid(); if (null === $userid) { // If there is no userid, it is owned by the system. return true; } // Check if the owner of the .h5p file has the capability to manage content-types. $context = \context::instance_by_id($file->get_contextid()); $fileuser = core_user::get_user($userid); if (empty($fileuser) || $fileuser->deleted) { $userid = null; } return has_capability('moodle/h5p:updatelibraries', $context, $userid); } /** * Convenience to take a fixture test file and create a stored_file. * * @param string $filepath The filepath of the file * @param int $userid The author of the file * @param \context $context The context where the file will be created * @return \stored_file The file created */ public static function create_fake_stored_file_from_path(string $filepath, int $userid = 0, ?\context $context = null): \stored_file { if (is_null($context)) { $context = context_system::instance(); } $filerecord = [ 'contextid' => $context->id, 'component' => 'core_h5p', 'filearea' => 'unittest', 'itemid' => rand(), 'filepath' => '/', 'filename' => basename($filepath), ]; if (!is_null($userid)) { $filerecord['userid'] = $userid; } $fs = get_file_storage(); return $fs->create_file_from_pathname($filerecord, $filepath); } /** * Get information about different H5P tools and their status. * * @return array Data to render by the template */ public static function get_h5p_tools_info(): array { $tools = array(); // Getting information from available H5P tools one by one because their enabled/disabled options are totally different. // Check the Display H5P filter status. $link = \core\plugininfo\filter::get_manage_url(); $status = filter_get_active_state('displayh5p', context_system::instance()->id); $tools[] = self::convert_info_into_array('filter_displayh5p', $link, $status); // Check H5P scheduled task. $link = ''; $status = 0; $statusaction = ''; if ($task = \core\task\manager::get_scheduled_task('\core\task\h5p_get_content_types_task')) { $status = !$task->get_disabled(); $link = new \moodle_url( '/admin/tool/task/scheduledtasks.php', array('action' => 'edit', 'task' => get_class($task)) ); if ($status && \core\task\manager::is_runnable() && get_config('tool_task', 'enablerunnow')) { $statusaction = \html_writer::link( new \moodle_url('/admin/tool/task/schedule_task.php', array('task' => get_class($task))), get_string('runnow', 'tool_task')); } } $tools[] = self::convert_info_into_array('task_h5p', $link, $status, $statusaction); return $tools; } /** * Convert information into needed mustache template data array * @param string $tool The name of the tool * @param \moodle_url $link The URL to management page * @param int $status The current status of the tool * @param string $statusaction A link to 'Run now' option for the task * @return array */ private static function convert_info_into_array(string $tool, \moodle_url $link, int $status, string $statusaction = ''): array { $statusclasses = array( TEXTFILTER_DISABLED => 'badge bg-danger text-white', TEXTFILTER_OFF => 'badge bg-warning text-dark', 0 => 'badge bg-danger text-white', TEXTFILTER_ON => 'badge bg-success text-white', ); $statuschoices = array( TEXTFILTER_DISABLED => get_string('disabled', 'admin'), TEXTFILTER_OFF => get_string('offbutavailable', 'core_filters'), 0 => get_string('disabled', 'admin'), 1 => get_string('enabled', 'admin'), ); return [ 'tool' => get_string($tool, 'h5p'), 'tool_description' => get_string($tool . '_description', 'h5p'), 'link' => $link, 'status' => $statuschoices[$status], 'status_class' => $statusclasses[$status], 'status_action' => $statusaction, ]; } /** * Get a query string with the theme revision number to include at the end * of URLs. This is used to force the browser to reload the asset when the * theme caches are cleared. * * @return string */ public static function get_cache_buster(): string { global $CFG; return '?ver=' . $CFG->themerev; } /** * Get the settings needed by the H5P library. * * @param string|null $component * @return array The settings. */ public static function get_core_settings(?string $component = null): array { global $CFG, $USER; $basepath = $CFG->wwwroot . '/'; $systemcontext = context_system::instance(); // H5P doesn't currently support xAPI State. It implements a mechanism in contentUserDataAjax() in h5p.js to update user // data. However, in our case, we're overriding this method to call the xAPI State web services. $ajaxpaths = [ 'contentUserData' => '', ]; $factory = new factory(); $core = $factory->get_core(); // When there is a logged in user, her information will be passed to the player. It will be used for tracking. $usersettings = []; if (isloggedin()) { $usersettings['name'] = fullname($USER, has_capability('moodle/site:viewfullnames', $systemcontext)); $usersettings['id'] = $USER->id; } $savefreq = false; if ($component !== null && get_config($component, 'enablesavestate')) { $savefreq = get_config($component, 'savestatefreq'); } $settings = array( 'baseUrl' => $basepath, 'url' => "{$basepath}pluginfile.php/{$systemcontext->instanceid}/core_h5p", 'urlLibraries' => "{$basepath}pluginfile.php/{$systemcontext->id}/core_h5p/libraries", 'postUserStatistics' => false, 'ajax' => $ajaxpaths, 'saveFreq' => $savefreq, 'siteUrl' => $CFG->wwwroot, 'l10n' => array('H5P' => $core->getLocalization()), 'user' => $usersettings, 'hubIsEnabled' => false, 'reportingIsEnabled' => false, 'crossorigin' => !empty($CFG->h5pcrossorigin) ? $CFG->h5pcrossorigin : null, 'libraryConfig' => $core->h5pF->getLibraryConfig(), 'pluginCacheBuster' => self::get_cache_buster(), 'libraryUrl' => autoloader::get_h5p_core_library_url('js')->out(), ); return $settings; } /** * Get the core H5P assets, including all core H5P JavaScript and CSS. * * @param string|null $component * @return Array core H5P assets. */ public static function get_core_assets(?string $component = null): array { global $PAGE; // Get core settings. $settings = self::get_core_settings($component); $settings['core'] = [ 'styles' => [], 'scripts' => [] ]; $settings['loadedJs'] = []; $settings['loadedCss'] = []; // Make sure files are reloaded for each plugin update. $cachebuster = self::get_cache_buster(); // Use relative URL to support both http and https. $liburl = autoloader::get_h5p_core_library_url()->out(); $relpath = '/' . preg_replace('/^[^:]+:\/\/[^\/]+\//', '', $liburl); // Add core stylesheets. foreach (core::$styles as $style) { $settings['core']['styles'][] = $relpath . $style . $cachebuster; $PAGE->requires->css(new \moodle_url($liburl . $style . $cachebuster)); } // Add core JavaScript. foreach (core::get_scripts() as $script) { $settings['core']['scripts'][] = $script->out(false); $PAGE->requires->js($script, true); } return $settings; } /** * Prepare the library name to be used as a cache key (remove whitespaces and replace dots to underscores). * * @param string $library Library name. * @return string Library name in a cache simple key format (a-zA-Z0-9_). */ public static function get_cache_librarykey(string $library): string { // Remove whitespaces and replace '.' to '_'. return str_replace('.', '_', str_replace(' ', '', $library)); } /** * Parse a JS array to a PHP array. * * @param string $jscontent The JS array to parse to PHP array. * @return array The JS array converted to PHP array. */ public static function parse_js_array(string $jscontent): array { // Convert all line-endings to UNIX format first. $jscontent = str_replace(array("\r\n", "\r"), "\n", $jscontent); $jsarray = preg_split('/,\n\s+/', substr($jscontent, 0, -1)); $jsarray = preg_replace('~{?\\n~', '', $jsarray); $strings = []; foreach ($jsarray as $key => $value) { $splitted = explode(":", $value, 2); $value = preg_replace("/^['|\"](.*)['|\"]$/", "$1", trim($splitted[1], ' ,')); $strings[ trim($splitted[0]) ] = str_replace("\'", "'", $value); } return $strings; } /** * Get the information related to the H5P export file. * The information returned will be: * - filename, filepath, mimetype, filesize, timemodified and fileurl. * * @param string $exportfilename The H5P export filename (with slug). * @param \moodle_url $url The URL of the exported file. * @param factory $factory The \core_h5p\factory object * @return array|null The information export file otherwise null. */ public static function get_export_info(string $exportfilename, ?\moodle_url $url = null, ?factory $factory = null): ?array { if (!$factory) { $factory = new factory(); } $core = $factory->get_core(); // Get export file. if (!$fileh5p = $core->fs->get_export_file($exportfilename)) { return null; } // Build the export info array. $file = []; $file['filename'] = $fileh5p->get_filename(); $file['filepath'] = $fileh5p->get_filepath(); $file['mimetype'] = $fileh5p->get_mimetype(); $file['filesize'] = $fileh5p->get_filesize(); $file['timemodified'] = $fileh5p->get_timemodified(); if (!$url) { $url = \moodle_url::make_webservice_pluginfile_url( $fileh5p->get_contextid(), $fileh5p->get_component(), $fileh5p->get_filearea(), '', '', $fileh5p->get_filename() ); } $file['fileurl'] = $url->out(false); return $file; } } PK*\eW5W5classes/editor_framework.phpnu[. /** * Class \core_h5p\editor_framework * * @package core_h5p * @copyright 2020 Victor Deniz , base on code by Joubel AS * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; use Moodle\H5peditorStorage; use stdClass; /** * Moodle's implementation of the H5P Editor storage interface. * * Makes it possible for the editor's core library to communicate with the * database used by Moodle. * * @package core_h5p * @copyright 2020 Victor Deniz , base on code by Joubel AS * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class editor_framework implements H5peditorStorage { /** * Retrieve library language file from file storage. Note that parent languages will also be checked until a matching * record is found (e.g. "de_kids" -> "de_du" -> "de") * * @param string $name * @param int $major * @param int $minor * @param string $lang * @return stdClass|bool Translation record if available, false otherwise */ private function get_language_record(string $name, int $major, int $minor, string $lang) { global $DB; $params = [ file_storage::COMPONENT, file_storage::LIBRARY_FILEAREA, ]; $sqllike = $DB->sql_like('f.filepath', '?'); $params[] = '%language%'; $sql = "SELECT hl.id, f.pathnamehash FROM {h5p_libraries} hl LEFT JOIN {files} f ON hl.id = f.itemid AND f.component = ? AND f.filearea = ? AND $sqllike WHERE ((hl.machinename = ? AND hl.majorversion = ? AND hl.minorversion = ?) AND f.filename = ?) ORDER BY hl.patchversion DESC"; $params[] = $name; $params[] = $major; $params[] = $minor; $params[] = $lang.'.json'; // Add translations, based initially on the given H5P language code. If missing then recurse language dependencies // until we find a matching H5P language file. $result = $DB->get_record_sql($sql, $params); if ($result === false) { // Normalise Moodle language using underscore, as opposed to H5P which uses dash. $moodlelanguage = str_replace('-', '_', $lang); $dependencies = get_string_manager()->get_language_dependencies($moodlelanguage); // If current language has a dependency, then request it. if (count($dependencies) > 1) { $parentlanguage = get_html_lang_attribute_value($dependencies[count($dependencies) - 2]); $result = $this->get_language_record($name, $major, $minor, $parentlanguage); } } return $result; } /** * Load language file(JSON). * Used to translate the editor fields(title, description etc.) * * @param string $name The machine readable name of the library(content type) * @param int $major Major part of version number * @param int $minor Minor part of version number * @param string $lang Language code * * @return string|boolean Translation in JSON format if available, false otherwise */ public function getLanguage($name, $major, $minor, $lang) { // Check if this information has been saved previously into the cache. $langcache = \cache::make('core', 'h5p_content_type_translations'); $library = new stdClass(); $library->machinename = $name; $library->majorversion = $major; $library->minorversion = $minor; $librarykey = helper::get_cache_librarykey(core::record_to_string($library)); $cachekey = "{$librarykey}/{$lang}"; $translation = $langcache->get($cachekey); if ($translation !== false) { // When there is no translation we store it in the cache as `null`. // This API requires it be returned as `false`. if ($translation === null) { return false; } return $translation; } // Get the language file for this library. $result = $this->get_language_record($name, $major, $minor, $lang); if (empty($result)) { // Save the fact that there is no translation into the cache. // The cache API cannot handle setting a literal `false` value so conver to `null` instead. $langcache->set($cachekey, null); return false; } // Save translation into the cache, and return its content. $fs = get_file_storage(); $file = $fs->get_file_by_hash($result->pathnamehash); $translation = $file->get_content(); $langcache->set($cachekey, $translation); return $translation; } /** * Load a list of available language codes. * * Until translations is implemented, only returns the "en" language. * * @param string $machinename The machine readable name of the library(content type) * @param int $major Major part of version number * @param int $minor Minor part of version number * * @return array List of possible language codes */ public function getAvailableLanguages($machinename, $major, $minor): array { global $DB; // Check if this information has been saved previously into the cache. $langcache = \cache::make('core', 'h5p_content_type_translations'); $library = new stdClass(); $library->machinename = $machinename; $library->majorversion = $major; $library->minorversion = $minor; $librarykey = helper::get_cache_librarykey(core::record_to_string($library)); $languages = $langcache->get($librarykey); if ($languages) { // This contains a list of all of the available languages for the library. return $languages; } // Get the language files for this library. $params = [ file_storage::COMPONENT, file_storage::LIBRARY_FILEAREA, ]; $filepathsqllike = $DB->sql_like('f.filepath', '?'); $params[] = '%language%'; $filenamesqllike = $DB->sql_like('f.filename', '?'); $params[] = '%.json'; $sql = "SELECT DISTINCT f.filename FROM {h5p_libraries} hl LEFT JOIN {files} f ON hl.id = f.itemid AND f.component = ? AND f.filearea = ? AND $filepathsqllike AND $filenamesqllike WHERE hl.machinename = ? AND hl.majorversion = ? AND hl.minorversion = ?"; $params[] = $machinename; $params[] = $major; $params[] = $minor; $defaultcode = 'en'; $languages = []; $results = $DB->get_recordset_sql($sql, $params); if ($results->valid()) { // Extract the code language from the JS language files. foreach ($results as $result) { if (!empty($result->filename)) { $lang = substr($result->filename, 0, -5); $languages[$lang] = $languages; } } $results->close(); // Semantics is 'en' by default. It has to be added always. if (!array_key_exists($defaultcode, $languages)) { $languages = array_keys($languages); array_unshift($languages, $defaultcode); } } else { $results->close(); $params = [ 'machinename' => $machinename, 'majorversion' => $major, 'minorversion' => $minor, ]; if ($DB->record_exists('h5p_libraries', $params)) { // If the library exists (but it doesn't contain any language file), at least defaultcode should be returned. $languages[] = $defaultcode; } } // Save available languages into the cache. $langcache->set($librarykey, $languages); return $languages; } /** * "Callback" for mark the given file as a permanent file. * * Used when saving content that has new uploaded files. * * @param int $fileid */ public function keepFile($fileid): void { // Temporal files will be removed on a task when they are in the "editor" file area and and are at least one day older. } /** * Return libraries details. * * Two use cases: * 1. No input, will list all the available content types. * 2. Libraries supported are specified, load additional data and verify * that the content types are available. Used by e.g. the Presentation Tool * Editor that already knows which content types are supported in its * slides. * * @param array $libraries List of library names + version to load info for. * * @return array List of all libraries loaded. */ public function getLibraries($libraries = null): ?array { if ($libraries !== null) { // Get details for the specified libraries. $librariesin = []; $fields = 'title, runnable, metadatasettings, example, tutorial'; foreach ($libraries as $library) { $params = [ 'machinename' => $library->name, 'majorversion' => $library->majorVersion, 'minorversion' => $library->minorVersion ]; $details = api::get_library_details($params, true, $fields); if ($details) { $library->title = $details->title; $library->runnable = $details->runnable; $library->metadataSettings = json_decode($details->metadatasettings ?? ''); $library->example = $details->example; $library->tutorial = $details->tutorial; $librariesin[] = $library; } } } else { $fields = 'id, machinename as name, title, majorversion, minorversion, metadatasettings, example, tutorial'; $librariesin = api::get_contenttype_libraries($fields); } return $librariesin; } /** * Allow for other plugins to decide which styles and scripts are attached. * * This is useful for adding and/or modifying the functionality and look of * the content types. * * @param array $files List of files as objects with path and version as properties. * @param array $libraries List of libraries indexed by machineName with objects as values. The objects have majorVersion and * minorVersion as properties. */ public function alterLibraryFiles(&$files, $libraries): void { global $PAGE; // Refactor dependency list. $librarylist = []; foreach ($libraries as $dependency) { $librarylist[$dependency['machineName']] = [ 'majorVersion' => $dependency['majorVersion'], 'minorVersion' => $dependency['minorVersion'] ]; } $renderer = $PAGE->get_renderer('core_h5p'); $embedtype = 'editor'; $renderer->h5p_alter_scripts($files['scripts'], $librarylist, $embedtype); $renderer->h5p_alter_styles($files['styles'], $librarylist, $embedtype); } /** * Saves a file or moves it temporarily. * * This is often necessary in order to validate and store uploaded or fetched H5Ps. * * @param string $data Uri of data that should be saved as a temporary file. * @param bool $movefile Can be set to TRUE to move the data instead of saving it. * * @return bool|object Returns false if saving failed or an object with path * of the directory and file that is temporarily saved. */ public static function saveFileTemporarily($data, $movefile = false) { // This is to be implemented when the Hub client is used to upload libraries. return false; } /** * Marks a file for later cleanup. * * Useful when files are not instantly cleaned up. E.g. for files that are uploaded through the editor. * * @param int $file Id of file that should be cleaned up * @param int|null $contentid Content id of file */ public static function markFileForCleanup($file, $contentid = null): ?int { // Temporal files will be removed on a task when they are in the "editor" file area and and are at least one day older. return null; } /** * Clean up temporary files * * @param string $filepath Path to file or directory */ public static function removeTemporarilySavedFiles($filepath): void { // This is to be implemented when the Hub client is used to upload libraries. } } PK*\QyMMclasses/factory.phpnu[. /** * H5P factory class. * This class is used to decouple the construction of H5P related objects. * * @package core_h5p * @copyright 2019 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; defined('MOODLE_INTERNAL') || die(); use core_h5p\local\library\autoloader; use Moodle\H5PContentValidator as content_validator; use Moodle\H5peditor; use Moodle\H5PStorage as storage; use Moodle\H5PValidator as validator; /** * H5P factory class. * This class is used to decouple the construction of H5P related objects. * * @package core_h5p * @copyright 2019 Mihail Geshoski * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class factory { /** @var \core_h5p\local\library\autoloader The autoloader */ protected $autoloader; /** @var \core_h5p\core The Moodle H5PCore implementation */ protected $core; /** @var \core_h5p\framework The Moodle H5PFramework implementation */ protected $framework; /** @var \core_h5p\file_storage The Moodle H5PStorage implementation */ protected $storage; /** @var validator The Moodle H5PValidator implementation */ protected $validator; /** @var content_validator The Moodle H5PContentValidator implementation */ protected $content_validator; /** @var editor_framework The Moodle H5peditorStorage implementation */ protected $editorframework; /** @var H5peditor */ protected $editor; /** @var editor_ajax The Moodle H5PEditorAjaxInterface implementation */ protected $editorajaxinterface; /** * factory constructor. */ public function __construct() { // Loading classes we need from H5P third party library. $this->autoloader = new autoloader(); autoloader::register(); } /** * Returns an instance of the \core_h5p\local\library\autoloader class. * * @return \core_h5p\local\library\autoloader */ public function get_autoloader(): autoloader { return $this->autoloader; } /** * Returns an instance of the \core_h5p\framework class. * * @return \core_h5p\framework */ public function get_framework(): framework { if (null === $this->framework) { $this->framework = new framework(); } return $this->framework; } /** * Returns an instance of the \core_h5p\core class. * * @return \core_h5p\core */ public function get_core(): core { if (null === $this->core) { $fs = new \core_h5p\file_storage(); $language = \core_h5p\framework::get_language(); $context = \context_system::instance(); $url = \moodle_url::make_pluginfile_url($context->id, 'core_h5p', '', null, '', '')->out(); $this->core = new core($this->get_framework(), $fs, $url, $language, true); } return $this->core; } /** * Returns an instance of the H5PStorage class. * * @return \Moodle\H5PStorage */ public function get_storage(): storage { if (null === $this->storage) { $this->storage = new storage($this->get_framework(), $this->get_core()); } return $this->storage; } /** * Returns an instance of the H5PValidator class. * * @return \Moodle\H5PValidator */ public function get_validator(): validator { if (null === $this->validator) { $this->validator = new validator($this->get_framework(), $this->get_core()); } return $this->validator; } /** * Returns an instance of the H5PContentValidator class. * * @return Moodle\H5PContentValidator */ public function get_content_validator(): content_validator { if (null === $this->content_validator) { $this->content_validator = new content_validator($this->get_framework(), $this->get_core()); } return $this->content_validator; } /** * Returns an instance of H5Peditor class. * * @return H5peditor */ public function get_editor(): H5peditor { if (null === $this->editor) { if (empty($this->editorframework)) { $this->editorframework = new editor_framework(); } if (empty($this->editorajaxinterface)) { $this->editorajaxinterface = new editor_ajax(); } if (empty($this->editor)) { $this->editor = new H5peditor($this->get_core(), $this->editorframework, $this->editorajaxinterface); } } return $this->editor; } } PK*\6 classes/output/renderer.phpnu[. namespace core_h5p\output; use plugin_renderer_base; /** * Renderer class. * * @package core_h5p * @copyright 2020 Victor Deniz {victor@moodle.com} * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class renderer extends plugin_renderer_base { /** * Alter which stylesheets are loaded for H5P. * This is useful for adding custom styles or replacing existing ones. * * This method can be overridden by other themes if the styles must be loaded from * a different place than the "Raw initial SCSS" and "Raw SCSS" theme settings. * * @param \stdClass[] $styles List of stylesheets that will be loaded * @param array $libraries Array of libraries indexed by the library's machineName * @param string $embedtype Possible values: div, iframe, external, editor */ public function h5p_alter_styles(&$styles, array $libraries, string $embedtype) { $customcss = \core_h5p\file_storage::get_custom_styles(); if (!empty($customcss)) { // Add the CSS file to the styles array, to load it from the H5P player. $styles[] = (object) [ 'path' => $customcss['cssurl']->out(), 'version' => '?ver='.$customcss['cssversion'], ]; } } /** * Alter which scripts are loaded for H5P. * This is useful for adding custom scripts or replacing existing ones. * * @param array|object $scripts List of JavaScripts that will be loaded * @param array $libraries Array of libraries indexed by the library's machineName * @param string $embedtype Possible values: div, iframe, external, editor */ public function h5p_alter_scripts(&$scripts, array $libraries, string $embedtype) { } /** * Alter semantics before they are processed. This is useful for changing * how the editor looks and how content parameters are filtered. * * @param object|object $semantics Semantics as object * @param string $name Machine name of library * @param int $majorversion Major version of library * @param int $minorversion Minor version of library */ public function h5p_alter_semantics(&$semantics, $name, $majorversion, $minorversion) { } /** * Alter parameters of H5P content after it has been filtered through semantics. * This is useful for adapting the content to the current context. * * @param array|object $parameters The content parameters for the library * @param string $name The machine readable name of the library * @param int $majorversion Major version of the library * @param int $minorversion Minor version of the library */ public function h5p_alter_filtered_parameters(&$parameters, string $name, int $majorversion, int $minorversion) { } } PK*\J`Jclasses/output/h5peditor.phpnu[. /** * Provides {@link \core_h5p\output\h5peditor} class. * * @package core_h5p * @copyright 2020 Victor Deniz * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\output; defined('MOODLE_INTERNAL') || die(); /** * Displays the H5P Editor * * @copyright 2020 Victor Deniz * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class h5peditor implements \renderable, \templatable { /** @var \stdClass Context in which the H5P Editor is being used. */ protected $context; /** * h5peditor constructor. * * @param \stdClass $context H5P editor context generated by core_h5p\editor. */ public function __construct(\stdClass $context) { $this->context = $context; } /** * Exports the data required for the H5P Editor. * * @param \renderer_base $output * @return \stdClass */ public function export_for_template(\renderer_base $output) { return $this->context; } } PK*\&*7classes/output/libraries.phpnu[. /** * Contains class core_h5p\output\libraries * * @package core_h5p * @copyright 2020 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\output; defined('MOODLE_INTERNAL') || die(); use renderable; use templatable; use renderer_base; use stdClass; use moodle_url; use action_menu; use action_menu_link; use pix_icon; /** * Class to help display H5P library management table. * * @copyright 2020 Ferran Recio * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class libraries implements renderable, templatable { /** @var H5P factory */ protected $factory; /** @var H5P library list */ protected $libraries; /** * Constructor. * * @param factory $factory The H5P factory * @param array $libraries array of h5p libraries records */ public function __construct(\core_h5p\factory $factory, array $libraries) { $this->factory = $factory; $this->libraries = $libraries; } /** * Export this data so it can be used as the context for a mustache template. * * @param renderer_base $output * @return stdClass */ public function export_for_template(renderer_base $output) { $installed = []; $filestorage = $this->factory->get_core()->fs; foreach ($this->libraries as $libraryname => $versions) { foreach ($versions as $version) { // Get the icon URL. $version->icon = $filestorage->get_icon_url( $version->id, $version->machine_name, $version->major_version, $version->minor_version ); // Get the action menu options. $actionmenu = new action_menu(); $actionmenu->set_menu_trigger(get_string('actions', 'core_h5p')); $actionmenu->prioritise = true; $actionmenu->add_primary_action(new action_menu_link( new moodle_url('/h5p/libraries.php', ['deletelibrary' => $version->id]), new pix_icon('t/delete', get_string('deletelibraryversion', 'core_h5p')), get_string('deletelibraryversion', 'core_h5p') )); $version->actionmenu = $actionmenu->export_for_template($output); if ($version->enabled) { $version->toggleenabledurl = new moodle_url('/h5p/libraries.php', [ 'id' => $version->id, 'action' => 'disable', 'sesskey' => sesskey(), ]); } else { $version->toggleenabledurl = new moodle_url('/h5p/libraries.php', [ 'id' => $version->id, 'action' => 'enable', 'sesskey' => sesskey(), ]); } $installed[] = $version; } } $r = new stdClass(); $r->contenttypes = $installed; return $r; } } PK*\^[ ""classes/editor_ajax.phpnu[. /** * Class \core_h5p\editor_ajax * * @package core_h5p * @copyright 2020 Victor Deniz , base on code by Joubel AS * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; use Moodle\H5PEditorAjaxInterface; use core\dml\table as dml_table; /** * Moodle's implementation of the H5P Editor Ajax interface. * * Makes it possible for the editor's core ajax functionality to communicate with the * database used by Moodle. * * @package core_h5p * @copyright 2020 Victor Deniz , base on code by Joubel AS * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class editor_ajax implements H5PEditorAjaxInterface { /** The component for H5P. */ public const EDITOR_AJAX_TOKEN = 'editorajax'; /** * Gets latest library versions that exists locally * * @return array Latest version of all local libraries */ public function getLatestLibraryVersions(): array { global $DB; $sql = "SELECT hl2.id, hl2.machinename as machine_name, hl2.title, hl2.majorversion as major_version, hl2.minorversion AS minor_version, hl2.patchversion as patch_version, '' as has_icon, 0 as restricted, hl2.enabled FROM {h5p_libraries} hl2 LEFT JOIN {h5p_libraries} hl1 ON hl1.machinename = hl2.machinename AND (hl2.majorversion < hl1.majorversion OR (hl2.majorversion = hl1.majorversion AND hl2.minorversion < hl1.minorversion) ) WHERE hl2.runnable = 1 AND hl1.majorversion is null ORDER BY hl2.title"; return $DB->get_records_sql($sql); } /** * Get locally stored Content Type Cache. * * If machine name is provided it will only get the given content type from the cache. * * @param null|string $machinename * * @return mixed|null Returns results from querying the database */ public function getContentTypeCache($machinename = null) { global $DB; // Added some extra fields to the result because they are expected by functions calling this. They have been // taken from method getCachedLibsMap() in h5peditor.class.php. $sql = "SELECT l.id, l.machinename AS machine_name, l.majorversion AS major_version, l.minorversion AS minor_version, l.patchversion AS patch_version, l.coremajor AS h5p_major_version, l.coreminor AS h5p_minor_version, l.title, l.tutorial, l.example, '' AS summary, '' AS description, '' AS icon, 0 AS created_at, 0 AS updated_at, 0 AS is_recommended, 0 AS popularity, '' AS screenshots, '' AS license, '' AS owner FROM {h5p_libraries} l"; $params = []; if (!empty($machinename)) { $sql .= ' WHERE l.machinename = :machine_name'; $params = ['machine_name' => $machinename]; } return $DB->get_records_sql($sql, $params); } /** * Gets recently used libraries for the current author * * @return array machine names. The first element in the array is the * most recently used. */ public function getAuthorsRecentlyUsedLibraries(): array { // This is to be implemented when the Hub client is used. return []; } /** * Checks if the provided token is valid for this endpoint. * * @param string $token The token that will be validated for. * * @return bool True if successful validation */ public function validateEditorToken($token): bool { return core::validToken(self::EDITOR_AJAX_TOKEN, $token); } /** * Get translations in one language for a list of libraries. * * @param array $libraries An array of libraries, in the form " . * @param string $languagecode Language code * * @return array Translations in $languagecode available for libraries $libraries */ public function getTranslations($libraries, $languagecode): array { $translations = []; $langcache = \cache::make('core', 'h5p_content_type_translations'); $missing = []; foreach ($libraries as $libstring) { // Check if this library has been saved previously into the cache. $librarykey = helper::get_cache_librarykey($libstring); $cachekey = "{$librarykey}/{$languagecode}"; $libtranslation = $langcache->get($cachekey); if ($libtranslation) { // The library has this language stored into the cache. $translations[$libstring] = $libtranslation; } else { // This language for the library hasn't been stored previously into the cache, so we need to get it from DB. $missing[] = $libstring; } } // Get all language files for libraries which aren't stored into the cache and merge them with the cache ones. return array_merge( $translations, $this->get_missing_translations($missing, $languagecode) ); } /** * Get translation for $language for libraries in $missing. * * @param array $missing An array of libraries, in the form " . * @param string $language Language code * @return array Translations in $language available for libraries $missing */ protected function get_missing_translations(array $missing, string $language): array { global $DB; if (empty($missing)) { return []; } $wheres = []; $params = [ file_storage::COMPONENT, file_storage::LIBRARY_FILEAREA, ]; $sqllike = $DB->sql_like('f.filepath', '?'); $params[] = '%language%'; foreach ($missing as $library) { $librarydata = core::libraryFromString($library); $wheres[] = '(h.machinename = ? AND h.majorversion = ? AND h.minorversion = ?)'; $params[] = $librarydata['machineName']; $params[] = $librarydata['majorVersion']; $params[] = $librarydata['minorVersion']; } $params[] = "{$language}.json"; $wheresql = implode(' OR ', $wheres); $filestable = new dml_table('files', 'f', 'f_'); $filestableselect = $filestable->get_field_select(); $libtable = new dml_table('h5p_libraries', 'h', 'h_'); $libtableselect = $libtable->get_field_select(); $sql = "SELECT {$filestableselect}, {$libtableselect} FROM {h5p_libraries} h LEFT JOIN {files} f ON h.id = f.itemid AND f.component = ? AND f.filearea = ? AND $sqllike WHERE ($wheresql) AND f.filename = ?"; // Get the content of all these language files and put them into the translations array. $langcache = \cache::make('core', 'h5p_content_type_translations'); $fs = get_file_storage(); $translations = []; $results = $DB->get_recordset_sql($sql, $params); $toset = []; foreach ($results as $result) { $file = $fs->get_file_instance($filestable->extract_from_result($result)); $library = $libtable->extract_from_result($result); $libstring = core::record_to_string($library); $librarykey = helper::get_cache_librarykey($libstring); $translations[$libstring] = $file->get_content(); $cachekey = "{$librarykey}/{$language}"; $toset[$cachekey] = $translations[$libstring]; } $langcache->set_many($toset); $results->close(); return $translations; } } PK*\,Mv classes/event/h5p_deleted.phpnu[. /** * H5P deleted event class. * * @package core * @since Moodle 3.8 * @copyright 2019 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\event; defined('MOODLE_INTERNAL') || die(); /** * H5P viewed event class. * * @package core_h5p * @since Moodle 3.8 * @copyright 2019 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class h5p_deleted extends \core\event\base { /** * Initialise event parameters. */ protected function init() { $this->data['objecttable'] = 'h5p'; $this->data['crud'] = 'd'; $this->data['edulevel'] = self::LEVEL_PARTICIPATING; } /** * Returns localised event name. * * @return string */ public static function get_name() { return get_string('eventh5pdeleted', 'h5p'); } /** * Returns non-localised event description with id's for admin use only. * * @return string */ public function get_description() { return "The user with id '$this->userid' deleted the H5P with id '$this->objectid'."; } /** * Custom validations. * * @throws \coding_exception * @return void */ protected function validate_data() { parent::validate_data(); if (!isset($this->objectid)) { throw new \coding_exception('The \'objectid\' must be set.'); } } /** * Returns relevant URL. * * @return \moodle_url */ public function get_url() { // There is no url since the previous event already has the url where the h5p content has been displayed. return null; } } PK*\J9 classes/event/h5p_viewed.phpnu[. /** * H5P viewed event class. * * @package core * @since Moodle 3.8 * @copyright 2019 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p\event; defined('MOODLE_INTERNAL') || die(); /** * H5P viewed event class. * * @package core_h5p * @since Moodle 3.8 * @copyright 2019 Carlos Escobedo * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class h5p_viewed extends \core\event\base { /** * Initialise event parameters. */ protected function init() { $this->data['objecttable'] = 'h5p'; $this->data['crud'] = 'r'; $this->data['edulevel'] = self::LEVEL_PARTICIPATING; } /** * Returns localised event name. * * @return string */ public static function get_name() { return get_string('eventh5pviewed', 'h5p'); } /** * Returns non-localised event description with id's for admin use only. * * @return string */ public function get_description() { return "The user with id '$this->userid' has viewed the H5P with the id '$this->objectid'."; } /** * Custom validations. * * @throws \coding_exception * @return void */ protected function validate_data() { parent::validate_data(); if (!isset($this->objectid)) { throw new \coding_exception('The \'objectid\' must be set.'); } } /** * Returns relevant URL. * * @return \moodle_url */ public function get_url() { // There is no url since the previous event already has the url where the h5p content has been displayed. return null; } } PK*\s&&classes/file_storage.phpnu[. /** * Class \core_h5p\file_storage. * * @package core_h5p * @copyright 2019 Victor Deniz , base on code by Joubel AS * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ namespace core_h5p; use stored_file; use Moodle\H5PCore; use Moodle\H5peditorFile; use Moodle\H5PFileStorage; // phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod /** * Class to handle storage and export of H5P Content. * * @package core_h5p * @copyright 2019 Victor Deniz * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class file_storage implements H5PFileStorage { /** The component for H5P. */ public const COMPONENT = 'core_h5p'; /** The library file area. */ public const LIBRARY_FILEAREA = 'libraries'; /** The content file area */ public const CONTENT_FILEAREA = 'content'; /** The cached assest file area. */ public const CACHED_ASSETS_FILEAREA = 'cachedassets'; /** The export file area */ public const EXPORT_FILEAREA = 'export'; /** The export css file area */ public const CSS_FILEAREA = 'css'; /** The icon filename */ public const ICON_FILENAME = 'icon.svg'; /** The custom CSS filename */ private const CUSTOM_CSS_FILENAME = 'custom_h5p.css'; /** * @var \context $context Currently we use the system context everywhere. * Don't feel forced to keep it this way in the future. */ protected $context; /** @var \file_storage $fs File storage. */ protected $fs; /** * Initial setup for file_storage. */ public function __construct() { // Currently everything uses the system context. $this->context = \context_system::instance(); $this->fs = get_file_storage(); } /** * Stores a H5P library in the Moodle filesystem. * * @param array $library Library properties. */ public function saveLibrary($library) { $options = [ 'contextid' => $this->context->id, 'component' => self::COMPONENT, 'filearea' => self::LIBRARY_FILEAREA, 'filepath' => '/' . H5PCore::libraryToFolderName($library) . '/', 'itemid' => $library['libraryId'], ]; // Easiest approach: delete the existing library version and copy the new one. $this->delete_library($library); $this->copy_directory($library['uploadDirectory'], $options); } /** * Delete library folder. * * @param array $library */ public function deleteLibrary($library) { // Although this class had a method (delete_library()) for removing libraries before this was added to the interface, // it's not safe to call it from here because looking at the place where it's called, it's not clear what are their // expectation. This method will be implemented once more information will be added to the H5P technical doc. } /** * Store the content folder. * * @param string $source Path on file system to content directory. * @param array $content Content properties */ public function saveContent($source, $content) { $options = [ 'contextid' => $this->context->id, 'component' => self::COMPONENT, 'filearea' => self::CONTENT_FILEAREA, 'itemid' => $content['id'], 'filepath' => '/', ]; $this->delete_directory($this->context->id, self::COMPONENT, self::CONTENT_FILEAREA, $content['id']); // Copy content directory into Moodle filesystem. $this->copy_directory($source, $options); } /** * Remove content folder. * * @param array $content Content properties */ public function deleteContent($content) { $this->delete_directory($this->context->id, self::COMPONENT, self::CONTENT_FILEAREA, $content['id']); } /** * Creates a stored copy of the content folder. * * @param string $id Identifier of content to clone. * @param int $newid The cloned content's identifier */ public function cloneContent($id, $newid) { // Not implemented in Moodle. } /** * Get path to a new unique tmp folder. * Please note this needs to not be a directory. * * @return string Path */ public function getTmpPath(): string { return make_request_directory() . '/' . uniqid('h5p-'); } /** * Fetch content folder and save in target directory. * * @param int $id Content identifier * @param string $target Where the content folder will be saved */ public function exportContent($id, $target) { $this->export_file_tree($target, $this->context->id, self::CONTENT_FILEAREA, '/', $id); } /** * Fetch library folder and save in target directory. * * @param array $library Library properties * @param string $target Where the library folder will be saved */ public function exportLibrary($library, $target) { $folder = H5PCore::libraryToFolderName($library); $this->export_file_tree($target . '/' . $folder, $this->context->id, self::LIBRARY_FILEAREA, '/' . $folder . '/', $library['libraryId']); } /** * Save export in file system * * @param string $source Path on file system to temporary export file. * @param string $filename Name of export file. */ public function saveExport($source, $filename) { global $USER; // Remove old export. $this->deleteExport($filename); $filerecord = [ 'contextid' => $this->context->id, 'component' => self::COMPONENT, 'filearea' => self::EXPORT_FILEAREA, 'itemid' => 0, 'filepath' => '/', 'filename' => $filename, 'userid' => $USER->id ]; $this->fs->create_file_from_pathname($filerecord, $source); } /** * Removes given export file * * @param string $filename filename of the export to delete. */ public function deleteExport($filename) { $file = $this->get_export_file($filename); if ($file) { $file->delete(); } } /** * Check if the given export file exists * * @param string $filename The export file to check. * @return boolean True if the export file exists. */ public function hasExport($filename) { return !!$this->get_export_file($filename); } /** * Will concatenate all JavaScrips and Stylesheets into two files in order * to improve page performance. * * @param array $files A set of all the assets required for content to display * @param string $key Hashed key for cached asset */ public function cacheAssets(&$files, $key) { foreach ($files as $type => $assets) { if (empty($assets)) { continue; } // Create new file for cached assets. $ext = ($type === 'scripts' ? 'js' : 'css'); $filename = $key . '.' . $ext; $fileinfo = [ 'contextid' => $this->context->id, 'component' => self::COMPONENT, 'filearea' => self::CACHED_ASSETS_FILEAREA, 'itemid' => 0, 'filepath' => '/', 'filename' => $filename ]; // Store concatenated content. $this->fs->create_file_from_string($fileinfo, $this->concatenate_files($assets, $type, $this->context)); $files[$type] = [ (object) [ 'path' => '/' . self::CACHED_ASSETS_FILEAREA . '/' . $filename, 'version' => '' ] ]; } } /** * Will check if there are cache assets available for content. * * @param string $key Hashed key for cached asset * @return array */ public function getCachedAssets($key) { $files = []; $js = $this->fs->get_file($this->context->id, self::COMPONENT, self::CACHED_ASSETS_FILEAREA, 0, '/', "{$key}.js"); if ($js && $js->get_filesize() > 0) { $files['scripts'] = [ (object) [ 'path' => '/' . self::CACHED_ASSETS_FILEAREA . '/' . "{$key}.js", 'version' => '' ] ]; } $css = $this->fs->get_file($this->context->id, self::COMPONENT, self::CACHED_ASSETS_FILEAREA, 0, '/', "{$key}.css"); if ($css && $css->get_filesize() > 0) { $files['styles'] = [ (object) [ 'path' => '/' . self::CACHED_ASSETS_FILEAREA . '/' . "{$key}.css", 'version' => '' ] ]; } return empty($files) ? null : $files; } /** * Remove the aggregated cache files. * * @param array $keys The hash keys of removed files */ public function deleteCachedAssets($keys) { if (empty($keys)) { return; } foreach ($keys as $hash) { foreach (['js', 'css'] as $type) { $cachedasset = $this->fs->get_file($this->context->id, self::COMPONENT, self::CACHED_ASSETS_FILEAREA, 0, '/', "{$hash}.{$type}"); if ($cachedasset) { $cachedasset->delete(); } } } } /** * Read file content of given file and then return it. * * @param string $filepath * @return string contents */ public function getContent($filepath) { list( 'filearea' => $filearea, 'filepath' => $filepath, 'filename' => $filename, 'itemid' => $itemid ) = $this->get_file_elements_from_filepath($filepath); if (!$itemid) { throw new \file_serving_exception('Could not retrieve the requested file, check your file permissions.'); } // Locate file. $file = $this->fs->get_file($this->context->id, self::COMPONENT, $filearea, $itemid, $filepath, $filename); // Return content. return $file->get_content(); } /** * Save files uploaded through the editor. * * @param H5peditorFile $file * @param int $contentid * * @return int The id of the saved file. */ public function saveFile($file, $contentid) { global $USER; $context = $this->context->id; $component = self::COMPONENT; $filearea = self::CONTENT_FILEAREA; if ($contentid === 0) { $usercontext = \context_user::instance($USER->id); $context = $usercontext->id; $component = 'user'; $filearea = 'draft'; } $record = array( 'contextid' => $context, 'component' => $component, 'filearea' => $filearea, 'itemid' => $contentid, 'filepath' => '/' . $file->getType() . 's/', 'filename' => $file->getName() ); $storedfile = $this->fs->create_file_from_pathname($record, $_FILES['file']['tmp_name']); return $storedfile->get_id(); } /** * Copy a file from another content or editor tmp dir. * Used when copy pasting content in H5P. * * @param string $file path + name * @param string|int $fromid Content ID or 'editor' string * @param \stdClass $tocontent Target Content * * @return void */ public function cloneContentFile($file, $fromid, $tocontent): void { // Determine source filearea and itemid. if ($fromid === 'editor') { $sourcefilearea = 'draft'; $sourceitemid = 0; } else { $sourcefilearea = self::CONTENT_FILEAREA; $sourceitemid = (int)$fromid; } $filepath = '/' . dirname($file) . '/'; $filename = basename($file); // Check to see if source exists. $sourcefile = $this->get_file($sourcefilearea, $sourceitemid, $file); if ($sourcefile === null) { return; // Nothing to copy from. } // Check to make sure that file doesn't exist already in target. $targetfile = $this->get_file(self::CONTENT_FILEAREA, $tocontent->id, $file); if ( $targetfile !== null) { return; // File exists, no need to copy. } // Create new file record. $record = [ 'contextid' => $this->context->id, 'component' => self::COMPONENT, 'filearea' => self::CONTENT_FILEAREA, 'itemid' => $tocontent->id, 'filepath' => $filepath, 'filename' => $filename, ]; $this->fs->create_file_from_storedfile($record, $sourcefile); } /** * Copy content from one directory to another. * Defaults to cloning content from the current temporary upload folder to the editor path. * * @param string $source path to source directory * @param string $contentid Id of content * */ public function moveContentDirectory($source, $contentid = null) { $contentidint = (int)$contentid; if ($source === null) { return; } // Get H5P and content json. $contentsource = $source . '/content'; // Move all temporary content files to editor. $it = new \RecursiveIteratorIterator( new \RecursiveDirectoryIterator($contentsource, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST ); $it->rewind(); while ($it->valid()) { $item = $it->current(); $pathname = $it->getPathname(); if (!$item->isDir() && !($item->getFilename() === 'content.json')) { $this->move_file($pathname, $contentidint); } $it->next(); } } /** * Get the file URL or given library and then return it. * * @param int $itemid * @param string $machinename * @param int $majorversion * @param int $minorversion * @return string url or false if the file doesn't exist */ public function get_icon_url(int $itemid, string $machinename, int $majorversion, int $minorversion) { $filepath = '/' . "{$machinename}-{$majorversion}.{$minorversion}" . '/'; if ($file = $this->fs->get_file( $this->context->id, self::COMPONENT, self::LIBRARY_FILEAREA, $itemid, $filepath, self::ICON_FILENAME) ) { $iconurl = \moodle_url::make_pluginfile_url( $this->context->id, self::COMPONENT, self::LIBRARY_FILEAREA, $itemid, $filepath, $file->get_filename()); // Return image URL. return $iconurl->out(); } return false; } /** * Checks to see if an H5P content has the given file. * * @param string $file File path and name. * @param int $content Content id. * * @return int|null File ID or NULL if not found */ public function getContentFile($file, $content): ?int { if (is_object($content)) { $content = $content->id; } $contentfile = $this->get_file(self::CONTENT_FILEAREA, $content, $file); return ($contentfile === null ? null : $contentfile->get_id()); } /** * Remove content files that are no longer used. * * Used when saving content. * * @param string $file File path and name. * @param int $contentid Content id. * * @return void */ public function removeContentFile($file, $contentid): void { // Although the interface defines $contentid as int, object given in H5peditor::processParameters. if (is_object($contentid)) { $contentid = $contentid->id; } $existingfile = $this->get_file(self::CONTENT_FILEAREA, $contentid, $file); if ($existingfile !== null) { $existingfile->delete(); } } /** * Check if server setup has write permission to * the required folders * * @return bool True if server has the proper write access */ public function hasWriteAccess() { // Moodle has access to the files table which is where all of the folders are stored. return true; } /** * Check if the library has a presave.js in the root folder * * @param string $libraryname * @param string $developmentpath * @return bool */ public function hasPresave($libraryname, $developmentpath = null) { return false; } /** * Check if upgrades script exist for library. * * @param string $machinename * @param int $majorversion * @param int $minorversion * @return string Relative path */ public function getUpgradeScript($machinename, $majorversion, $minorversion) { $path = '/' . "{$machinename}-{$majorversion}.{$minorversion}" . '/'; $file = 'upgrade.js'; $itemid = $this->get_itemid_for_file(self::LIBRARY_FILEAREA, $path, $file); if ($this->fs->get_file($this->context->id, self::COMPONENT, self::LIBRARY_FILEAREA, $itemid, $path, $file)) { return '/' . self::LIBRARY_FILEAREA . $path. $file; } else { return null; } } /** * Store the given stream into the given file. * * @param string $path * @param string $file * @param resource $stream * @return bool|int */ public function saveFileFromZip($path, $file, $stream) { $fullpath = $path . '/' . $file; check_dir_exists(pathinfo($fullpath, PATHINFO_DIRNAME)); return file_put_contents($fullpath, $stream); } /** * Deletes a library from the file system. * * @param array $library Library details */ public function delete_library(array $library): void { global $DB; // A library ID of false would result in all library files being deleted, which we don't want. Return instead. if (empty($library['libraryId'])) { return; } $areafiles = $this->fs->get_area_files($this->context->id, self::COMPONENT, self::LIBRARY_FILEAREA, $library['libraryId']); $this->delete_directory($this->context->id, self::COMPONENT, self::LIBRARY_FILEAREA, $library['libraryId']); $librarycache = \cache::make('core', 'h5p_library_files'); foreach ($areafiles as $file) { if (!$DB->record_exists('files', array('contenthash' => $file->get_contenthash(), 'component' => self::COMPONENT, 'filearea' => self::LIBRARY_FILEAREA))) { $librarycache->delete($file->get_contenthash()); } } } /** * Remove an H5P directory from the filesystem. * * @param int $contextid context ID * @param string $component component * @param string $filearea file area or all areas in context if not specified * @param int $itemid item ID or all files if not specified */ private function delete_directory(int $contextid, string $component, string $filearea, int $itemid): void { $this->fs->delete_area_files($contextid, $component, $filearea, $itemid); } /** * Copy an H5P directory from the temporary directory into the file system. * * @param string $source Temporary location for files. * @param array $options File system information. */ private function copy_directory(string $source, array $options): void { $librarycache = \cache::make('core', 'h5p_library_files'); $it = new \RecursiveIteratorIterator(new \RecursiveDirectoryIterator($source, \RecursiveDirectoryIterator::SKIP_DOTS), \RecursiveIteratorIterator::SELF_FIRST); $root = $options['filepath']; $it->rewind(); while ($it->valid()) { $item = $it->current(); $subpath = $it->getSubPath(); if (!$item->isDir()) { $options['filename'] = $it->getFilename(); if (!$subpath == '') { $options['filepath'] = $root . $subpath . '/'; } else { $options['filepath'] = $root; } $file = $this->fs->create_file_from_pathname($options, $item->getPathName()); if ($options['filearea'] == self::LIBRARY_FILEAREA) { if (!$librarycache->has($file->get_contenthash())) { $librarycache->set($file->get_contenthash(), file_get_contents($item->getPathName())); } } } $it->next(); } } /** * Copies files from storage to temporary folder. * * @param string $target Path to temporary folder * @param int $contextid context where the files are found * @param string $filearea file area * @param string $filepath file path * @param int $itemid Optional item ID */ private function export_file_tree(string $target, int $contextid, string $filearea, string $filepath, int $itemid = 0): void { // Make sure target folder exists. check_dir_exists($target); // Read source files. $files = $this->fs->get_directory_files($contextid, self::COMPONENT, $filearea, $itemid, $filepath, true); $librarycache = \cache::make('core', 'h5p_library_files'); foreach ($files as $file) { $path = $target . str_replace($filepath, DIRECTORY_SEPARATOR, $file->get_filepath()); if ($file->is_directory()) { check_dir_exists(rtrim($path)); } else { if ($filearea == self::LIBRARY_FILEAREA) { $cachedfile = $librarycache->get($file->get_contenthash()); if (empty($cachedfile)) { $file->copy_content_to($path . $file->get_filename()); $librarycache->set($file->get_contenthash(), file_get_contents($path . $file->get_filename())); } else { file_put_contents($path . $file->get_filename(), $cachedfile); } } else { $file->copy_content_to($path . $file->get_filename()); } } } } /** * Adds all files of a type into one file. * * @param array $assets A list of files. * @param string $type The type of files in assets. Either 'scripts' or 'styles' * @param \context $context Context * @return string All of the file content in one string. */ private function concatenate_files(array $assets, string $type, \context $context): string { $content = ''; foreach ($assets as $asset) { // Find location of asset. list( 'filearea' => $filearea, 'filepath' => $filepath, 'filename' => $filename, 'itemid' => $itemid ) = $this->get_file_elements_from_filepath($asset->path); if ($itemid === false) { continue; } // Locate file. $file = $this->fs->get_file($context->id, self::COMPONENT, $filearea, $itemid, $filepath, $filename); // Get file content and concatenate. if ($type === 'scripts') { $content .= $file->get_content() . ";\n"; } else { // Rewrite relative URLs used inside stylesheets. $content .= preg_replace_callback( '/url\([\'"]?([^"\')]+)[\'"]?\)/i', function ($matches) use ($filearea, $filepath, $itemid) { if (preg_match("/^(data:|([a-z0-9]+:)?\/)/i", $matches[1]) === 1) { return $matches[0]; // Not relative, skip. } // Find "../" in matches[1]. // If it exists, we have to remove "../". // And switch the last folder in the filepath for the first folder in $matches[1]. // For instance: // $filepath: /H5P.Question-1.4/styles/ // $matches[1]: ../images/plus-one.svg // We want to avoid this: H5P.Question-1.4/styles/ITEMID/../images/minus-one.svg // We want this: H5P.Question-1.4/images/ITEMID/minus-one.svg. if (preg_match('/\.\.\//', $matches[1], $pathmatches)) { $path = preg_split('/\//', $filepath, -1, PREG_SPLIT_NO_EMPTY); $pathfilename = preg_split('/\//', $matches[1], -1, PREG_SPLIT_NO_EMPTY); // Remove the first element: ../. array_shift($pathfilename); // Replace pathfilename into the filepath. $path[count($path) - 1] = $pathfilename[0]; $filepath = '/' . implode('/', $path) . '/'; // Remove the element used to replace. array_shift($pathfilename); $matches[1] = implode('/', $pathfilename); } return 'url("../' . $filearea . $filepath . $itemid . '/' . $matches[1] . '")'; }, $file->get_content()) . "\n"; } } return $content; } /** * Get files ready for export. * * @param string $filename File name to retrieve. * @return bool|\stored_file Stored file instance if exists, false if not */ public function get_export_file(string $filename) { return $this->fs->get_file($this->context->id, self::COMPONENT, self::EXPORT_FILEAREA, 0, '/', $filename); } /** * Converts a relative system file path into Moodle File API elements. * * @param string $filepath The system filepath to get information from. * @return array File information. */ private function get_file_elements_from_filepath(string $filepath): array { $sections = explode('/', $filepath); // Get the filename. $filename = array_pop($sections); // Discard first element. if (empty($sections[0])) { array_shift($sections); } // Get the filearea. $filearea = array_shift($sections); $itemid = array_shift($sections); // Get the filepath. $filepath = implode('/', $sections); $filepath = '/' . $filepath . '/'; return ['filearea' => $filearea, 'filepath' => $filepath, 'filename' => $filename, 'itemid' => $itemid]; } /** * Returns the item id given the other necessary variables. * * @param string $filearea The file area. * @param string $filepath The file path. * @param string $filename The file name. * @return mixed the specified value false if not found. */ private function get_itemid_for_file(string $filearea, string $filepath, string $filename) { global $DB; return $DB->get_field('files', 'itemid', ['component' => self::COMPONENT, 'filearea' => $filearea, 'filepath' => $filepath, 'filename' => $filename]); } /** * Helper to make it easy to load content files. * * @param string $filearea File area where the file is saved. * @param int $itemid Content instance or content id. * @param string $file File path and name. * * @return stored_file|null */ private function get_file(string $filearea, int $itemid, string $file): ?stored_file { global $USER; $component = self::COMPONENT; $context = $this->context->id; if ($filearea === 'draft') { $itemid = 0; $component = 'user'; $usercontext = \context_user::instance($USER->id); $context = $usercontext->id; } $filepath = '/'. dirname($file). '/'; $filename = basename($file); // Load file. $existingfile = $this->fs->get_file($context, $component, $filearea, $itemid, $filepath, $filename); if (!$existingfile) { return null; } return $existingfile; } /** * Move a single file * * @param string $sourcefile Path to source file * @param int $contentid Content id or 0 if the file is in the editor file area * * @return void */ private function move_file(string $sourcefile, int $contentid): void { $pathparts = pathinfo($sourcefile); $filename = $pathparts['basename']; $filepath = $pathparts['dirname']; $foldername = basename($filepath); // Create file record for content. $record = array( 'contextid' => $this->context->id, 'component' => $contentid > 0 ? self::COMPONENT : 'user', 'filearea' => $contentid > 0 ? self::CONTENT_FILEAREA : 'draft', 'itemid' => $contentid > 0 ? $contentid : 0, 'filepath' => '/' . $foldername . '/', 'filename' => $filename ); $file = $this->fs->get_file( $record['contextid'], $record['component'], $record['filearea'], $record['itemid'], $record['filepath'], $record['filename'] ); if ($file) { // Delete it to make sure that it is replaced with correct content. $file->delete(); } $this->fs->create_file_from_pathname($record, $sourcefile); } /** * Generate H5P custom styles if any. */ public static function generate_custom_styles(): void { $record = self::get_custom_styles_file_record(); $cssfile = self::get_custom_styles_file($record); if ($cssfile) { // The CSS file needs to be updated, so delete and recreate it // if there is CSS in the 'h5pcustomcss' setting. $cssfile->delete(); } $css = get_config('core_h5p', 'h5pcustomcss'); if (!empty($css)) { $fs = get_file_storage(); $fs->create_file_from_string($record, $css); } } /** * Get H5P custom styles if any. * * @throws \moodle_exception If the CSS setting is empty but there is a file to serve * or there is no file but the CSS setting is not empty. * @return array|null If there is CSS then an array with the keys 'cssurl' * and 'cssversion' is returned otherwise null. 'cssurl' is a link to the * generated 'custom_h5p.css' file and 'cssversion' the md5 hash of its contents. */ public static function get_custom_styles(): ?array { $record = self::get_custom_styles_file_record(); $css = get_config('core_h5p', 'h5pcustomcss'); if (self::get_custom_styles_file($record)) { if (empty($css)) { // The custom CSS file exists and yet the setting 'h5pcustomcss' is empty. // This prevents an invalid content hash. throw new \moodle_exception( 'The H5P \'h5pcustomcss\' setting is empty and yet the custom CSS file \''. $record['filename']. '\' exists.', 'core_h5p' ); } // File exists, so generate the url and version hash. $cssurl = \moodle_url::make_pluginfile_url( $record['contextid'], $record['component'], $record['filearea'], null, $record['filepath'], $record['filename'] ); return ['cssurl' => $cssurl, 'cssversion' => md5($css)]; } else if (!empty($css)) { // The custom CSS file does not exist and yet should do. throw new \moodle_exception( 'The H5P custom CSS file \''. $record['filename']. '\' does not exist and yet there is CSS in the \'h5pcustomcss\' setting.', 'core_h5p' ); } return null; } /** * Get H5P custom styles file record. * * @return array File record for the CSS custom styles. */ private static function get_custom_styles_file_record(): array { return [ 'contextid' => \context_system::instance()->id, 'component' => self::COMPONENT, 'filearea' => self::CSS_FILEAREA, 'itemid' => 0, 'filepath' => '/', 'filename' => self::CUSTOM_CSS_FILENAME, ]; } /** * Get H5P custom styles file. * * @param array $record The H5P custom styles file record. * * @return stored_file|bool stored_file instance if exists, false if not. */ private static function get_custom_styles_file($record): stored_file|bool { $fs = get_file_storage(); return $fs->get_file( $record['contextid'], $record['component'], $record['filearea'], $record['itemid'], $record['filepath'], $record['filename'] ); } } PK*\m>?>?classes/core.phpnu[. namespace core_h5p; defined('MOODLE_INTERNAL') || die(); require_once("$CFG->libdir/filelib.php"); use Moodle\H5PCore; use Moodle\H5PFrameworkInterface; use Moodle\H5PHubEndpoints; use stdClass; use moodle_url; use core_h5p\local\library\autoloader; // phpcs:disable moodle.NamingConventions.ValidFunctionName.LowercaseMethod // phpcs:disable moodle.NamingConventions.ValidVariableName.VariableNameLowerCase /** * H5P core class, containing functions and storage shared by the other H5P classes. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class core extends H5PCore { /** @var array The array containing all the present libraries */ protected $libraries; /** * Constructor for core_h5p/core. * * @param H5PFrameworkInterface $framework The frameworks implementation of the H5PFrameworkInterface * @param string|H5PFileStorage $path The H5P file storage directory or class * @param string $url The URL to the file storage directory * @param string $language The language code. Defaults to english * @param boolean $export Whether export is enabled */ public function __construct(H5PFrameworkInterface $framework, $path, string $url, string $language = 'en', bool $export = false) { parent::__construct($framework, $path, $url, $language, $export); // Aggregate the assets by default. $this->aggregateAssets = true; } /** * Get the path to the dependency. * * @param array $dependency An array containing the information of the requested dependency library * @return string The path to the dependency library */ protected function getDependencyPath(array $dependency): string { $library = $this->find_library($dependency); return "libraries/{$library->id}/" . H5PCore::libraryToFolderName($dependency); } /** * Get the paths to the content dependencies. * * @param int $id The H5P content ID * @return array An array containing the path of each content dependency */ public function get_dependency_roots(int $id): array { $roots = []; $dependencies = $this->h5pF->loadContentDependencies($id); $context = \context_system::instance(); foreach ($dependencies as $dependency) { $library = $this->find_library($dependency); $roots[self::libraryToFolderName($dependency)] = (moodle_url::make_pluginfile_url( $context->id, 'core_h5p', 'libraries', $library->id, "/" . self::libraryToFolderName($dependency), '' ))->out(false); } return $roots; } /** * Get a particular dependency library. * * @param array $dependency An array containing information of the dependency library * @return stdClass|null The library object if the library dependency exists, null otherwise */ protected function find_library(array $dependency): ?\stdClass { global $DB; if (null === $this->libraries) { $this->libraries = $DB->get_records('h5p_libraries'); } $major = $dependency['majorVersion']; $minor = $dependency['minorVersion']; $patch = $dependency['patchVersion']; foreach ($this->libraries as $library) { if ($library->machinename !== $dependency['machineName']) { continue; } if ($library->majorversion != $major) { continue; } if ($library->minorversion != $minor) { continue; } if ($library->patchversion != $patch) { continue; } return $library; } return null; } /** * Get the list of JS scripts to include on the page. * * @return array The array containg urls of the core JavaScript files */ public static function get_scripts(): array { global $PAGE; $jsrev = $PAGE->requires->get_jsrev(); $urls = []; foreach (self::$scripts as $script) { $urls[] = autoloader::get_h5p_core_library_url($script, [ 'ver' => $jsrev, ]); } $urls[] = new moodle_url("/h5p/js/h5p_overrides.js", [ 'ver' => $jsrev, ]); return $urls; } /** * Fetch and install the latest H5P content types libraries from the official H5P repository. * If the latest version of a content type library is present in the system, nothing is done for that content type. * * @return stdClass */ public function fetch_latest_content_types(): ?\stdClass { $contenttypes = $this->get_latest_content_types(); if (!empty($contenttypes->error)) { return $contenttypes; } $typesinstalled = []; $factory = new factory(); $framework = $factory->get_framework(); foreach ($contenttypes->contentTypes as $type) { // Don't fetch content types if any of the versions is disabled. $librarydata = (object) ['machinename' => $type->id]; if (!api::is_library_enabled($librarydata)) { continue; } // Don't fetch content types that require a higher H5P core API version. if (!$this->is_required_core_api($type->coreApiVersionNeeded)) { continue; } $library = [ 'machineName' => $type->id, 'majorVersion' => $type->version->major, 'minorVersion' => $type->version->minor, 'patchVersion' => $type->version->patch, ]; // Add example and tutorial to the library, to store this information too. if (isset($type->example)) { $library['example'] = $type->example; } if (isset($type->tutorial)) { $library['tutorial'] = $type->tutorial; } $shoulddownload = true; if ($framework->getLibraryId($type->id, $type->version->major, $type->version->minor)) { if (!$framework->isPatchedLibrary($library)) { $shoulddownload = false; } } if ($shoulddownload) { $installed['id'] = $this->fetch_content_type($library); if ($installed['id']) { $installed['name'] = H5PCore::libraryToString($library); $typesinstalled[] = $installed; } } } $result = new stdClass(); $result->error = ''; $result->typesinstalled = $typesinstalled; return $result; } /** * Given an H5P content type machine name, fetch and install the required library from the official H5P repository. * * @param array $library Library machineName, majorversion and minorversion. * @return int|null Returns the id of the content type library installed, null otherwise. */ public function fetch_content_type(array $library): ?int { global $DB; $factory = new factory(); $fs = get_file_storage(); // Delete any existing file, if it was not deleted during a previous download. $existing = $fs->get_file( (\context_system::instance())->id, 'core_h5p', 'library_sources', 0, '/', $library['machineName'] ); if ($existing) { $existing->delete(); } // Download the latest content type from the H5P official repository. $file = $fs->create_file_from_url( (object) [ 'component' => 'core_h5p', 'filearea' => 'library_sources', 'itemid' => 0, 'contextid' => (\context_system::instance())->id, 'filepath' => '/', 'filename' => $library['machineName'], ], $this->get_api_endpoint($library['machineName']), null, true ); if (!$file) { return null; } helper::save_h5p($factory, $file, (object) [], false, true); $file->delete(); $librarykey = static::libraryToString($library); if (is_null($factory->get_storage()->h5pC->librariesJsonData)) { // There was an error fetching the content type. debugging('Error fetching content type: ' . $librarykey); return null; } $libraryjson = $factory->get_storage()->h5pC->librariesJsonData[$librarykey]; if (is_null($libraryjson) || !array_key_exists('libraryId', $libraryjson)) { // There was an error fetching the content type. debugging('Error fetching content type: ' . $librarykey); return null; } $libraryid = $libraryjson['libraryId']; // Update example and tutorial (if any of them are defined in $library). $params = ['id' => $libraryid]; if (array_key_exists('example', $library)) { $params['example'] = $library['example']; } if (array_key_exists('tutorial', $library)) { $params['tutorial'] = $library['tutorial']; } if (count($params) > 1) { $DB->update_record('h5p_libraries', $params); } return $libraryid; } /** * Get H5P endpoints. * * If $endpoint = 'content' and $library is null, moodle_url is the endpoint of the latest version of the H5P content * types; however, if $library is the machine name of a content type, moodle_url is the endpoint to download the content type. * The SITES endpoint ($endpoint = 'site') may be use to get a site UUID or send site data. * * @param string|null $library The machineName of the library whose endpoint is requested. * @param string $endpoint The endpoint required. Valid values: "site", "content". * @return moodle_url The endpoint moodle_url object. */ public function get_api_endpoint(?string $library = null, string $endpoint = 'content'): moodle_url { if ($endpoint == 'site') { $h5purl = H5PHubEndpoints::createURL(H5PHubEndpoints::SITES ); } else if ($endpoint == 'content') { $h5purl = H5PHubEndpoints::createURL(H5PHubEndpoints::CONTENT_TYPES ) . $library; } return new moodle_url($h5purl); } /** * Get the latest version of the H5P content types available in the official repository. * * @return stdClass An object with 2 properties: * - string error: error message when there is any problem, empty otherwise * - array contentTypes: an object for each H5P content type with its information */ public function get_latest_content_types(): \stdClass { global $CFG; $siteuuid = $this->get_site_uuid() ?? md5($CFG->wwwroot); $postdata = ['uuid' => $siteuuid]; // Get the latest content-types json. $endpoint = $this->get_api_endpoint(); $request = download_file_content($endpoint, null, $postdata, true); if (!empty($request->error) || $request->status != '200' || empty($request->results)) { if (empty($request->error)) { $request->error = get_string('fetchtypesfailure', 'core_h5p'); } return $request; } $contenttypes = json_decode($request->results); $contenttypes->error = ''; return $contenttypes; } /** * Get the site UUID. If site UUID is not defined, try to register the site. * * return $string The site UUID, null if it is not set. */ public function get_site_uuid(): ?string { // Check if the site_uuid is already set. $siteuuid = get_config('core_h5p', 'site_uuid'); if (!$siteuuid) { $siteuuid = $this->register_site(); } return $siteuuid; } /** * Get H5P generated site UUID. * * return ?string Returns H5P generated site UUID, null if can't get it. */ private function register_site(): ?string { $endpoint = $this->get_api_endpoint(null, 'site'); $siteuuid = download_file_content($endpoint, null, ''); // Successful UUID retrieval from H5P. if ($siteuuid) { $json = json_decode($siteuuid); if (isset($json->uuid)) { set_config('site_uuid', $json->uuid, 'core_h5p'); return $json->uuid; } } return null; } /** * Checks that the required H5P core API version or higher is installed. * * @param stdClass $coreapi Object with properties major and minor for the core API version required. * @return bool True if the required H5P core API version is installed. False if not. */ public function is_required_core_api($coreapi): bool { if (isset($coreapi) && !empty($coreapi)) { if (($coreapi->major > H5PCore::$coreApi['majorVersion']) || (($coreapi->major == H5PCore::$coreApi['majorVersion']) && ($coreapi->minor > H5PCore::$coreApi['minorVersion']))) { return false; } } return true; } /** * Get the library string from a DB library record. * * @param stdClass $record The DB library record. * @param bool $foldername If true, use hyphen instead of space in returned string. * @return string The string name on the form {machineName} {majorVersion}.{minorVersion}. */ public static function record_to_string(stdClass $record, bool $foldername = false): string { if ($foldername) { return static::libraryToFolderName([ 'machineName' => $record->machinename, 'majorVersion' => $record->majorversion, 'minorVersion' => $record->minorversion, ]); } else { return static::libraryToString([ 'machineName' => $record->machinename, 'majorVersion' => $record->majorversion, 'minorVersion' => $record->minorversion, ]); } } /** * Small helper for getting the library's ID. * This method is rewritten to use MUC (instead of an static variable which causes some problems with PHPUnit). * * @param array $library * @param string $libString * @return int Identifier, or FALSE if non-existent */ public function getLibraryId($library, $libString = null) { if (!$libString) { $libString = self::libraryToString($library); } // Check if this information has been saved previously into the cache. $libcache = \cache::make('core', 'h5p_libraries'); $librarykey = helper::get_cache_librarykey($libString); $libraryId = $libcache->get($librarykey); if ($libraryId === false) { $libraryId = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']); $libcache->set($librarykey, $libraryId); } return $libraryId; } } PK*\?+#templates/h5ptoolsoverview.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5ptoolsoverview Example context (json): { "tools": [ { "tool": "h5ptasks", "tool_description": "h5ptasks_description", "link": "https://example.com/admin/tool/task/scheduledtasks.php", "status": "On", "status_class": "bade bg-success text-white", "status_action": "Run now" }, { "tool": "h5ptasks", "tool_description": "h5ptasks_description", "link": "https://example.com/admin/filters.php", "status": "Off", "status_class": "bade bg-danger text-white" } ] } }} {{#tools}} {{/tools}}
{{#str}} feature, h5p {{/str}} {{#str}} status, h5p {{/str}} {{#str}} description, h5p {{/str}}
{{{ tool }}}
{{{ status }}}
{{#status_action}}
{{{ status_action }}}
{{/status_action}}
{{{ tool_description }}}
PK*\rl~~templates/h5piframe.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5piframe This template will render an iframe for h5p content. Variables required for this template: * h5pid - The database id for the H5P content Example context (json): { "h5pid": 123 } }}
PK*\Y"templates/h5plibraries.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5plibraries Example context (json): { "contenttypes": [ { "title": "Accordion", "major_version": 1, "minor_version:": 0, "patch_version:": 0, "runnable": 1, "icon": "icon.svg", "enabled": true, "toggleenabledurl": "http://myserver.cat/h5p/libraries.php?id=26&action=disable" }, { "title": "Collage", "major_version": 0, "minor_version:": 3, "patch_version:": 1, "runnable": 1, "enabled": true, "toggleenabledurl": "http://myserver.cat/h5p/libraries.php?id=37&action=disable" }, { "title": "FontAwesome", "major_version": 4, "minor_version:": 5, "patch_version:": 0, "runnable": 1, "icon": "icon.svg", "enabled": false, "toggleenabledurl": "http://myserver.cat/h5p/libraries.php?id=54&action=enable" } ] } }}

{{#str}} installedh5p, h5p {{/str}}

{{#contenttypes}} {{#runnable}} {{/runnable}} {{/contenttypes}}
{{#str}}enable, core{{/str}} {{#str}}description, core{{/str}} {{#str}}version, core{{/str}}
{{#enabled}} {{#pix}}t/hide, core,{{#str}}disable{{/str}}{{/pix}} {{/enabled}} {{^enabled}} {{#pix}}t/show, core,{{#str}}enable{{/str}}{{/pix}} {{/enabled}} {{#icon}} {{/icon}} {{^icon}} {{#pix}} b/h5p_library, core {{/pix}} {{/icon}} {{{ title }}} {{{ major_version }}}.{{{ minor_version }}}.{{{ patch_version }}} {{#actionmenu}} {{>core/action_menu}} {{/actionmenu}}
{{#contenttypes}} {{^runnable}} {{/runnable}} {{/contenttypes}}
{{#str}}description, core{{/str}} {{#str}}version, core{{/str}}
{{{ title }}} {{{ major_version }}}.{{{ minor_version }}}.{{{ patch_version }}} {{#actionmenu}} {{>core/action_menu}} {{/actionmenu}}
PK*\ utemplates/h5presize.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5presize This template will render the resize JS code. Variables required for this template: * resizeurl - The database id for the H5P content Example context (json): { "resizeurl": "http://example.com/lib/h5p/js/h5p-resizer.js" } }} PK*\8\templates/h5perror.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5perror This template will render the embed code shown in the H5P content embed popup. Note: this mustache is part of the H5P player and requires '/h5p/js/embed.js' already loaded. Variables required for this template: * h5picon - The icon * message - The error messages to display. Example context (json): { "embedurl": "http://example.com/h5p/embed.php?url=testurl" } }}
{{#h5picon}} {{#str}}h5p, core_h5p{{/str}} {{/h5picon}}
{{#exception}} {{/exception}} {{#info}} {{/info}} {{#error}} {{/error}}
{{#js}} (function() { if (typeof H5PEmbedCommunicator !== 'undefined') { H5PEmbedCommunicator.send('resize', { scrollHeight: document.body.scrollHeight }); } })(); {{/js}} PK*\\:Km m templates/h5pembed.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5pembed This template will render the embed code shown in the H5P content embed popup. H5P implements iframe autoheight but if the content is not available it does not work and we need ensure a minimum height using javascript. Otherwise the user will not see the error. Variables required for this template: * embedurl - The URL with the H5P file to embed * editurl - The URL for the edit button; if it's empty, the edit button won't be displayed. Example context (json): { "embedurl": "http://example.com/h5p/embed.php?url=testurl", "editurl": "http://example.com/h5p/embed.php?url=testurl&edit=1", "extraactions": [ { "text": "View attempts (2)", "url": "http://example.com/mod/h5pactivity/report.php?a=1", "icon": { "key": "i\/chartbar", "component": "core", "title": "" } } ] } }} PK*\OXtemplates/h5pdiv.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5pdiv This template will render an div for h5p content. Variables required for this template: * h5pid - The database id for the H5P content Example context (json): { "h5pid": 123 } }}
PK*\uUxtemplates/h5peditor.mustachenu[{{! This file is part of Moodle - http://moodle.org/ Moodle 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 3 of the License, or (at your option) any later version. Moodle 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 Moodle. If not, see . }} {{! @template core_h5p/h5peditor Displays the H5P Editor form. Classes required for JS: * editor_display Data attributes required for JS: * none Context variables required for this template: * none Example context (json): { } }}
{{> core/loading }}
{{#js}} require(['core_h5p/editor_display'], function(Editor) { Editor.init("editor-region-{{uniqid}}"); }); {{/js}}PK*\I˪1 1 upgrade.txtnu[=== 4.5 Onwards === This file has been replaced by UPGRADING.md. See MDL-81125 for further information. === This files describes API changes in core libraries and APIs, information provided here is intended especially for developers. === 4.4 === * Added new methods, 'generate_custom_styles' and 'get_custom_styles' to 'core_h5p\file_storage' to generate then provide a CSS file to be used by the 'core_h5p\output\renderer\h5p_alter_styles' method, reference: (https://h5p.org/documentation/for-developers/visual-changes) when there is custom CSS in the 'core_h5p\h5pcustomcss' setting. This will then apply to the H5P content. === 4.3 === * The `\core_h5p\file_storage::EDITOR_FILEAREA` constant has been removed, as all editor files are stored in user draft === 4.0 === * Added new methods to api: get_original_content_from_pluginfile_url and can_edit_content. * Added edit.php and editcontent_form class, for modifying H5P content given an H5P identifier (from the h5p table). * Added a new parameter to the player::display method, to define whether the edit button should be displayed below the H5P content or not. Default value for this parameter is false. * H5P subsystem is allowed to act as an API (level 2) too. * Plugins can now implement h5p\canedit::can_edit_content method to define, if required, any custom behaviour for deciding whether an H5P content can be edited or not. The specific plugin check will completely override the generic check. * The third-party library h5p/h5plib/v124/core has been updated to version 1.24.3. === 3.11 === * Added $skipcapcheck parameter to H5P constructor, api::create_content_from_pluginfile_url() and api::get_content_from_pluginfile_url() to let skip capabilities check to get the pluginfile URL. * Added new field "enabled" to h5p_libraries to let define if a content type is enabled (1) or not (0). For now, only runnable content-types can be disabled/enabled. When a content-type is disabled, their contents are not displayed and no new contents using it can be created/uploaded. Some extra methods have been added to the api too in order to support this field: - set_library_enabled - is_library_enabled - is_valid_package * The third-party library h5p/h5plib/v124/core has been updated to version 1.24.2. === 3.10 === * Added a new cache for h5p_library_files (MDL-69207) === 3.9 === * A new plugintype has been created, h5plib, for having installed more than one H5P library version. * H5P third-party libraries have been moved from /lib/h5p to h5p/h5plib/v124, as an h5plib plugintype. * H5P Editor PHP library added to h5plib v124 plugin. PK*\f??edit.phpnu[. /** * Open the editor to modify an H5P content from a given H5P URL. * * @package core_h5p * @copyright 2021 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__ . '/../config.php'); require_once("$CFG->libdir/formslib.php"); require_once("$CFG->libdir/filestorage/file_storage.php"); require_login(null, false); $contenturl = required_param('url', PARAM_LOCALURL); $returnurl = optional_param('returnurl', null, PARAM_LOCALURL); // If no returnurl is defined, use local_referer. if (empty($returnurl)) { $returnurl = get_local_referer(false); if (empty($returnurl)) { // If local referer is empty, returnurl will be set to default site page. $returnurl = new \moodle_url('/'); } } $contentid = null; $isreferenced = false; $context = \context_system::instance(); if (!empty($contenturl)) { list($originalfile, $h5p, $file) = \core_h5p\api::get_original_content_from_pluginfile_url($contenturl); $isreferenced = ($file !== false); if ($originalfile) { // Check if the user can edit the content behind the given URL. if (\core_h5p\api::can_edit_content($originalfile)) { if (!$h5p) { // This H5P file hasn't been deployed yet, so it should be saved to create the entry into the H5P DB. \core_h5p\local\library\autoloader::register(); $factory = new \core_h5p\factory(); $config = new \stdClass(); $onlyupdatelibs = !\core_h5p\helper::can_update_library($originalfile); $contentid = \core_h5p\helper::save_h5p($factory, $originalfile, $config, $onlyupdatelibs, false); } else { // The H5P content exists. Update the contentid value. $contentid = $h5p->id; } } if ($file) { list($context, $course, $cm) = get_context_info_array($file->get_contextid()); if ($course) { $context = \context_course::instance($course->id); } } else { list($context, $course, $cm) = get_context_info_array($originalfile->get_contextid()); if ($course) { $context = \context_course::instance($course->id); } } } } if (empty($contentid)) { throw new \moodle_exception('error:emptycontentid', 'core_h5p', $returnurl); } $pagetitle = get_string('h5peditor', 'core_h5p'); $url = new \moodle_url("/h5p/edit.php"); $PAGE->set_context($context); $PAGE->set_url($url); $PAGE->set_title($pagetitle); $PAGE->set_heading($pagetitle); $PAGE->set_pagelayout('course'); $values = [ 'id' => $contentid, 'contenturl' => $contenturl, 'returnurl' => $returnurl, ]; $form = new \core_h5p\form\editcontent_form(null, $values); if ($form->is_cancelled()) { redirect($returnurl); } else if ($data = $form->get_data()) { $form->save_h5p($data); if (!empty($returnurl)) { redirect($returnurl); } } echo $OUTPUT->header(); if ($isreferenced) { echo $OUTPUT->notification(get_string('contentinuse', 'core_h5p'), 'info'); } $form->display(); echo $OUTPUT->footer(); PK*\NUr2ajax.phpnu[. /** * Responsible for handling AJAX requests related to H5P. * * @package core_h5p * @copyright 2020 Victor Deniz , based on code by Joubel AS * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ use core_h5p\factory; use core_h5p\framework; use core_h5p\local\library\autoloader; use Moodle\H5PCore; use Moodle\H5PEditorEndpoints; define('AJAX_SCRIPT', true); require(__DIR__ . '/../config.php'); require_once($CFG->libdir . '/filelib.php'); if (!confirm_sesskey()) { autoloader::register(); H5PCore::ajaxError(get_string('invalidsesskey', 'error')); header('HTTP/1.1 403 Forbidden'); return; } require_login(); $action = required_param('action', PARAM_ALPHA); $factory = new factory(); $editor = $factory->get_editor(); // Set context to default system context. $PAGE->set_context(null); switch ($action) { // Load list of libraries or details for library. case 'libraries': // Get parameters. $name = optional_param('machineName', '', PARAM_TEXT); $major = optional_param('majorVersion', 0, PARAM_INT); $minor = optional_param('minorVersion', 0, PARAM_INT); // Normalise Moodle language using underscore, as opposed to H5P which uses dash. $language = optional_param('default-language', '', PARAM_RAW); $language = clean_param(str_replace('-', '_', $language), PARAM_LANG); if (!empty($name)) { $editor->ajax->action(H5PEditorEndpoints::SINGLE_LIBRARY, $name, $major, $minor, framework::get_language(), '', '', $language); } else { $editor->ajax->action(H5PEditorEndpoints::LIBRARIES); } break; // Load content type cache list to display available libraries in hub. case 'contenttypecache': $editor->ajax->action(H5PEditorEndpoints::CONTENT_TYPE_CACHE); break; // Handle file upload through the editor. // This endpoint needs a token that only users with H5P editor access could get. // TODO: MDL-68907 to check capabilities. case 'files': $token = required_param('token', PARAM_RAW); $contentid = required_param('contentId', PARAM_INT); $maxsize = get_max_upload_file_size($CFG->maxbytes); // Check size of each uploaded file and scan for viruses. foreach ($_FILES as $uploadedfile) { $filename = clean_param($uploadedfile['name'], PARAM_FILE); if ($uploadedfile['size'] > $maxsize) { H5PCore::ajaxError(get_string('maxbytesfile', 'error', ['file' => $filename, 'size' => display_size($maxsize, 0)])); return; } \core\antivirus\manager::scan_file($uploadedfile['tmp_name'], $filename, true); } $editor->ajax->action(H5PEditorEndpoints::FILES, $token, $contentid); break; // Get the $language libraries translations. case 'translations': $language = required_param('language', PARAM_RAW); $editor->ajax->action(H5PEditorEndpoints::TRANSLATIONS, $language); break; // Handle filtering of parameters through AJAX. case 'filter': $token = required_param('token', PARAM_RAW); $libraryparameters = required_param('libraryParameters', PARAM_RAW); $editor->ajax->action(H5PEditorEndpoints::FILTER, $token, $libraryparameters); break; // Throw error if AJAX action is not handled. default: throw new coding_exception('Unhandled AJAX'); break; } PK*\ embed.phpnu[. /** * Render H5P content from an H5P file. * * @package core_h5p * @copyright 2019 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ require_once(__DIR__ . '/../config.php'); // The login check is done inside the player when getting the file from the url param. $url = required_param('url', PARAM_LOCALURL); $config = new stdClass(); $config->frame = optional_param('frame', 0, PARAM_INT); $config->export = optional_param('export', 0, PARAM_INT); $config->embed = optional_param('embed', 0, PARAM_INT); $config->copyright = optional_param('copyright', 0, PARAM_INT); $preventredirect = optional_param('preventredirect', true, PARAM_BOOL); $component = optional_param('component', '', PARAM_COMPONENT); $PAGE->set_url(new \moodle_url('/h5p/embed.php', array('url' => $url))); try { $h5pplayer = new \core_h5p\player($url, $config, $preventredirect, $component); $messages = $h5pplayer->get_messages(); } catch (\Exception $e) { $messages = (object) [ 'exception' => $e->getMessage(), ]; } if (empty($messages->error) && empty($messages->exception)) { // Configure page. $context = $h5pplayer->get_context(); if ($context instanceof context_module) { [$course, $cm] = get_course_and_cm_from_cmid($context->instanceid); $PAGE->set_cm($cm, $course); $PAGE->activityheader->disable(); } else { $PAGE->set_context($context); } $PAGE->set_title($h5pplayer->get_title()); $PAGE->set_heading($h5pplayer->get_title()); // Embed specific page setup. $PAGE->add_body_class('h5p-embed'); $PAGE->set_pagelayout('embedded'); // Load the embed.js to allow communication with the parent window. $PAGE->requires->js(new moodle_url('/h5p/js/embed.js')); // Add H5P assets to the page. $h5pplayer->add_assets_to_page(); // Print page HTML. echo $OUTPUT->header(); // Check if some error has been raised when adding assets to the page. If that's the case, display them above the H5P content. $messages = $h5pplayer->get_messages(); if (!empty($messages->exception) || !empty($messages->error)) { $messages->h5picon = new \moodle_url('/h5p/pix/icon.svg'); echo $OUTPUT->render_from_template('core_h5p/h5perror', $messages); } // Display the H5P content. echo $h5pplayer->output(); } else { // If there is any error or exception when creating the player, it should be displayed. $PAGE->set_context(context_system::instance()); $title = get_string('h5p', 'core_h5p'); $PAGE->set_title($title); $PAGE->set_heading($title); $PAGE->add_body_class('h5p-embed'); $PAGE->set_pagelayout('embedded'); // Load the embed.js to allow communication with the parent window. $PAGE->requires->js(new moodle_url('/h5p/js/embed.js')); echo $OUTPUT->header(); // Print all the errors. $messages->h5picon = new \moodle_url('/h5p/pix/icon.svg'); echo $OUTPUT->render_from_template('core_h5p/h5perror', $messages); } echo $OUTPUT->footer(); PK*\ ^h5plib/v127/thirdpartylibs.xmlnu[ joubel/core h5p-php-library The general H5P library. moodle-1.27.0 GPL 3.0+ https://github.com/h5p/h5p-php-library/ Joubel joubel/editor h5p-editor-php-library A general library that is supposed to be used in most PHP implementations of H5P. moodle-1.27.0 GPL 3.0+ https://github.com/h5p/h5p-editor-php-library/ Joubel PK*\xBs)E)E#h5plib/v127/lang/en/h5plib_v127.phpnu[. /** * Strings for component 'h5p_v127' * * @package h5plib_v127 * @copyright 2024 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $string['editor:a11ytitleshowlabel'] = 'Show label for AT'; $string['editor:a11ytitlehidelabel'] = 'Hide label for AT'; $string['editor:atoz'] = 'A to Z'; $string['editor:add'] = 'Add'; $string['editor:addauthor'] = 'Save author'; $string['editor:addentity'] = 'Add :entity'; $string['editor:addfile'] = 'Add file'; $string['editor:addnewchange'] = 'Add new change'; $string['editor:addtitle'] = 'Add title'; $string['editor:addvideodescription'] = 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.'; $string['editor:avtablistlabel'] = 'Insert using'; $string['editor:belowmin'] = 'The :property value is below the minimum of :min.'; $string['editor:cancel'] = 'Cancel'; $string['editor:cancellabel'] = 'Cancel'; $string['editor:changefile'] = 'Change file'; $string['editor:changelanguage'] = 'Change language to :language?'; $string['editor:changelibrary'] = 'Change content type?'; $string['editor:changelogdescription'] = 'Some licences require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.'; $string['editor:close'] = 'Close'; $string['editor:collapseallcontent'] = 'Collapse all content'; $string['editor:commonfields'] = 'Text overrides and translations'; $string['editor:commonfieldsdescription'] = 'Here you can edit settings or translate texts used in this content.'; $string['editor:confirmchangelibrary'] = 'By doing this you will lose all work done with the current content type. Are you sure you wish to change content type?'; $string['editor:confirmdeletechangelog'] = 'Are you sure you would like to delete this change log entry?'; $string['editor:confirmimageremoval'] = 'This will remove your image. Are you sure you wish to proceed?'; $string['editor:confirmpastebuttontext'] = 'Replace content'; $string['editor:confirmpastecontent'] = 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?'; $string['editor:confirmremoval'] = 'Are you sure you wish to remove this :type?'; $string['editor:confirmremoveauthor'] = 'Are you sure you would like to remove this author?'; $string['editor:contenttypebackbuttonlabel'] = 'Back'; $string['editor:contenttypecacheoutdated'] = 'Content type list outdated'; $string['editor:contenttypecacheoutdateddesc'] = 'Your site is having difficulties connecting to H5P.org to check for content type updates. You may not be able to update or install new content types.'; $string['editor:contenttypedemobuttonlabel'] = 'Content demo'; $string['editor:contenttypedetailbuttonlabel'] = 'Details'; $string['editor:contenttypegetbuttonlabel'] = 'Get'; $string['editor:contenttypeiconalttext'] = 'Icon'; $string['editor:contenttypeinstallbuttonlabel'] = 'Install'; $string['editor:contenttypeinstallerror'] = ':contentType could not be installed. Contact your administrator.'; $string['editor:contenttypeinstallsuccess'] = ':contentType successfully installed!'; $string['editor:contenttypeinstallingbuttonlabel'] = 'Installing'; $string['editor:contenttypelicensepaneltitle'] = 'Licence'; $string['editor:contenttypenotinstalled'] = 'Content type not installed'; $string['editor:contenttypenotinstalleddesc'] = 'You do not have permission to install content types.'; $string['editor:contenttypeowner'] = 'By :owner'; $string['editor:contenttyperestricted'] = 'Restricted content type'; $string['editor:contenttyperestricteddesc'] = 'The use of this content type has been restricted by an administrator.'; $string['editor:contenttypesearchfieldplaceholder'] = 'Search for content types'; $string['editor:contenttypesectionall'] = 'All content types'; $string['editor:contenttypeunsupportedapiversioncontent'] = 'Contact your system administrator to provide you with the necessary updates'; $string['editor:contenttypeunsupportedapiversiontitle'] = 'This content type requires a newer core version'; $string['editor:contenttypeupdateavailable'] = 'Update available'; $string['editor:contenttypeupdatebuttonlabel'] = 'Update'; $string['editor:contenttypeupdatesuccess'] = ':contentType successfully updated!'; $string['editor:contenttypeupdatingbuttonlabel'] = 'Updating'; $string['editor:contenttypeusebuttonlabel'] = 'Use'; $string['editor:contributetranslations'] = 'If you want to complete the translation for :language, see contributing translations to H5P.'; $string['editor:copiedbutton'] = 'Copied'; $string['editor:copiedtoclipboard'] = 'Content is copied to the clipboard'; $string['editor:copybutton'] = 'Copy'; $string['editor:copytoclipboard'] = 'Copy H5P content to the clipboard'; $string['editor:createcontenttablabel'] = 'Create content'; $string['editor:currentmenuselected'] = 'current selection'; $string['editor:editcopyright'] = 'Edit copyright'; $string['editor:editimage'] = 'Edit image'; $string['editor:editmode'] = 'Editing mode'; $string['editor:enteraudiotitle'] = 'Paste link or other audio source URL'; $string['editor:enteraudiourl'] = 'Enter audio source URL'; $string['editor:enterfullscreenbuttonlabel'] = 'Enter fullscreen'; $string['editor:entervideotitle'] = 'Paste YouTube link or other video source URL'; $string['editor:entervideourl'] = 'Enter video URL'; $string['editor:errorcalculatingmaxscore'] = 'Could not calculate the max score for this content. The max score is assumed to be 0. Contact your administrator if this isn’t correct.'; $string['editor:errorcommunicatinghubcontent'] = 'An error occured. Please try again.'; $string['editor:errorcommunicatinghubtitle'] = 'Not able to communicate with hub.'; $string['editor:errorheader'] = 'An error occured'; $string['editor:errornotsupported'] = 'Parameters contain %used which is not supported.'; $string['editor:errorparamsbroken'] = 'Parameters are broken.'; $string['editor:errortoohighversion'] = 'Parameters contain %used while only %supported or earlier are supported.'; $string['editor:example'] = 'Example'; $string['editor:exceedsmax'] = 'The :property value exceeds the maximum of :max.'; $string['editor:exitfullscreenbuttonlabel'] = 'Exit fullscreen'; $string['editor:expandallcontent'] = 'Expand all content'; $string['editor:expandcollapse'] = 'Expand/Collapse'; $string['editor:filetolarge'] = 'The file you are trying to upload might be too large.'; $string['editor:fillinthefieldsbelow'] = 'Fill in the fields below'; $string['editor:gethelp'] = 'Get help'; $string['editor:h5pfileuploadservererrorcontent'] = 'An unexpected error occurred. Check your server error log for more details.'; $string['editor:h5pfileuploadservererrortitle'] = 'The H5P file could not be uploaded'; $string['editor:h5pfilevalidationfailedcontent'] = 'Make sure the uploaded H5P contains valid H5P content. H5P files containing only libraries should be uploaded through the H5P libraries page.'; $string['editor:h5pfilevalidationfailedtitle'] = 'Could not validate H5P file.'; $string['editor:h5pfilewrongextensioncontent'] = 'Only files with the .h5p extension are allowed.'; $string['editor:h5pfilewrongextensiontitle'] = 'The selected file could not be uploaded'; $string['editor:height'] = 'height'; $string['editor:hide'] = 'Hide'; $string['editor:hideimportantinstructions'] = 'Hide important instructions'; $string['editor:hubpanellabel'] = 'Select content type'; $string['editor:illegaldecimalnumber'] = ':property can only contain numbers with max :decimals decimals.'; $string['editor:imagelightboxprogress'] = ':num of :total'; $string['editor:imagelightboxtitle'] = 'Images'; $string['editor:importantinstructions'] = 'Important instructions'; $string['editor:insert'] = 'Insert'; $string['editor:invalidformat'] = 'Field value contains an invalid format or characters that are forbidden.'; $string['editor:language'] = 'Language'; $string['editor:librarymissing'] = 'Missing required library %lib.'; $string['editor:licensecandistribute'] = 'Can distribute'; $string['editor:licensecanholdliable'] = 'Can hold liable'; $string['editor:licensecanmodify'] = 'Can modify'; $string['editor:licensecansublicense'] = 'Can sub-licence'; $string['editor:licensecanusecommercially'] = 'Can use commercially'; $string['editor:licensecannotholdliable'] = 'Cannot hold liable'; $string['editor:licensedescription'] = 'Some of the features of this licence are indicated below. Click the info icon above to read the original licence text.'; $string['editor:licensefetchdetailsfailed'] = 'Failed fetching licence details'; $string['editor:licensemodalsubtitle'] = 'Select a licence to view information about proper usage'; $string['editor:licensemodaltitle'] = 'Licence details'; $string['editor:licensemustincludecopyright'] = 'Must include copyright'; $string['editor:licensemustincludelicense'] = 'Must include licence'; $string['editor:licenseunspecified'] = 'Unspecified'; $string['editor:listbelowmin'] = 'The list needs at least :min items for the content to function properly.'; $string['editor:listexceedsmax'] = 'The list exceeds the maximum of :max items.'; $string['editor:listlabel'] = 'List'; $string['editor:loading'] = 'Loading, please wait...'; $string['editor:loadingimageeditor'] = 'Loading image editor, please wait...'; $string['editor:logthischange'] = 'Log this change'; $string['editor:loggedchanges'] = 'Logged changes'; $string['editor:maxscoresemanticsmissing'] = 'Could not find the expected semantics in the content.'; $string['editor:metadata'] = 'Metadata'; $string['editor:metadatasharingandlicensinginfo'] = 'Metadata (sharing and licencing info)'; $string['editor:missingproperty'] = 'Field :index is missing its :property property.'; $string['editor:missingtranslation'] = '[Missing translation :key]'; $string['editor:newchangehasbeenlogged'] = 'New change has been logged'; $string['editor:newestfirst'] = 'Newest first'; $string['editor:nextimage'] = 'Next image'; $string['editor:nochangeshavebeenlogged'] = 'No changes have been logged'; $string['editor:nocontenttypesavailable'] = 'No content types are available'; $string['editor:nocontenttypesavailabledesc'] = 'Your site is having difficulties connecting to H5P.org and listing the available content types.'; $string['editor:nofollow'] = 'Cannot follow field ":path".'; $string['editor:nolanguagessupported'] = 'No languages supported'; $string['editor:noresultsfound'] = 'No results found'; $string['editor:noresultsfounddesc'] = 'There is no content type that matches your search criteria.'; $string['editor:nosemantics'] = 'Error, could not load the content type form.'; $string['editor:notalltextschanged'] = 'Not all texts were changed, as there is only partial coverage for :language.'; $string['editor:notimagefield'] = '":path" is not an image.'; $string['editor:notimageordimensionsfield'] = '":path" is not an image or dimensions field.'; $string['editor:numresults'] = ':num results'; $string['editor:numberfield'] = 'number field'; $string['editor:ok'] = 'OK'; $string['editor:onlynumbers'] = 'The :property value can only contain numbers.'; $string['editor:or'] = 'or'; $string['editor:orderitemdown'] = 'Order item down'; $string['editor:orderitemup'] = 'Order item up'; $string['editor:outofstep'] = 'The :property value can only be changed in steps of :step.'; $string['editor:pasteandreplacebutton'] = 'Paste and replace'; $string['editor:pasteandreplacefromclipboard'] = 'Replace existing content with H5P content from the clipboard'; $string['editor:pastebutton'] = 'Paste'; $string['editor:pastecontent'] = 'Replace content'; $string['editor:pastecontentnotsupported'] = 'The content in the H5P clipboard is not supported in this context'; $string['editor:pastecontentrestricted'] = 'The content in the clipboard has been restricted on this site'; $string['editor:pasteerror'] = 'Cannot paste from clipboard'; $string['editor:pastefromclipboard'] = 'Paste H5P content from the clipboard'; $string['editor:pastenocontent'] = 'No H5P content on the clipboard'; $string['editor:pastetoonew'] = 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local). If possible, try to have this content upgraded first, then try pasting the content here again.'; $string['editor:pastetooold'] = 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local). If possible, try to have the content you want to paste upgraded, then copy it again and try pasting it here.'; $string['editor:popularfirst'] = 'Popular first'; $string['editor:previousimage'] = 'Previous image'; $string['editor:proceedbuttonlabel'] = 'Proceed to save'; $string['editor:readless'] = 'Read less'; $string['editor:readmore'] = 'Read more'; $string['editor:recentlyusedfirst'] = 'Recently used first'; $string['editor:reloadbuttonlabel'] = 'Reload'; $string['editor:removefile'] = 'Remove file'; $string['editor:removeimage'] = 'Remove image'; $string['editor:removeitem'] = 'Remove item'; $string['editor:requiredproperty'] = 'The :property is required and must have a value.'; $string['editor:resettooriginallabel'] = 'Reset to original'; $string['editor:savelabel'] = 'Save'; $string['editor:savemetadata'] = 'Save metadata'; $string['editor:screenshots'] = 'Screenshots'; $string['editor:scriptmissing'] = 'Could not load upgrades script for %lib.'; $string['editor:searchresults'] = 'Search results'; $string['editor:selectfiletoupload'] = 'Select file to upload'; $string['editor:selectlibrary'] = 'Select the library you wish to use for your content.'; $string['editor:semanticserror'] = 'Semantics error: :error'; $string['editor:show'] = 'Show'; $string['editor:showimportantinstructions'] = 'Show instructions'; $string['editor:tabtitlebasicfileupload'] = 'File upload'; $string['editor:tabtitleinputlinkurl'] = 'Link/URL'; $string['editor:textfield'] = 'text field'; $string['editor:thecontenttype'] = 'the content type'; $string['editor:thiswillpotentially'] = 'This will potentially reset all the text and translations. You can\'t undo this. The content itself will not be changed. Do you want to proceed?'; $string['editor:title'] = 'Title'; $string['editor:toolong'] = 'Field value is too long; it should contain :max letters or less.'; $string['editor:tryagain'] = 'Try again'; $string['editor:tutorial'] = 'Tutorial'; $string['editor:unabletointerpreterror'] = 'Unable to interpret response.'; $string['editor:unabletointerpretsolution'] = 'Please check your error log.'; $string['editor:unknownfieldpath'] = 'Unable to find ":path".'; $string['editor:unknownfileuploaderror'] = 'Unknown file upload error'; $string['editor:unknownlibrary'] = 'Unfortunately, the selected content type \'%lib\' isn\'t installed on this system.'; $string['editor:untitled'] = 'Untitled :libraryTitle'; $string['editor:uploadaudiotitle'] = 'Upload audio file'; $string['editor:uploaderror'] = 'File upload error'; $string['editor:uploadfilebuttonchangelabel'] = 'Change file'; $string['editor:uploadfilebuttonlabel'] = 'Upload a file'; $string['editor:uploadinstructionscontent'] = 'You may start with examples from H5P.org.'; $string['editor:uploadinstructionstitle'] = 'Upload an H5P file.'; $string['editor:uploadplaceholder'] = 'No file chosen'; $string['editor:uploadsuccess'] = ':title was successfully uploaded!'; $string['editor:uploadtablabel'] = 'Upload'; $string['editor:uploadvideotitle'] = 'Upload video file'; $string['editor:uploading'] = 'Uploading, please wait...'; $string['editor:uploadingthrobber'] = 'Now uploading...'; $string['editor:usedforsearchingreportsandcopyrightinformation'] = 'Used for searching, reports and copyright information'; $string['editor:videoquality'] = 'Video quality label'; $string['editor:videoqualitydefaultlabel'] = 'Quality :index'; $string['editor:videoqualitydescription'] = 'This label helps the user identify the current quality of the video. E.g. 1080p, 720p, HD or Mobile'; $string['editor:warningchangebrowsingtoseeresults'] = 'Click All to get the list of all the content types you can install.'; $string['editor:warningnocontenttypesinstalled'] = 'You don\'t have any content types installed.'; $string['editor:warningupdateavailablebody'] = 'Update to the latest version for an improved experience.'; $string['editor:warningupdateavailabletitle'] = 'A new version of :contentType is available.'; $string['editor:width'] = 'width'; $string['pluginname'] = 'H5P framework v1.27'; $string['pluginname_help'] = 'H5P framework version 1.27.'; $string['privacy:metadata'] = 'The H5P framework v1.27 does not store any personal data.'; PK*\6\?h5plib/v127/version.phpnu[. /** * Version information. * * @package h5plib_v127 * @copyright 2024 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ defined('MOODLE_INTERNAL') || die(); $plugin->version = 2025041400; // The current module version (Date: YYYYMMDDXX). $plugin->requires = 2025040800; // Requires this Moodle version. $plugin->component = 'h5plib_v127'; // Full name of the plugin (used for diagnostics). PK*\YX&u  (h5plib/v127/classes/privacy/provider.phpnu[. namespace h5plib_v127\privacy; /** * Privacy provider implementation for this version of the H5P library. * * @package h5plib_v127 * @copyright 2024 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class provider implements \core_privacy\local\metadata\null_provider { /** * Get the language string identifier with the component's language * file to explain why this plugin stores no data. * * @return string */ public static function get_reason(): string { return 'privacy:metadata'; } } PK*\m֓-h5plib/v127/classes/local/library/handler.phpnu[. namespace h5plib_v127\local\library; /** * Handler for this version of the H5P library. * * @package h5plib_v127 * @copyright 2024 Sara Arjona * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class handler extends \core_h5p\local\library\handler { /** * Get the current version of the H5P core library. * * @return string */ public static function get_h5p_version(): string { return '127'; } } PK*\K>>1h5plib/v127/joubel/core/styles/font-open-sans.cssnu[/* Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. */ /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic-ext.woff2') format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic.woff2') format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-greek-ext.woff2') format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-greek.woff2') format('woff2'); unicode-range: U+0370-03FF; } /* hebrew */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-hebrew.woff2') format('woff2'); unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-vietnamese.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-latin-ext.woff2') format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic-ext.woff2') format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic.woff2') format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-greek-ext.woff2') format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-greek.woff2') format('woff2'); unicode-range: U+0370-03FF; } /* hebrew */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-hebrew.woff2') format('woff2'); unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-vietnamese.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-latin-ext.woff2') format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic-ext.woff2') format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic.woff2') format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-greek-ext.woff2') format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-greek.woff2') format('woff2'); unicode-range: U+0370-03FF; } /* hebrew */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-hebrew.woff2') format('woff2'); unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-vietnamese.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-latin-ext.woff2') format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: italic; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-italic-400-600-700-v28-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-cyrillic-ext.woff2') format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-cyrillic.woff2') format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-greek-ext.woff2') format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-greek.woff2') format('woff2'); unicode-range: U+0370-03FF; } /* hebrew */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-hebrew.woff2') format('woff2'); unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-vietnamese.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-latin-ext.woff2') format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 400; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-cyrillic-ext.woff2') format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-cyrillic.woff2') format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-greek-ext.woff2') format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-greek.woff2') format('woff2'); unicode-range: U+0370-03FF; } /* hebrew */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-hebrew.woff2') format('woff2'); unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-vietnamese.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-latin-ext.woff2') format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 600; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; } /* cyrillic-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-cyrillic-ext.woff2') format('woff2'); unicode-range: U+0460-052F, U+1C80-1C88, U+20B4, U+2DE0-2DFF, U+A640-A69F, U+FE2E-FE2F; } /* cyrillic */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-cyrillic.woff2') format('woff2'); unicode-range: U+0400-045F, U+0490-0491, U+04B0-04B1, U+2116; } /* greek-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-greek-ext.woff2') format('woff2'); unicode-range: U+1F00-1FFF; } /* greek */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-greek.woff2') format('woff2'); unicode-range: U+0370-03FF; } /* hebrew */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-hebrew.woff2') format('woff2'); unicode-range: U+0590-05FF, U+200C-2010, U+20AA, U+25CC, U+FB1D-FB4F; } /* vietnamese */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-vietnamese.woff2') format('woff2'); unicode-range: U+0102-0103, U+0110-0111, U+0128-0129, U+0168-0169, U+01A0-01A1, U+01AF-01B0, U+1EA0-1EF9, U+20AB; } /* latin-ext */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-latin-ext.woff2') format('woff2'); unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF; } /* latin */ @font-face { font-family: 'Open Sans'; font-style: normal; font-weight: 700; font-stretch: 100%; font-display: swap; src: url('../fonts/open-sans/opensans-400-600-700-v28-latin.woff2') format('woff2'); unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD; }PK*\"yʛ,h5plib/v127/joubel/core/styles/h5p-admin.cssnu[/* Administration interface styling */ .h5p-content { border: 1px solid #DDD; border-radius: 3px; padding: 10px; } .h5p-admin-table, .h5p-admin-table > tbody { border: none; width: 100%; } .h5p-admin-table tr:nth-child(odd), .h5p-data-view tr:nth-child(odd) { background-color: #F9F9F9; } .h5p-admin-table tbody tr:hover { background-color: #EEE; } .h5p-admin-table.empty { padding: 1em; background-color: #EEE; font-size: 1.2em; font-weight: bold; } .h5p-admin-table.libraries th:last-child, .h5p-admin-table.libraries td:last-child { text-align: right; } .h5p-admin-buttons-wrapper { white-space: nowrap; } .h5p-admin-table.libraries button { font-size: 2em; cursor: pointer; border: 1px solid #AAA; border-radius: .2em; background-color: #e0e0e0; text-shadow: 0 0 0.5em #fff; padding: 0; line-height: 1em; width: 1.125em; height: 1.05em; text-indent: -0.125em; margin: 0.125em 0.125em 0 0.125em; } .h5p-admin-upgrade-library:before { font-family: 'H5P'; content: "\e888"; } .h5p-admin-view-library:before { font-family: 'H5P'; content: "\e889"; } .h5p-admin-delete-library:before { font-family: 'H5P'; content: "\e890"; } .h5p-admin-table.libraries button:hover { background-color: #d0d0d0; } .h5p-admin-table.libraries button:disabled:hover { background-color: #e0e0e0; cursor: default; } .h5p-admin-upgrade-library { color: #339900; } .h5p-admin-view-library { color: #0066cc; } .h5p-admin-delete-library { color: #990000; } .h5p-admin-delete-library:disabled, .h5p-admin-upgrade-library:disabled { cursor: default; color: #c0c0c0; } .h5p-library-info { padding: 1em 1em; margin: 1em 0; width: 350px; border: 1px solid #DDD; border-radius: 3px; } /* Labeled field (label + value) */ .h5p-labeled-field { border-bottom: 1px solid #ccc; } .h5p-labeled-field:last-child { border-bottom: none; } .h5p-labeled-field .h5p-label { display: inline-block; min-width: 150px; font-size: 1.2em; font-weight: bold; padding: 0.2em; } .h5p-labeled-field .h5p-value { display: inline-block; padding: 0.2em; } /* Search element */ .h5p-content-search { display: inline-block; position: relative; width: 100%; padding: 5px 0; margin-top: 10px; border: 1px solid #CCC; border-radius: 3px; box-shadow: 2px 2px 5px #888888; } .h5p-content-search:before { font-family: 'H5P'; vertical-align: bottom; content: "\e88a"; font-size: 2em; line-height: 1.25em; } .h5p-content-search input { font-size: 120%; line-height: 120%; } .h5p-admin-search-results { margin-left: 10px; color: #888; } .h5p-admin-pager-size-selector { position: absolute; right: 10px; top: .75em; display: inline-block; } .h5p-admin-pager-size-selector > span { padding: 5px; margin-left: 10px; cursor: pointer; border: 1px solid #CCC; border-radius: 3px; } .h5p-admin-pager-size-selector > span.selected { background-color: #edf5fa; } .h5p-admin-pager-size-selector > span:hover { background-color: #555; color: #FFF; } /* Generic "javascript"-action button */ button.h5p-admin { border: 1px solid #AAA; border-radius: 5px; padding: 3px 10px; background-color: #EEE; cursor: pointer; display: inline-block; text-align: center; color: #222; } button.h5p-admin:hover { background-color: #555; color: #FFF; } button.h5p-admin.disabled, button.h5p-admin.disabled:hover { cursor: auto; color: #CCC; background-color: #FFF; } /* Pager element */ .h5p-content-pager { display: inline-block; border: 1px solid #CCC; border-radius: 3px; box-shadow: 2px 2px 5px #888888; width: 100%; text-align: center; padding: 3px 0; } .h5p-content-pager > button { min-width: 80px; font-size: 130%; line-height: 130%; border: none; background: none; font-family: 'H5P'; font-size: 1.4em; } .h5p-content-pager > button:focus { outline: 0; } .h5p-content-pager > button:last-child { margin-left: 10px; } .h5p-content-pager > .pager-info { cursor: pointer; padding: 5px; border-radius: 3px; } .h5p-content-pager > .pager-info:hover { background-color: #555; color: #FFF; } .h5p-content-pager > .pager-info, .h5p-content-pager > .h5p-pager-goto { margin: 0 10px; line-height: 130%; display: inline-block; } .h5p-admin-header { margin-top: 1.5em; } #h5p-library-upload-form.h5p-admin-upload-libraries-form, #h5p-content-type-cache-update-form.h5p-admin-upload-libraries-form { position: relative; margin: 0; } .h5p-admin-upload-libraries-form .form-submit { position: absolute; top: 0; right: 0; } .h5p-spinner { padding: 0 0.5em; font-size: 1.5em; font-weight: bold; } #h5p-admin-container .h5p-admin-center { text-align: center; } .h5p-pagination { text-align: center; } .h5p-pagination > span, .h5p-pagination > input { margin: 0 1em; } .h5p-data-view input[type="text"] { margin-bottom: 0.5em; margin-right: 0.5em; float: left; } .h5p-data-view input[type="text"]::-ms-clear { display: none; } .h5p-data-view .h5p-others-contents-toggler-wrapper { float: right; line-height: 2; margin-right: 0.5em; } .h5p-data-view .h5p-others-contents-toggler-label { font-size: 14px; } .h5p-data-view .h5p-others-contents-toggler { margin-right: 0.5em; } .h5p-data-view th[role="button"] { cursor: pointer; } .h5p-data-view th[role="button"].h5p-sort:after, .h5p-data-view th[role="button"]:hover:after, .h5p-data-view th[role="button"].h5p-sort.h5p-reverse:hover:after { content: "\25BE"; position: relative; left: 0.5em; top: -1px; } .h5p-data-view th[role="button"].h5p-sort.h5p-reverse:after, .h5p-data-view th[role="button"].h5p-sort:hover:after { content: "\25B4"; top: -2px; } .h5p-data-view th[role="button"]:hover:after, .h5p-data-view th[role="button"].h5p-sort.h5p-reverse:hover:after, .h5p-data-view th[role="button"].h5p-sort:hover:after { color: #999; } .h5p-data-view .h5p-facet { cursor: pointer; color: #0073aa; outline: none; } .h5p-data-view .h5p-facet:hover, .h5p-data-view .h5p-facet:active { color: #00a0d2; } .h5p-data-view .h5p-facet:focus { color: #124964; box-shadow: 0 0 0 1px #5b9dd9,0 0 2px 1px rgba(30,140,190,.8); } .h5p-data-view .h5p-facet-wrapper { line-height: 23px; } .h5p-data-view .h5p-facet-tag { margin: 2px 0 0 0.5em; font-size: 12px; background: #e8e8e8; border: 1px solid #cbcbcc; border-radius: 5px; color: #5d5d5d; padding: 0 24px 0 10px; display: inline-block; position: relative; } .h5p-data-view .h5p-facet-tag > span { position: absolute; right: 0; top: auto; bottom: auto; font-size: 18px; color: #a2a2a2; outline: none; width: 21px; text-indent: 4px; letter-spacing: 10px; overflow: hidden; cursor: pointer; } .h5p-data-view .h5p-facet-tag > span:before { content: "×"; font-weight: bold; } .h5p-data-view .h5p-facet-tag > span:hover, .h5p-data-view .h5p-facet-tag > span:focus { color: #a20000; } .h5p-data-view .h5p-facet-tag > span:active { color: #d20000; } .content-upgrade-log { color: red; } PK*\12h5plib/v127/joubel/core/styles/h5p-core-button.cssnu[button.h5p-core-button:visited, button.h5p-core-button:link, button.h5p-core-button { font-family: "Open Sans", sans-serif; font-weight: 600; font-size: 1em; line-height: 1.2; padding: 0.5em 1.25em; border-radius: 2em; background: #2579c6; color: #fff; cursor: pointer; border: none; box-shadow: none; outline: none; display: inline-block; text-align: center; text-shadow: none; vertical-align: baseline; text-decoration: none; -webkit-transition: initial; transition: initial; } button.h5p-core-button:focus { background: #1f67a8; } button.h5p-core-button:hover { background: rgba(31, 103, 168, 0.83); } button.h5p-core-button:active { background: #104888; } button.h5p-core-button:before { font-family: 'H5P'; padding-right: 0.15em; font-size: 1.5em; vertical-align: middle; line-height: 0.7; } button.h5p-core-cancel-button:visited, button.h5p-core-cancel-button:link, button.h5p-core-cancel-button { border: none; background: none; color: #a00; margin-right: 1em; font-size: 1em; text-decoration: none; cursor: pointer; } button.h5p-core-cancel-button:hover, button.h5p-core-cancel-button:focus { background: none; border: none; color: #e40000; } PK*\ crm\m\7h5plib/v127/joubel/core/styles/h5p-hub-registration.cssnu[.h5p-hub-publish button,.h5p-hub-registration button{font-family:"Open Sans", sans-serif;font-size:0.75em;background:transparent;padding:0.75em 2em;color:#757575;border-radius:3em;border:1px solid #d6d6d6;cursor:pointer;font-weight:bold}.h5p-hub-publish button:before,.h5p-hub-registration button:before{font-weight:normal}.h5p-hub-publish button:hover,.h5p-hub-registration button:hover{color:#5f5f5f;border-color:#5f5f5f}.h5p-hub-publish button.h5p-hub-contained.h5p-hub-green,.h5p-hub-registration button.h5p-hub-contained.h5p-hub-green{background-color:#186df7;color:#fff;border-color:#186df7}.h5p-hub-publish button.h5p-hub-contained.h5p-hub-green:hover,.h5p-hub-registration button.h5p-hub-contained.h5p-hub-green:hover{background-color:#2e46a4;border-color:#2e46a4}.h5p-hub-publish button.h5p-hub-outlined.h5p-hub-green,.h5p-hub-registration button.h5p-hub-outlined.h5p-hub-green{border-width:0.125em;background-color:white;border-color:#186df7;color:#186df7}.h5p-hub-publish button.h5p-hub-outlined.h5p-hub-green:hover,.h5p-hub-registration button.h5p-hub-outlined.h5p-hub-green:hover{background-color:#186df7;border-color:#186df7;color:#ffffff}.h5p-hub-publish button.h5p-hub-outlined.h5p-hub-green[disabled],.h5p-hub-registration button.h5p-hub-outlined.h5p-hub-green[disabled]{color:#aac3ec;border-color:#aac3ec;background-color:white;pointer-events:none}.h5p-hub-publish .h5p-hub-navigation button{padding:0.833em;max-width:10.5em} .h5p-hub-publish .h5p-hub-form-element,.h5p-hub-registration .h5p-hub-form-element{font-family:Nunito, sans-serif;font-size:16px;padding:1em 0}.h5p-hub-publish .h5p-hub-form-element label,.h5p-hub-registration .h5p-hub-form-element label{display:block;margin-bottom:0.4em;font-weight:bold}.h5p-hub-publish .h5p-hub-form-element.h5p-hub-mandatory label:after,.h5p-hub-registration .h5p-hub-form-element.h5p-hub-mandatory label:after{content:'*';color:#d11e15;position:relative;top:-0.2em}.h5p-hub-publish .h5p-hub-form-element input,.h5p-hub-registration .h5p-hub-form-element input{border-radius:0.208em;width:100%;box-sizing:border-box;line-height:normal}.h5p-hub-publish .h5p-hub-form-element input::placeholder,.h5p-hub-registration .h5p-hub-form-element input::placeholder{font-style:italic}.h5p-hub-publish .h5p-hub-form-element .h5p-hub-description,.h5p-hub-registration .h5p-hub-form-element .h5p-hub-description{font-size:0.833em;color:#707475;margin:0 0 1em 0}.h5p-hub-publish .h5p-hub-form-element textarea,.h5p-hub-registration .h5p-hub-form-element textarea{resize:none;width:100%;border-radius:0.208em;box-sizing:border-box;line-height:1.25em}.h5p-hub-publish .h5p-hub-form-element textarea::-webkit-scrollbar,.h5p-hub-registration .h5p-hub-form-element textarea::-webkit-scrollbar{background-color:rgba(105,117,133,0.25);width:0.333em;border-radius:5.45256em}.h5p-hub-publish .h5p-hub-form-element textarea::-webkit-scrollbar-thumb,.h5p-hub-registration .h5p-hub-form-element textarea::-webkit-scrollbar-thumb{background-color:#697585;background-size:24px 100%;border-radius:5.45256em}.h5p-hub-publish .h5p-hub-form-element textarea::placeholder,.h5p-hub-registration .h5p-hub-form-element textarea::placeholder{font-style:italic}.h5p-hub-publish .h5p-hub-form-element .h5p-hub-link-button,.h5p-hub-registration .h5p-hub-form-element .h5p-hub-link-button{border:none;text-decoration:underline;text-align:right;align-self:flex-start;color:#186df7;font-size:.917em;font-weight:normal;padding:0}.h5p-hub-publish .h5p-hub-form-element .h5p-hub-details-row,.h5p-hub-registration .h5p-hub-form-element .h5p-hub-details-row{display:flex;align-content:center;align-items:center;justify-content:space-between}.h5p-hub-publish .h5p-hub-form-element textarea,.h5p-hub-publish .h5p-hub-form-element input,.h5p-hub-publish .h5p-hub-form-element select,.h5p-hub-registration .h5p-hub-form-element textarea,.h5p-hub-registration .h5p-hub-form-element input,.h5p-hub-registration .h5p-hub-form-element select{padding:.958em;border:2px solid #e2e5ee;box-shadow:none;color:#3c4859;font-family:Nunito, sans-serif}.h5p-hub-publish .h5p-hub-form-element textarea:focus,.h5p-hub-publish .h5p-hub-form-element input:focus,.h5p-hub-publish .h5p-hub-form-element select:focus,.h5p-hub-registration .h5p-hub-form-element textarea:focus,.h5p-hub-registration .h5p-hub-form-element input:focus,.h5p-hub-registration .h5p-hub-form-element select:focus{border-color:#98cbe8;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(152,203,232,0.6);outline:none}.h5p-hub-publish .h5p-hub-step-content>.h5p-hub-form-element:first-child,.h5p-hub-registration .h5p-hub-step-content>.h5p-hub-form-element:first-child{padding-top:0}.h5p-hub-publish .h5p-hub-step-content>.h5p-hub-form-element:last-child,.h5p-hub-registration .h5p-hub-step-content>.h5p-hub-form-element:last-child{padding-bottom:0} /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ /* Document ========================================================================== */ /** * 1. Correct the line height in all browsers. * 2. Prevent adjustments of font size after orientation changes in iOS. */ html { line-height: 1.15; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ } /* Sections ========================================================================== */ /** * Remove the margin in all browsers. */ body { margin: 0; } /** * Render the `main` element consistently in IE. */ main { display: block; } /** * Correct the font size and margin on `h1` elements within `section` and * `article` contexts in Chrome, Firefox, and Safari. */ h1 { font-size: 2em; margin: 0.67em 0; } /* Grouping content ========================================================================== */ /** * 1. Add the correct box sizing in Firefox. * 2. Show the overflow in Edge and IE. */ hr { box-sizing: content-box; /* 1 */ height: 0; /* 1 */ overflow: visible; /* 2 */ } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ pre { font-family: monospace, monospace; /* 1 */ font-size: 1em; /* 2 */ } /* Text-level semantics ========================================================================== */ /** * Remove the gray background on active links in IE 10. */ a { background-color: transparent; } /** * 1. Remove the bottom border in Chrome 57- * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ abbr[title] { border-bottom: none; /* 1 */ text-decoration: underline; /* 2 */ text-decoration: underline dotted; /* 2 */ } /** * Add the correct font weight in Chrome, Edge, and Safari. */ b, strong { font-weight: bolder; } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ code, kbd, samp { font-family: monospace, monospace; /* 1 */ font-size: 1em; /* 2 */ } /** * Add the correct font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` elements from affecting the line height in * all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } /* Embedded content ========================================================================== */ /** * Remove the border on images inside links in IE 10. */ img { border-style: none; } /* Forms ========================================================================== */ /** * 1. Change the font styles in all browsers. * 2. Remove the margin in Firefox and Safari. */ button, input, optgroup, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 1 */ line-height: 1.15; /* 1 */ margin: 0; /* 2 */ } /** * Show the overflow in IE. * 1. Show the overflow in Edge. */ button, input { /* 1 */ overflow: visible; } /** * Remove the inheritance of text transform in Edge, Firefox, and IE. * 1. Remove the inheritance of text transform in Firefox. */ button, select { /* 1 */ text-transform: none; } /** * Correct the inability to style clickable types in iOS and Safari. */ button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } /** * Remove the inner border and padding in Firefox. */ button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; } /** * Restore the focus styles unset by the previous rule. */ button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } /** * Correct the padding in Firefox. */ fieldset { padding: 0.35em 0.75em 0.625em; } /** * 1. Correct the text wrapping in Edge and IE. * 2. Correct the color inheritance from `fieldset` elements in IE. * 3. Remove the padding so developers are not caught out when they zero out * `fieldset` elements in all browsers. */ legend { box-sizing: border-box; /* 1 */ color: inherit; /* 2 */ display: table; /* 1 */ max-width: 100%; /* 1 */ padding: 0; /* 3 */ white-space: normal; /* 1 */ } /** * Add the correct vertical alignment in Chrome, Firefox, and Opera. */ progress { vertical-align: baseline; } /** * Remove the default vertical scrollbar in IE 10+. */ textarea { overflow: auto; } /** * 1. Add the correct box sizing in IE 10. * 2. Remove the padding in IE 10. */ [type="checkbox"], [type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * Correct the cursor style of increment and decrement buttons in Chrome. */ [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Correct the odd appearance in Chrome and Safari. * 2. Correct the outline style in Safari. */ [type="search"] { -webkit-appearance: textfield; /* 1 */ outline-offset: -2px; /* 2 */ } /** * Remove the inner padding in Chrome and Safari on macOS. */ [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * 1. Correct the inability to style clickable types in iOS and Safari. * 2. Change font properties to `inherit` in Safari. */ ::-webkit-file-upload-button { -webkit-appearance: button; /* 1 */ font: inherit; /* 2 */ } /* Interactive ========================================================================== */ /* * Add the correct display in Edge, IE 10+, and Firefox. */ details { display: block; } /* * Add the correct display in all browsers. */ summary { display: list-item; } /* Misc ========================================================================== */ /** * Add the correct display in IE 10+. */ template { display: none; } /** * Add the correct display in IE 10. */ [hidden] { display: none; } @keyframes spinner{0%{transform:translate3d(-50%, -50%, 0) rotate(0deg)}100%{transform:translate3d(-50%, -50%, 0) rotate(360deg)}}.h5p-hub-publish,.h5p-hub-registration-wrapper{position:relative;margin:2em auto;max-width:1024px;border:1px solid #2c9586;border-radius:0.167em;box-sizing:border-box;box-shadow:0px 0px 20px rgba(0,0,0,0.1);font-family:Nunito, sans-serif;font-size:16px;padding-top:0.25em}.h5p-hub-publish .h5p-hub-header,.h5p-hub-registration-wrapper .h5p-hub-header{padding:1.5em;display:flex;align-items:center;width:100%;box-sizing:border-box;border-bottom:1px solid #d5d5d7;border-bottom-color:#e2e5ee}.h5p-hub-publish .h5p-hub-header .h5p-hub-title,.h5p-hub-registration-wrapper .h5p-hub-header .h5p-hub-title{font-size:1.458em;flex-grow:1;color:black;padding-left:1em}.h5p-hub-publish .h5p-hub-step-panel,.h5p-hub-registration-wrapper .h5p-hub-step-panel{margin:2em;border-radius:0.208em;border:1px solid #e2e5ee}.h5p-hub-publish .h5p-hub-step-title,.h5p-hub-registration-wrapper .h5p-hub-step-title{color:#1a1a1a;font-size:1.250em;font-weight:bold;border-bottom:1px solid #ccc;padding:1.2em 1.8em;line-height:normal;border-bottom-color:#e2e5ee}.h5p-hub-publish .h5p-hub-step-content,.h5p-hub-registration-wrapper .h5p-hub-step-content{padding:2em}.h5p-hub-publish .h5p-hub-footer,.h5p-hub-registration-wrapper .h5p-hub-footer{padding:0 2em 2em;width:100%;box-sizing:border-box;position:relative}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation{display:flex}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation button,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation button{z-index:1}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation button:before,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation button:before{font-family:'h5p';font-size:0.75em;content:"\e91a";transform:rotate(180deg);display:inline-block;margin-right:0.75em;line-height:1;position:relative;top:-0.1em}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation .h5p-hub-back:before,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation .h5p-hub-back:before{transform:rotate(0)}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation #h5p-hub-share-in-process::before,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation #h5p-hub-share-in-process::before{font-family:"h5p";font-size:0.75em;content:"\e928";animation:2s linear infinite spinner;top:0.5em;margin-left:0.55em}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation .h5p-hub-next,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation .h5p-hub-next{margin-left:auto}.h5p-hub-publish .h5p-hub-tip-text-field,.h5p-hub-registration-wrapper .h5p-hub-tip-text-field{top:1.5em}.h5p-hub-publish .h5p-hub-hare-error,.h5p-hub-registration-wrapper .h5p-hub-hare-error{padding:0 2em 2em;text-align:end}.h5p-hub-publish .h5p-hub-bold,.h5p-hub-registration-wrapper .h5p-hub-bold{font-weight:bold}.h5p-hub-publish .h5p-hub-row,.h5p-hub-registration-wrapper .h5p-hub-row{display:flex;flex-wrap:wrap;margin-right:-1em}.h5p-hub-publish .h5p-hub-row .h5p-hub-form-element,.h5p-hub-registration-wrapper .h5p-hub-row .h5p-hub-form-element{flex-basis:100%;flex:1;min-width:17em;align-self:flex-end;border-right:1em solid #ffffff}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-row .h5p-hub-form-element,.h5p-hub-registration-wrapper .h5p-hub-row .h5p-hub-form-element{min-width:calc(100% - 1em)}}.h5p-hub-publish .h5p-hub-columns,.h5p-hub-registration-wrapper .h5p-hub-columns{display:flex;margin-right:-1em}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-columns,.h5p-hub-registration-wrapper .h5p-hub-columns{flex-wrap:wrap}}.h5p-hub-publish .h5p-hub-columns .h5p-hub-column,.h5p-hub-registration-wrapper .h5p-hub-columns .h5p-hub-column{width:50%;border-right:1em solid #ffffff}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-columns .h5p-hub-column,.h5p-hub-registration-wrapper .h5p-hub-columns .h5p-hub-column{width:100%;margin-right:0}}.h5p-hub-publish .h5p-hub-sharing-note,.h5p-hub-registration-wrapper .h5p-hub-sharing-note{text-align:center;color:#707475;width:calc(100% - 4.9em);position:absolute;top:0.65em;box-sizing:border-box;padding:0 9em}.h5p-hub-publish .h5p-hub-sharing-note .h5p-hub-icon-info:before,.h5p-hub-registration-wrapper .h5p-hub-sharing-note .h5p-hub-icon-info:before{font-size:0.5em;display:inline-block;margin-right:1em;background:#d1d7e3;padding:0.4em;border-radius:50%;position:relative;top:-0.25em}.h5p-hub-publish .h5p-hub-sr-only,.h5p-hub-registration-wrapper .h5p-hub-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.h5p-hub-publish [class^="h5p-hub-icon-"],.h5p-hub-publish [class*=" h5p-hub-icon-"],.h5p-hub-registration-wrapper [class^="h5p-hub-icon-"],.h5p-hub-registration-wrapper [class*=" h5p-hub-icon-"]{font-family:'h5p' !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.h5p-hub-publish .h5p-hub-icon-dropdown:before,.h5p-hub-registration-wrapper .h5p-hub-icon-dropdown:before{content:"\e925"}.h5p-hub-publish .h5p-hub-icon-info:before,.h5p-hub-registration-wrapper .h5p-hub-icon-info:before{content:"\e93c"}.h5p-hub-publish .h5p-hub-icon-thick-arrow:before,.h5p-hub-registration-wrapper .h5p-hub-icon-thick-arrow:before{content:"\e91a"}.h5p-hub-publish .h5p-hub-icon-check:before,.h5p-hub-registration-wrapper .h5p-hub-icon-check:before{content:"\e933"}.h5p-hub-publish .h5p-hub-icon-close:before,.h5p-hub-registration-wrapper .h5p-hub-icon-close:before{content:"\e93a"}.h5p-hub-publish .h5p-hub-icon-plus:before,.h5p-hub-registration-wrapper .h5p-hub-icon-plus:before{content:"\e939"}.h5p-hub-publish button,.h5p-hub-registration-wrapper button{font-size:.917em;border-width:.125em;border-radius:.208em;padding:.833em 1.65em;background:#fff;color:#3c4859;font-family:Nunito, sans-serif;outline:none;transition:all 0.1s}.h5p-hub-publish button:hover,.h5p-hub-registration-wrapper button:hover{color:#3c4859;background:#e2e5ee;border-color:#e2e5ee}.h5p-hub-registration-wrapper{border:none}.h5p-hub-publish{border:1px solid #e2e5ee}.h5p-hub-share-error{margin:2em} .h5p-hub-registration .h5p-hub-message-header{font-weight:bold;font-size:1.042em;font-family:'Open Sans', sans-serif}.h5p-hub-registration .h5p-hub-message-description{margin-top:0.5em;font-size:0.833em;font-family:'Open Sans', sans-serif}.h5p-hub-registration .h5p-hub-message-description a{margin-left:0.3em;color:#000}.h5p-hub-registration .h5p-hub-email-address{display:flex;flex-direction:column;justify-content:flex-end}.h5p-hub-registration .h5p-hub-publisher-description{height:10em}.h5p-hub-registration .h5p-hub-logo-upload-text{font-size:0.917em;color:#707475;margin-bottom:1em;margin-top:0.5em}.h5p-hub-registration .h5p-hub-text-field{max-height:10em;margin-top:1.5em}.h5p-hub-registration .h5p-hub-checkbox{margin-top:1.5em;font-weight:normal;font-size:.917em}.h5p-hub-registration .h5p-hub-register-hub{margin-left:1em;border:2px solid #186df7;background-color:#186df7;color:#fff}.h5p-hub-registration .h5p-hub-register-hub[disabled]{color:#aac3ec;border-color:#aac3ec;background-color:white;pointer-events:none}.h5p-hub-registration .h5p-hub-register-hub:hover{background-color:#2e46a4;border-color:#2e46a4;color:white}.h5p-hub-registration .h5p-hub-footer{display:flex;justify-content:flex-end} .h5p-hub-publish .h5p-hub-image-preview,.h5p-hub-registration .h5p-hub-image-preview{width:4em;height:3em;display:inline-block;background-position:center;background-size:contain;background-repeat:no-repeat;background-color:#d0d0d1} .h5p-hub-publish .h5p-hub-image-upload-container,.h5p-hub-registration .h5p-hub-image-upload-container{width:4em;height:3em;margin-right:1em;position:relative;display:flex}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close{cursor:pointer;font-size:1em;border:none;outline:none;position:absolute;right:0;padding:0}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close::before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close::before{font-size:0.6em;padding:0.5em;line-height:1.1;color:#fff;background:#000;position:absolute;z-index:1;display:inline-block;right:-1.2em;top:-1.2em;border:3px solid #fff;border-radius:50%;cursor:pointer;transition:all 0.3s}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close:hover::before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close:hover::before{background:#eee;color:#000}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close:focus::before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close:focus::before{outline:#000;outline-style:auto}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;transition:all 0.3s;border:0.125em dashed #bebdcd;color:#bebdcd}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload input,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload input{position:absolute;left:0;top:0;width:100%;height:100%;cursor:pointer;opacity:0}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload input::-webkit-file-upload-button,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload input::-webkit-file-upload-button{visibility:hidden}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload:hover,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload:hover{color:#777;border-color:#777}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload:before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload:before{content:"+";font-size:2em;display:inline-block;position:relative;top:50%;transform:translateY(-50%)}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected{border-style:solid;border-radius:0.1em}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected:before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected:before{display:none} .h5p-hub-registration .h5p-hub-text-field{padding:1.5em;overflow:hidden;overflow-y:scroll;border:1px solid #bebdcd;border-radius:0.208em}.h5p-hub-registration .h5p-hub-text-field::-webkit-scrollbar{background-color:rgba(105,117,133,0.25);width:0.333em;border-radius:5.45256em}.h5p-hub-registration .h5p-hub-text-field::-webkit-scrollbar-thumb{background-color:#697585;background-size:24px 100%;border-radius:5.45256em}.h5p-hub-registration .h5p-hub-text-field .h5p-hub-title{color:#1a1a1a;font-size:1.250em;margin-bottom:0.5em}.h5p-hub-registration .h5p-hub-text-field .h5p-hub-description{color:#707475;font-size:0.833em;margin-bottom:1.5em}.h5p-hub-registration .h5p-hub-text-field .h5p-hub-main-text{color:#707475;font-size:0.833em} .h5p-hub-registration .h5p-hub-checkbox{font-size:1.05em;padding:0.5em 0;font-weight:bold;display:flex;cursor:pointer;align-self:start;color:#4d5057;width:100%;position:relative}.h5p-hub-registration .h5p-hub-checkbox>input{visibility:hidden;position:absolute}.h5p-hub-registration .h5p-hub-checkbox:focus{box-shadow:0 0 0.4em 0.01em RGBA(26, 147, 244, 0.7);outline:none}.h5p-hub-registration .h5p-hub-checkbox .h5p-hub-icon:before{font-family:'h5p';content:'\e923';font-style:normal;font-weight:normal;font-size:1em;margin:0.4em 0.4em 0 0.4em;margin-right:1em}.h5p-hub-registration .h5p-hub-checkbox.h5p-hub-checked .h5p-hub-icon:before{content:'\e938';font-family:'h5p';font-style:normal;font-weight:normal;font-size:1em;margin:0.4em 0.4em 0 0.4em;margin-right:1em} .h5p-hub-publish .h5p-hub-message,.h5p-hub-registration .h5p-hub-message{font-size:1em;border-left:0.3em solid;padding:1em;margin:0.5em 0}.h5p-hub-publish .h5p-hub-message.h5p-hub-warning,.h5p-hub-registration .h5p-hub-message.h5p-hub-warning{border-color:#fdcc31;background:#fff8e0}.h5p-hub-publish .h5p-hub-message.h5p-hub-error,.h5p-hub-registration .h5p-hub-message.h5p-hub-error{border-color:#c1494b;background-color:#ece0e0;color:#c1494b}.h5p-hub-publish .h5p-hub-message.h5p-hub-success,.h5p-hub-registration .h5p-hub-message.h5p-hub-success{border-color:#03a953;background-color:#d9eae2} PK*\$v33&h5plib/v127/joubel/core/styles/h5p.cssnu[/* Import common fonts */ @import 'font-open-sans.css'; /* General CSS for H5P. Licensed under the MIT License.*/ /* Custom H5P font to use for icons. */ @font-face { font-family: 'h5p'; src: url('../fonts/h5p-core-30.eot?h1atjl'); src: url('../fonts/h5p-core-30.eot?h1atjl#iefix') format('embedded-opentype'), url('../fonts/h5p-core-30.ttf?h1atjl') format('truetype'), url('../fonts/h5p-core-30.woff?h1atjl') format('woff'), url('../fonts/h5p-core-30.svg?h1atjl#h5p-core-30') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'h5p-hub-publish'; src: url('../fonts/h5p-hub-publish.eot?wy8ylc'); src: url('../fonts/h5p-hub-publish.eot?wy8ylc#iefix') format('embedded-opentype'), url('../fonts/h5p-hub-publish.ttf?wy8ylc') format('truetype'), url('../fonts/h5p-hub-publish.woff?wy8ylc') format('woff'), url('../fonts/h5p-hub-publish.svg?wy8ylc#h5p-hub') format('svg'); font-weight: normal; font-style: normal; font-display: block; } html.h5p-iframe, html.h5p-iframe > body { font-family: Sans-Serif; /* Use the browser's default sans-serif font. (Since Heletica doesn't look nice on Windows, and Arial on OS X.) */ width: 100%; height: 100%; margin: 0; padding: 0; } .h5p-semi-fullscreen, .h5p-fullscreen, html.h5p-iframe .h5p-container { overflow: hidden; } .h5p-content { position: relative; background: #fefefe; border: 1px solid #EEE; border-bottom: none; box-sizing: border-box; -moz-box-sizing: border-box; } .h5p-noselect { -khtml-user-select: none; -ms-user-select: none; -moz-user-select: none; -webkit-user-select: none; user-select: none; } html.h5p-iframe .h5p-content { font-size: 16px; line-height: 1.5em; width: 100%; height: auto; -webkit-text-size-adjust: none; text-size-adjust: none; } html.h5p-iframe .h5p-fullscreen .h5p-content, html.h5p-iframe .h5p-semi-fullscreen .h5p-content { height: 100%; } .h5p-content.h5p-no-frame, .h5p-fullscreen .h5p-content, .h5p-semi-fullscreen .h5p-content { border: 0; } .h5p-container { position: relative; z-index: 1; } .h5p-iframe-wrapper.h5p-fullscreen { background-color: #000; } body.h5p-semi-fullscreen { position: fixed; width: 100%; height: 100%; } .h5p-container.h5p-semi-fullscreen { position: fixed; top: 0; left: 0; z-index: 101; width: 100%; height: 100%; background-color: #FFF; } .h5p-content-controls { margin: 0; position: absolute; right: 0; top: 0; z-index: 3; } .h5p-fullscreen .h5p-content-controls { display: none; } .h5p-content-controls > a:link, .h5p-content-controls > a:visited, a.h5p-disable-fullscreen:link, a.h5p-disable-fullscreen:visited { color: #e5eef6; } .h5p-enable-fullscreen:before { font-family: 'H5P'; content: "\e88c"; } .h5p-disable-fullscreen:before { font-family: 'H5P'; content: "\e891"; } .h5p-enable-fullscreen, .h5p-disable-fullscreen { cursor: pointer; color: #EEE; background: rgb(0,0,0); background: rgba(0,0,0,0.3); line-height: 0.975em; font-size: 2em; width: 1.125em; height: 1em; text-indent: 0.04em; } .h5p-disable-fullscreen { line-height: 0.925em; width: 1.1em; height: 0.9em; } .h5p-enable-fullscreen:focus, .h5p-disable-fullscreen:focus { outline-style: solid; outline-width: 1px; outline-offset: 0.25em; } .h5p-enable-fullscreen:hover, .h5p-disable-fullscreen:hover { background: rgba(0,0,0,0.5); } .h5p-semi-fullscreen .h5p-enable-fullscreen { display: none; } div.h5p-fullscreen { width: 100%; height: 100%; } .h5p-iframe-wrapper { width: auto; height: auto; } .h5p-fullscreen .h5p-iframe-wrapper, .h5p-semi-fullscreen .h5p-iframe-wrapper { width: 100%; height: 100%; } .h5p-iframe-wrapper.h5p-semi-fullscreen { width: auto; height: auto; background: black; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 100001; } .h5p-iframe-wrapper.h5p-semi-fullscreen .buttons { position: absolute; top: 0; right: 0; z-index: 20; } .h5p-iframe-wrapper iframe.h5p-iframe { /* Hack for IOS landscape / portrait */ width: 10px; min-width: 100%; *width: 100%; /* End of hack */ height: 100%; z-index: 10; overflow: hidden; border: 0; display: block; } .h5p-content ul.h5p-actions { box-sizing: border-box; -moz-box-sizing: border-box; list-style: none; padding: 0px 10px; margin: 0; height: 25px; font-size: 12px; background: #FAFAFA; border-top: 1px solid #EEE; border-bottom: 1px solid #EEE; clear: both; font-family: Sans-Serif; } .h5p-fullscreen .h5p-actions, .h5p-semi-fullscreen .h5p-actions { display: none; } .h5p-actions > .h5p-button { float: left; cursor: pointer; margin: 0 0.5em 0 0; background: none; padding: 0 0.75em 0 0.25em; vertical-align: top; color: #707070; text-decoration: none; outline: none; line-height: 22px; } .h5p-actions button:hover { color: #333; } .h5p-actions button:active, .h5p-actions button:focus, .h5p-actions .h5p-link:active, .h5p-actions .h5p-link:focus { color: #666; } .h5p-actions button { display: inline-flex; padding: 0; margin: 0; color: #6A6A6A; position: relative; /* Disable default button style */ background: none; border: none; font: inherit; cursor: pointer; line-height: 2; } .h5p-actions button:focus, .h5p-actions .h5p-link:focus { outline-style: solid; outline-width: thin; outline-offset: -2px; outline-color: #5981A1; } .h5p-actions button:before { font-family: 'H5P'; font-size: 20px; line-height: 23px; vertical-align: bottom; padding-right: 0; } .h5p-actions > .h5p-button.h5p-export > button:before { content: "\e90b"; } .h5p-actions > .h5p-button.h5p-copyrights > button:before { content: "\e88f"; } .h5p-actions > .h5p-button.h5p-embed > button:before { content: "\e892"; } .h5p-actions .h5p-link { float: right; margin-right: 0; font-size: 2.0em; line-height: 23px; position: relative; color: #6a6a6a; text-decoration: none; outline: none; } .h5p-actions .h5p-link:before { font-family: 'H5P'; content: "\e88e"; vertical-align: bottom; } .h5p-actions > li { margin: 0; list-style: none; } .h5p-popup-dialog { position: absolute; top: 0; left: 0; width: 100%; min-height: 100%; z-index: 100; padding: 2em; box-sizing: border-box; -moz-box-sizing: border-box; opacity: 0; -webkit-transition: opacity 0.2s; -moz-transition: opacity 0.2s; -o-transition: opacity 0.2s; transition: opacity 0.2s; background:#000; background:rgba(0,0,0,0.75); } .h5p-popup-dialog.h5p-open { opacity: 1; } .h5p-popup-dialog .h5p-inner { box-sizing: border-box; -moz-box-sizing: border-box; background: #fff; height: 100%; max-height: 100%; position: relative; } .h5p-popup-dialog .h5p-inner > h2 { position: absolute; box-sizing: border-box; -moz-box-sizing: border-box; width: 100%; margin: 0; background: #eee; display: block; color: #656565; font-size: 1.25em; padding: 0.325em 0.5em 0.25em; line-height: 1.25em; border-bottom: 1px solid #ccc; z-index: 2; } .h5p-popup-dialog .h5p-inner > h2 > a { font-size: 12px; margin-left: 1em; } .h5p-embed-dialog .h5p-inner, .h5p-reuse-dialog .h5p-inner, .h5p-content-user-data-reset-dialog .h5p-inner { min-width: 316px; max-width: 400px; left: 50%; top: 50%; transform: translateX(-50%); } .h5p-embed-dialog .h5p-embed-code-container, .h5p-embed-size { resize: none; outline: none; width: 100%; padding: 0.375em 0.5em 0.25em; margin: 0; overflow: hidden; border: 1px solid #ccc; box-shadow: 0 1px 2px 0 #d0d0d0 inset; font-size: 0.875em; letter-spacing: 0.065em; font-family: sans-serif; white-space: pre; line-height: 1.5em; height: 2.0714em; background: #f5f5f5; box-sizing: border-box; -moz-box-sizing: border-box; } .h5p-embed-dialog .h5p-embed-code-container:focus { height: 5em; } .h5p-embed-size { width: 3.5em; text-align: right; margin: 0.5em 0; line-height: 2em; } .h5p-popup-dialog .h5p-scroll-content { border-top: 2.25em solid transparent; padding: 1em; box-sizing: border-box; -moz-box-sizing: border-box; color: #555555; z-index: 1; } .h5p-popup-dialog.h5p-open .h5p-scroll-content { overflow: auto; overflow-x: hidden; overflow-y: auto; height: 100%; } .h5p-popup-dialog .h5p-scroll-content::-webkit-scrollbar { width: 8px; } .h5p-popup-dialog .h5p-scroll-content::-webkit-scrollbar-track { background: #e0e0e0; } .h5p-popup-dialog .h5p-scroll-content::-webkit-scrollbar-thumb { box-shadow: 0 0 10px #000 inset; border-radius: 4px; } .h5p-popup-dialog .h5p-close { cursor: pointer; font-size: 2em; position: absolute; right: 0; top: 0; width: 1.125em; height: 1.125em; line-height: 1.125em; color: #656565; cursor: pointer; text-indent: -0.065em; z-index: 3 } .h5p-popup-dialog .h5p-close:after { font-family: 'H5P'; content: "\e894"; } .h5p-popup-dialog .h5p-close:hover:after, .h5p-popup-dialog .h5p-close:focus:after { color: #454545; } .h5p-popup-dialog .h5p-close:active:after { color: #252525; } .h5p-poopup-dialog h2 { margin: 0.25em 0 0.5em; } .h5p-popup-dialog h3 { margin: 0.75em 0 0.25em; } .h5p-popup-dialog dl { margin: 0.25em 0 0.75em; } .h5p-popup-dialog dt { float: left; margin: 0 0.75em 0 0; } .h5p-popup-dialog dt:after { content: ':'; } .h5p-popup-dialog dd { margin: 0; } .h5p-expander { cursor: pointer; font-size: 1.125em; margin: 0.5em 0 0; display: inline-block; } .h5p-expander:before { content: "+"; width: 1em; display: inline-block; font-weight: bold; } .h5p-expander.h5p-open:before { content: "-"; text-indent: 0.125em; } .h5p-expander:hover, .h5p-expander:focus { color: #303030; } .h5p-expander:active { color: #202020; } .h5p-expander-content { display: none; } .h5p-expander-content p { margin: 0.5em 0; } .h5p-content-copyrights { border-left: 0.25em solid #d0d0d0; margin-left: 0.25em; padding-left: 0.25em; } .h5p-throbber { background: url('../images/throbber.gif?ver=1.2.1') 10px center no-repeat; padding-left: 38px; min-height: 30px; line-height: 30px; } .h5p-dialog-ok-button { cursor: default; float: right; outline: none; border: 2px solid #ccc; padding: 0.25em 0.75em 0.125em; background: #eee; } .h5p-dialog-ok-button:hover, .h5p-dialog-ok-button:focus { background: #fafafa; } .h5p-dialog-ok-button:active { background: #eeffee; } .h5p-big-button { line-height: 1.25; display: block; position: relative; cursor: pointer; width: 100%; padding: 1em 1em 1em 3.75em; text-align: left; border: 1px solid #dedede; background: linear-gradient(#ffffff, #f1f1f2); border-radius: 0.25em; } .h5p-big-button:before { font-family: 'h5p'; content: "\e893"; line-height: 1; font-size: 3em; color: #2747f7; position: absolute; left: 0.125em; top: 0.125em; } .h5p-copy-button:before { content: "\e905"; } .h5p-big-button:hover { border: 1px solid #2747f7; background: #eff1fe; } .h5p-big-button:active { border: 1px solid #dedede; background: #dfe4fe; } .h5p-button-title { color: #2747f7; font-size: 15px; font-weight: bold; margin-bottom: 0.5em; } .h5p-button-description { color: #757575; } .h5p-horizontal-line-text { border-top: 1px solid #dadada; line-height: 1; color: #474747; text-align: center; position: relative; margin: 1.25em 0; } .h5p-horizontal-line-text > span { background: white; padding: 0.5em; position: absolute; top: -1em; left: 50%; transform: translateX(-50%); } .h5p-toast { font-size: 0.75em; background-color: rgba(0, 0, 0, 0.9); color: #fff; z-index: 110; position: absolute; padding: 0 0.5em; line-height: 2; border-radius: 4px; white-space: nowrap; pointer-events: none; top: 0; opacity: 1; visibility: visible; transition: opacity 1s; } .h5p-toast-disabled { opacity: 0; visibility: hidden; } .h5p-content code, .h5peditor code { color: #3d3d3d; background: #e0e0e0; border-radius: 2px; padding: 0 5px; } .h5p-content pre > code, .h5peditor pre > code { background-color: #fafafa; padding: 5px; display: block; line-height: normal; border: 1px solid #c7c7c7; border-left-width: 4px; max-width: 100%; white-space: pre; overflow: auto; } /* This is loaded as part of Core and not Editor since this needs to be outside the editor iframe */ .h5peditor-semi-fullscreen { width: 100%; height: 100%; position: fixed; top: 0; left: 0; right: 0; bottom: 0; z-index: 101; } iframe.h5peditor-semi-fullscreen { background: #fff; z-index: 100001; } .h5p-content.using-mouse *:not(textarea):focus { outline: none !important; } .h5p-content-hub-button:before { font-family: "h5p"; margin-right: 0.5em; font-size: 0.7em; line-height: 1; } .h5p-content-hub-button.unpublish:before { content: "\e916"; } .h5p-content-hub-button.waiting:before, .h5p-content-hub-button.sync:before { content: "\e917"; } .h5p-content-hub-button.waiting:before { display: inline-block; animation: rotate 2s linear infinite; } @keyframes rotate { to { transform: rotate(360deg); } } PK*\9|iEE.h5plib/v127/joubel/core/styles/h5p-tooltip.cssnu[.h5p-tooltip { --translateX: -50%; --translateY: 0; display: none; position: absolute; bottom: 100%; left: 50%; transform: translateX(var(--translateX)) translateY(var(--translateY)); z-index: 4; font-size: 0.9rem; line-height: 1.5rem; padding: 0 0.5rem; white-space: nowrap; background: #000; color: #FFF; cursor: default; /* To hide the position adjustments and to get a bit more pleasent popup effect */ -webkit-animation: 800ms ease 0s normal forwards 1 fadein; animation: 800ms ease 0s normal forwards 1 fadein; } @keyframes fadein{ 0% { opacity: 0; } 80% { opacity: 0; } 100% { opacity: 1; } } @-webkit-keyframes fadein{ 0% { opacity: 0; } 80% { opacity: 0; } 100% { opacity: 1; } } .h5p-tooltip-bottom { top: 100%; bottom: auto; } .h5p-tooltip-left { --translateY: -50%; --translateX: 0; top: 50%; bottom: auto; left: auto; right: 100%; } .h5p-tooltip-right { --translateY: -50%; --translateX: 0; top: 50%; bottom: auto; left: 100%; right: auto; } .h5p-tooltip-visible { display: block; } PK*\"",h5plib/v127/joubel/core/styles/h5p-table.cssnu[/* Table styling for content types to imitate ckeditor 5 */ .h5p-iframe { /* The figure around the table */ figure.table { display: table; table-layout: fixed; margin: 0 auto; padding: 0; float: left; /* The actual table */ table { border-collapse: collapse; height: 100%; width: 100%; border-spacing: 0; border-width: 1px; border-color: #494949; td, th { padding: 1px; border-color: #494949; border-bottom-style: solid; } td { border-width: 0.083em; } th { text-align: left; border-width: .167em; } tr:last-child > td { border-bottom-style: none; } } figcaption { background-color: transparent; caption-side: top; color: #333; display: table-caption; font-size: .75em; outline-offset: -1px; padding: .6em; text-align: center; word-break: break-word; } } .table-overflow-protection { clear: both; } } PK*\2h5plib/v127/joubel/core/styles/h5p-hub-sharing.cssnu[.h5p-hub-publish button,.h5p-hub-registration button{font-family:"Open Sans", sans-serif;font-size:0.75em;background:transparent;padding:0.75em 2em;color:#757575;border-radius:3em;border:1px solid #d6d6d6;cursor:pointer;font-weight:bold}.h5p-hub-publish button:before,.h5p-hub-registration button:before{font-weight:normal}.h5p-hub-publish button:hover,.h5p-hub-registration button:hover{color:#5f5f5f;border-color:#5f5f5f}.h5p-hub-publish button.h5p-hub-contained.h5p-hub-green,.h5p-hub-registration button.h5p-hub-contained.h5p-hub-green{background-color:#186df7;color:#fff;border-color:#186df7}.h5p-hub-publish button.h5p-hub-contained.h5p-hub-green:hover,.h5p-hub-registration button.h5p-hub-contained.h5p-hub-green:hover{background-color:#2e46a4;border-color:#2e46a4}.h5p-hub-publish button.h5p-hub-outlined.h5p-hub-green,.h5p-hub-registration button.h5p-hub-outlined.h5p-hub-green{border-width:0.125em;background-color:white;border-color:#186df7;color:#186df7}.h5p-hub-publish button.h5p-hub-outlined.h5p-hub-green:hover,.h5p-hub-registration button.h5p-hub-outlined.h5p-hub-green:hover{background-color:#186df7;border-color:#186df7;color:#ffffff}.h5p-hub-publish button.h5p-hub-outlined.h5p-hub-green[disabled],.h5p-hub-registration button.h5p-hub-outlined.h5p-hub-green[disabled]{color:#aac3ec;border-color:#aac3ec;background-color:white;pointer-events:none}.h5p-hub-publish .h5p-hub-navigation button{padding:0.833em;max-width:10.5em} .h5p-hub-publish .h5p-hub-stepper{display:flex;width:100%;max-width:40em;align-items:center;flex-direction:row;margin:2em auto;padding:0 2em;box-sizing:border-box}.h5p-hub-publish .h5p-hub-step-connector{flex-grow:1;margin-left:-2em;margin-right:-2em;position:relative;top:-0.6em}.h5p-hub-publish .h5p-hub-step-connector-line{display:block;border-top-style:solid;border-top-width:1px;border-color:#d5d5d7} .h5p-hub-publish .h5p-hub-step{text-align:center;font-weight:bold}.h5p-hub-publish .h5p-hub-step .h5p-hub-step-icon{color:#303030;border-radius:50%;border:0.462em solid #e1e1e1;width:3.2em;height:3.2em;line-height:2.276;display:inline-block;z-index:1;position:relative;background:#fff;box-sizing:border-box}.h5p-hub-publish .h5p-hub-step .h5p-hub-step-icon .h5p-hub-icon-check{line-height:2.276}.h5p-hub-publish .h5p-hub-step .h5p-hub-step-label{color:#757575;margin-top:0.5em;min-width:8em}.h5p-hub-publish .h5p-hub-step.h5p-hub-active{color:#20d2b2}.h5p-hub-publish .h5p-hub-step.h5p-hub-active .h5p-hub-step-icon{border-color:#1886f7;color:#186df7}.h5p-hub-publish .h5p-hub-step.h5p-hub-completed .h5p-hub-step-icon{background:#186df7;border-color:#609bff;color:#fff} .h5p-hub-publish .h5p-hub-form-element,.h5p-hub-registration .h5p-hub-form-element{font-family:Nunito, sans-serif;font-size:16px;padding:1em 0}.h5p-hub-publish .h5p-hub-form-element label,.h5p-hub-registration .h5p-hub-form-element label{display:block;margin-bottom:0.4em;font-weight:bold}.h5p-hub-publish .h5p-hub-form-element.h5p-hub-mandatory label:after,.h5p-hub-registration .h5p-hub-form-element.h5p-hub-mandatory label:after{content:'*';color:#d11e15;position:relative;top:-0.2em}.h5p-hub-publish .h5p-hub-form-element input,.h5p-hub-registration .h5p-hub-form-element input{border-radius:0.208em;width:100%;box-sizing:border-box;line-height:normal}.h5p-hub-publish .h5p-hub-form-element input::placeholder,.h5p-hub-registration .h5p-hub-form-element input::placeholder{font-style:italic}.h5p-hub-publish .h5p-hub-form-element .h5p-hub-description,.h5p-hub-registration .h5p-hub-form-element .h5p-hub-description{font-size:0.833em;color:#707475;margin:0 0 1em 0}.h5p-hub-publish .h5p-hub-form-element textarea,.h5p-hub-registration .h5p-hub-form-element textarea{resize:none;width:100%;border-radius:0.208em;box-sizing:border-box;line-height:1.25em}.h5p-hub-publish .h5p-hub-form-element textarea::-webkit-scrollbar,.h5p-hub-registration .h5p-hub-form-element textarea::-webkit-scrollbar{background-color:rgba(105,117,133,0.25);width:0.333em;border-radius:5.45256em}.h5p-hub-publish .h5p-hub-form-element textarea::-webkit-scrollbar-thumb,.h5p-hub-registration .h5p-hub-form-element textarea::-webkit-scrollbar-thumb{background-color:#697585;background-size:24px 100%;border-radius:5.45256em}.h5p-hub-publish .h5p-hub-form-element textarea::placeholder,.h5p-hub-registration .h5p-hub-form-element textarea::placeholder{font-style:italic}.h5p-hub-publish .h5p-hub-form-element .h5p-hub-link-button,.h5p-hub-registration .h5p-hub-form-element .h5p-hub-link-button{border:none;text-decoration:underline;text-align:right;align-self:flex-start;color:#186df7;font-size:.917em;font-weight:normal;padding:0}.h5p-hub-publish .h5p-hub-form-element .h5p-hub-details-row,.h5p-hub-registration .h5p-hub-form-element .h5p-hub-details-row{display:flex;align-content:center;align-items:center;justify-content:space-between}.h5p-hub-publish .h5p-hub-form-element textarea,.h5p-hub-publish .h5p-hub-form-element input,.h5p-hub-publish .h5p-hub-form-element select,.h5p-hub-registration .h5p-hub-form-element textarea,.h5p-hub-registration .h5p-hub-form-element input,.h5p-hub-registration .h5p-hub-form-element select{padding:.958em;border:2px solid #e2e5ee;box-shadow:none;color:#3c4859;font-family:Nunito, sans-serif}.h5p-hub-publish .h5p-hub-form-element textarea:focus,.h5p-hub-publish .h5p-hub-form-element input:focus,.h5p-hub-publish .h5p-hub-form-element select:focus,.h5p-hub-registration .h5p-hub-form-element textarea:focus,.h5p-hub-registration .h5p-hub-form-element input:focus,.h5p-hub-registration .h5p-hub-form-element select:focus{border-color:#98cbe8;box-shadow:inset 0 1px 1px rgba(0,0,0,0.075),0 0 8px rgba(152,203,232,0.6);outline:none}.h5p-hub-publish .h5p-hub-step-content>.h5p-hub-form-element:first-child,.h5p-hub-registration .h5p-hub-step-content>.h5p-hub-form-element:first-child{padding-top:0}.h5p-hub-publish .h5p-hub-step-content>.h5p-hub-form-element:last-child,.h5p-hub-registration .h5p-hub-step-content>.h5p-hub-form-element:last-child{padding-bottom:0} .h5p-hub-publish select{font-size:0.917em;border-radius:0.208em;padding:0.833em 2.334em 0.833em 0.833em;color:#313131;background-color:#ffffff;font-family:"Open Sans", sans-serif;border:1px solid #bebdcd;width:100%;-webkit-appearance:none;-moz-appearance:none;line-height:1.5}.h5p-hub-publish select:disabled{background-color:#ededed}.h5p-hub-publish select:disabled::before{content:"-"}.h5p-hub-publish select::-ms-expand{display:none}.h5p-hub-publish div.h5p-hub-icon-arrow-down{position:relative;line-height:1.1em;pointer-events:none}.h5p-hub-publish div.h5p-hub-icon-arrow-down:before{content:"\e925";transform:rotate(90deg);position:absolute;right:1.5em;top:1.9em;font-size:0.6em} .h5p-hub-publish .h5p-hub-modal-content{z-index:2;background-color:#ffffff;opacity:1;position:relative;margin:2em 3em;border-radius:0.167em;max-height:calc(100% - 4em);overflow:auto}.h5p-hub-publish .h5p-hub-modal-overlay{position:absolute;top:0;left:0px;right:0px;bottom:0px;background-color:rgba(0,0,0,0.7);z-index:2} .h5p-hub-hidden-read{width:1px;height:1px;top:-1px;position:absolute;text-indent:1px;overflow:hidden} .h5p-hub-publish .h5p-hub-tip{position:relative;display:block}.h5p-hub-publish .h5p-hub-tip.h5p-hub-positioned{position:unset}.h5p-hub-publish .h5p-hub-tip.h5p-hub-bottom .h5p-hub-tip-wrapper{top:115%}.h5p-hub-publish .h5p-hub-tip.h5p-hub-bottom .h5p-hub-tip-wrapper .h5p-hub-arrow:after{top:-0.75em;border-bottom-color:black;border-top-color:transparent}.h5p-hub-publish .h5p-hub-tip.h5p-hub-left-aligned .h5p-hub-tip-wrapper{transform:none;top:-0.85em;right:0}.h5p-hub-publish .h5p-hub-tip.h5p-hub-left-aligned .h5p-hub-tip-wrapper .h5p-hub-tip{white-space:normal}.h5p-hub-publish .h5p-hub-tip.h5p-hub-left-aligned .h5p-hub-tip-wrapper .h5p-hub-arrow:after{left:auto;transform:none;right:1.3em}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper{display:none;position:absolute;top:-3.5em;font-size:14px;font-weight:400;color:white;border-radius:0.4em;z-index:2}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-enter-done,.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-enter,.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-enter-active,.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-exit,.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-exit-active{display:block}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-enter{transform:translate(0, 30%);opacity:0}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-enter-active{transform:translate(0, 0);opacity:1;transition:opacity 0.2s, transform 0.2s}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-exit{transform:translate(0, 0);opacity:1}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper.h5p-hub-tip-wrapper-exit-active{transform:translate(0, 30%);opacity:0;transition:opacity 0.2s, transform 0.2s}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper .h5p-hub-tip{white-space:nowrap;background:black;padding:0.3em 1em;border-radius:0.4em}.h5p-hub-publish .h5p-hub-tip .h5p-hub-tip-wrapper .h5p-hub-arrow:after{content:" ";position:absolute;left:50%;transform:translateX(-50%);pointer-events:none;border:0.4em solid transparent;border-top-color:black} .h5p-hub-publish .h5p-hub-accordion-heading{display:flex;align-items:center}.h5p-hub-publish .h5p-hub-accordion-heading .h5p-hub-icon-dropdown{font-size:0.4em;color:#616161;display:inline-block;left:0;display:flex;padding:0.2em}.h5p-hub-publish .h5p-hub-accordion-heading .h5p-hub-icon-dropdown.h5p-hub-open{transform:rotate(90deg)}.h5p-hub-publish .h5p-hub-accordion-button{border:none;position:relative;padding:0.2em;width:100%;justify-self:start;display:flex}.h5p-hub-publish .h5p-hub-accordion-button .h5p-hub-accordion-header{border:none;text-align:left;color:#616161}.h5p-hub-publish .h5p-hub-panel-body{font-size:0.833em;margin:0.8em;margin-bottom:0;color:#707475;overflow:hidden} .h5p-hub-publish .h5p-hub-dialog-header{padding:1.708em 2.292em;border-bottom:1px solid #d5d5d7}.h5p-hub-publish .h5p-hub-dialog-header .h5p-hub-dialog-description{font-size:0.833em;color:#707475}.h5p-hub-publish .h5p-hub-dialog-content{padding:1.708em 2.292em}.h5p-hub-publish .h5p-hub-dialog-title{display:flex;justify-content:space-between}.h5p-hub-publish .h5p-hub-dialog-title span{font-size:1.458em;color:#1a1a1a;margin-bottom:0.2em}.h5p-hub-publish .h5p-hub-dialog-title button{max-height:2.77em} .h5p-hub-publish .h5p-hub-chips-list{display:flex;list-style:none;padding:0;flex-wrap:wrap;margin:0 0 0.5em}.h5p-hub-publish .h5p-hub-chips-list li{margin:0}.h5p-hub-publish .h5p-hub-chips-list li button{border-radius:0.125em;margin-right:0.5em;margin-top:0.5em;font-style:italic;color:#000000;display:flex;align-items:center;outline:none;border-color:#e2e5ee;padding:0.5em;font-size:0.85em}.h5p-hub-publish .h5p-hub-chips-list li button .h5p-hub-icon-close{font-size:0.8em;margin-left:2em}.h5p-hub-publish .h5p-hub-chips-list li button:focus{background-color:#e8e8e8;border-color:#dddee2}.h5p-hub-publish .h5p-hub-chips-list li button:hover{background-color:#f5f5f5;border-color:#dddee2} .h5p-hub-publish .h5p-hub-keywords-input-wrapper{display:flex;align-items:center;border-radius:2em}.h5p-hub-publish .h5p-hub-keywords-input-wrapper .h5p-hub-add-button{position:absolute;right:4.5em;border-radius:1.5em;padding:0.5em 1em;margin-right:0.5em}.h5p-hub-publish .h5p-hub-keywords-input-wrapper .h5p-hub-add-button:focus{border-color:#3ba0f2}.h5p-hub-publish .h5p-hub-keywords-input-wrapper .h5p-hub-add-button.disabled{cursor:default;color:#d6d6d6}.h5p-hub-publish .h5p-hub-keywords-input-wrapper .h5p-hub-add-button.disabled:hover{background-color:transparent}.h5p-hub-publish .h5p-hub-tip-keywords{top:2.5em} .h5p-hub-publish .h5p-hub-image-preview,.h5p-hub-registration .h5p-hub-image-preview{width:4em;height:3em;display:inline-block;background-position:center;background-size:contain;background-repeat:no-repeat;background-color:#d0d0d1} .h5p-hub-publish .h5p-hub-image-upload-container,.h5p-hub-registration .h5p-hub-image-upload-container{width:4em;height:3em;margin-right:1em;position:relative;display:flex}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close{cursor:pointer;font-size:1em;border:none;outline:none;position:absolute;right:0;padding:0}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close::before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close::before{font-size:0.6em;padding:0.5em;line-height:1.1;color:#fff;background:#000;position:absolute;z-index:1;display:inline-block;right:-1.2em;top:-1.2em;border:3px solid #fff;border-radius:50%;cursor:pointer;transition:all 0.3s}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close:hover::before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close:hover::before{background:#eee;color:#000}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-icon-close:focus::before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-icon-close:focus::before{outline:#000;outline-style:auto}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload{position:absolute;top:0;left:0;width:100%;height:100%;text-align:center;transition:all 0.3s;border:0.125em dashed #bebdcd;color:#bebdcd}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload input,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload input{position:absolute;left:0;top:0;width:100%;height:100%;cursor:pointer;opacity:0}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload input::-webkit-file-upload-button,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload input::-webkit-file-upload-button{visibility:hidden}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload:hover,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload:hover{color:#777;border-color:#777}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload:before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload:before{content:"+";font-size:2em;display:inline-block;position:relative;top:50%;transform:translateY(-50%)}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected{border-style:solid;border-radius:0.1em}.h5p-hub-publish .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected:before,.h5p-hub-registration .h5p-hub-image-upload-container .h5p-hub-image-upload.h5p-hub-image-selected:before{display:none} .h5p-hub-publish .h5p-hub-optional .h5p-hub-keywords .h5p-hub-form-element label{margin-bottom:0.708em}.h5p-hub-publish .h5p-hub-optional .h5p-hub-form-screenshots{display:flex;flex-wrap:wrap;flex-direction:column}.h5p-hub-publish .h5p-hub-optional .h5p-hub-form-screenshots .h5p-hub-image-upload-container{margin-top:0.4em}.h5p-hub-publish .h5p-hub-optional .h5p-hub-form-screenshots .h5p-hub-row{margin-top:0.5em}.h5p-hub-publish .h5p-hub-optional .h5p-hub-form-screenshots .h5p-hub-row .h5p-hub-form-element{padding:0}.h5p-hub-publish .h5p-hub-optional .h5p-hub-form-screenshots .h5p-hub-alt-text{padding:0.3em}.h5p-hub-publish .h5p-hub-optional .h5p-hub-optional-second-part{display:flex}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-optional .h5p-hub-optional-second-part{flex-wrap:wrap}}.h5p-hub-publish .h5p-hub-optional #h5p-hub-form-long-description{height:10.458em}.h5p-hub-publish .h5p-hub-optional #h5p-hub-form-short-description{height:6.333em} .h5p-hub-publish .h5p-hub-discipline-element,.h5p-hub-registration .h5p-hub-discipline-element{font-size:1.05em;padding:0.5em 0;font-weight:bold;display:flex;cursor:pointer;align-self:start;color:#4d5057;width:100%;position:relative}.h5p-hub-publish .h5p-hub-discipline-element .h5p-hub-checkbox-error-tip,.h5p-hub-registration .h5p-hub-discipline-element .h5p-hub-checkbox-error-tip{top:5em;position:absolute;margin-left:2.5em;z-index:1}.h5p-hub-publish .h5p-hub-discipline-element:last-child .h5p-hub-checkbox-error-tip,.h5p-hub-registration .h5p-hub-discipline-element:last-child .h5p-hub-checkbox-error-tip{top:2.5em}.h5p-hub-publish .h5p-hub-discipline-element:focus,.h5p-hub-registration .h5p-hub-discipline-element:focus{box-shadow:0 0 0.4em 0.01em RGBA(26, 147, 244, 0.7);outline:none}.h5p-hub-publish .h5p-hub-discipline-element.h5p-hub-parent::after,.h5p-hub-registration .h5p-hub-discipline-element.h5p-hub-parent::after{font-family:'h5p';content:'\e58e';transform:rotate(90deg);font-style:normal;font-size:1.1em;display:inline-block;align-self:center}.h5p-hub-publish .h5p-hub-discipline-element .h5p-hub-content,.h5p-hub-registration .h5p-hub-discipline-element .h5p-hub-content{display:flex;align-items:center;margin-left:0.5em}.h5p-hub-publish .h5p-hub-discipline-element .h5p-hub-bold,.h5p-hub-registration .h5p-hub-discipline-element .h5p-hub-bold{font-weight:bold}.h5p-hub-publish .h5p-hub-discipline-element .h5p-hub-non-bold,.h5p-hub-registration .h5p-hub-discipline-element .h5p-hub-non-bold{font-weight:normal} .h5p-hub-publish .h5p-hub-checkbox-list{list-style:none;padding:0;background-color:#ffffff}.h5p-hub-publish .h5p-hub-checkbox-list.h5p-hub-animate-in-right{animation:move-from-right 0.35s}.h5p-hub-publish .h5p-hub-checkbox-list.h5p-hub-animate-in-left{animation:move-from-left 0.35s}@keyframes move-from-right{0%{opacity:0;transform:translateX(30%)}30%{opacity:0}100%{opacity:1;transform:translateX(0)}}@keyframes move-from-left{0%{opacity:0;transform:translateX(-10%)}30%{opacity:0}100%{opacity:1;transform:translateX(0)}} .h5p-hub-publish .h5p-hub-bottom-line{border-bottom:2px solid #697585}.h5p-hub-publish .h5p-hub-category-header{background-color:#f2f2f2;color:#313131;font-style:italic;padding:0 0 0 0.9em;font-size:0.81788em} .h5p-hub-publish .h5p-hub-search-button{width:100%;position:relative}.h5p-hub-publish .h5p-hub-search-button .h5p-hub-search-field{position:relative;display:flex;align-items:center;justify-content:space-between}.h5p-hub-publish .h5p-hub-search-button .h5p-hub-search-field::before{content:"\e926";font-family:"h5p";font-style:normal;font-size:1em;margin-left:1.25em;color:#b7b8ba;position:absolute}.h5p-hub-publish .h5p-hub-search-button .h5p-hub-search-field .h5p-hub-icon-arrow{margin:1em;font-size:1.30353em;cursor:pointer;color:#000000;transform:rotate(90deg)}.h5p-hub-publish .h5p-hub-search-button .h5p-hub-search-field .h5p-hub-icon-arrow::before{content:"\e925";font-family:"h5p";font-style:normal;font-size:0.6em}.h5p-hub-publish #h5p-hub-filter-search-bar{border:none;padding:0.833em;font-style:italic;width:100%;box-sizing:border-box;font-size:1.15em;padding-left:3.044em}.h5p-hub-publish #h5p-hub-filter-search-bar::placeholder{color:#b7b8ba}.h5p-hub-publish #h5p-hub-filter-search-bar:focus{border-color:#3ba0f2;background-color:#fff;outline:none} .h5p-hub-publish .h5p-hub-search-filter{position:relative;border-radius:0.208em;font-size:0.833em;border:2px solid #e2e5ee}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-clear-button{background:none;position:absolute;padding:1.6em;right:3.5em;color:#757575;border:none;top:50%;transform:translateY(-50%)}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-clear-button::before{content:"\e93a";font-family:"h5p";font-style:normal;font-size:1em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-navigate-parent{font-size:1.25em;padding:0.3534em;display:flex;font-weight:bold;font-family:"Open Sans", sans-serif;border-top:1px solid #e6e6e8;align-items:center;border-bottom:solid 1px #e6e6e8}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-navigate-parent button{background-color:#ffffff;position:relative;font-style:normal;font-size:0.8em;align-self:center;border:none;padding:0.75em;margin-right:1em;border-radius:50%;width:2.75em;height:2.75em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-navigate-parent button::before{content:"\e937";font-family:"h5p";transform:rotate(180deg);font-weight:normal;display:inline-block}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-navigate-parent button:hover{background-color:#dadada;cursor:pointer}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list{overflow:hidden;overflow-y:scroll;max-height:25em;margin:0}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li{border-bottom:1px solid #e6e6e8;margin:0}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li:last-child{border-bottom:none}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li:first-child{border-top:1px solid #e6e6e8}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li .h5p-hub-content{padding:0.3em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li .h5p-hub-content .h5p-hub-label-text{margin:0 0.2em 0 1em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li .h5p-hub-content button{border-radius:1.5em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li:focus{border-color:#3ba0f2;background-color:#fff;outline:none;box-shadow:none}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li:hover{background-color:#f2f2f2}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li.h5p-hub-highlighted{outline:1px solid #3ba0f2;outline-offset:-1px;background-color:#fff;box-shadow:none}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list li:hover{background-color:rgba(230,230,232,0.25)}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list::-webkit-scrollbar{background-color:rgba(105,117,133,0.25);width:0.54525em;border-radius:5.45256em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-checkbox-list::-webkit-scrollbar-thumb{background-color:#697585;background-size:24px 100%;border-radius:5.45256em}.h5p-hub-publish .h5p-hub-search-filter .h5p-hub-publish .h5p-hub-form-element input{border:none} .h5p-hub-publish .h5p-hub-message,.h5p-hub-registration .h5p-hub-message{font-size:1em;border-left:0.3em solid;padding:1em;margin:0.5em 0}.h5p-hub-publish .h5p-hub-message.h5p-hub-warning,.h5p-hub-registration .h5p-hub-message.h5p-hub-warning{border-color:#fdcc31;background:#fff8e0}.h5p-hub-publish .h5p-hub-message.h5p-hub-error,.h5p-hub-registration .h5p-hub-message.h5p-hub-error{border-color:#c1494b;background-color:#ece0e0;color:#c1494b}.h5p-hub-publish .h5p-hub-message.h5p-hub-success,.h5p-hub-registration .h5p-hub-message.h5p-hub-success{border-color:#03a953;background-color:#d9eae2} .h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-review-header{margin-bottom:1em;color:#363636}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review dl{border-top:1px solid #d5d5d5;margin:1.25em 0 0 0}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition{border-bottom:1px solid #d5d5d5;display:flex;border-bottom-color:#e2e5ee}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition dt{width:25%;min-width:25%;background:#f4f5f9;display:inline-block;padding:0.5em 0 0.5em 1em}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition dd{color:#707475;display:inline-block;margin:0;padding:0.5em 0 0.5em 1em}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition .h5p-hub-img-alt{display:flex;align-items:center}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition .h5p-hub-screenshots{margin-bottom:0.2em}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition .h5p-hub-screenshots:last-child{margin-bottom:0}.h5p-hub-publish .h5p-hub-step-content.h5p-hub-review .h5p-hub-definition .h5p-hub-screenshots .h5p-hub-image-preview{font-size:0.75em;margin-right:0.5em} .h5p-hub-publish .h5p-hub-success-page{text-align:center}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-step-icon-success{font-size:0.75em;border-radius:50%;border:0.462em solid #609bff;width:3.2em;height:3.2em;line-height:2.276;display:inline-block;box-sizing:border-box;margin-bottom:0.667em;background:#186df7;color:#fff}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-submitted-text{margin-bottom:2.167em;font-size:0.75em;color:#186df7}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-content-type{letter-spacing:0.146em;color:#303438;margin-bottom:0.7em}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-title{font-size:1.75em;margin-bottom:0.5em;color:#1a1a1a}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-title.h5p-hub-is-edit{margin-bottom:1.75em}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-now-submitted-text{font-size:1.458em;margin-bottom:1.75em;color:#1a1a1a}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-now-submitted-text.h5p-hub-is-edit{margin-bottom:.5em}.h5p-hub-publish .h5p-hub-success-page .h5p-hub-content-available{font-size:0.833em;color:#707475} .h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal{margin:2em auto;width:30em;max-width:90%}.h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal .h5p-hub-dialog-header{padding:1.708em 2.292em;border-bottom:1px solid #d5d5d7}.h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal .h5p-hub-dialog-header .h5p-hub-dialog-title{display:flex;justify-content:space-between}.h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal .h5p-hub-dialog-header .h5p-hub-dialog-title span{font-size:1.458em;color:#1a1a1a;margin-bottom:0.2em}.h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal .h5p-hub-dialog-content .h5p-hub-dialog-description{font-size:0.833em;color:#707475}.h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal .h5p-hub-dialog-content .h5p-hub-button-group{display:flex;justify-content:flex-end;margin-top:2em}.h5p-hub-publish .h5p-hub-cancel-publish-confirmation-modal .h5p-hub-dialog-content .h5p-hub-button-group button{margin-left:1em} /*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */ /* Document ========================================================================== */ /** * 1. Correct the line height in all browsers. * 2. Prevent adjustments of font size after orientation changes in iOS. */ html { line-height: 1.15; /* 1 */ -webkit-text-size-adjust: 100%; /* 2 */ } /* Sections ========================================================================== */ /** * Remove the margin in all browsers. */ body { margin: 0; } /** * Render the `main` element consistently in IE. */ main { display: block; } /** * Correct the font size and margin on `h1` elements within `section` and * `article` contexts in Chrome, Firefox, and Safari. */ h1 { font-size: 2em; margin: 0.67em 0; } /* Grouping content ========================================================================== */ /** * 1. Add the correct box sizing in Firefox. * 2. Show the overflow in Edge and IE. */ hr { box-sizing: content-box; /* 1 */ height: 0; /* 1 */ overflow: visible; /* 2 */ } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ pre { font-family: monospace, monospace; /* 1 */ font-size: 1em; /* 2 */ } /* Text-level semantics ========================================================================== */ /** * Remove the gray background on active links in IE 10. */ a { background-color: transparent; } /** * 1. Remove the bottom border in Chrome 57- * 2. Add the correct text decoration in Chrome, Edge, IE, Opera, and Safari. */ abbr[title] { border-bottom: none; /* 1 */ text-decoration: underline; /* 2 */ text-decoration: underline dotted; /* 2 */ } /** * Add the correct font weight in Chrome, Edge, and Safari. */ b, strong { font-weight: bolder; } /** * 1. Correct the inheritance and scaling of font size in all browsers. * 2. Correct the odd `em` font sizing in all browsers. */ code, kbd, samp { font-family: monospace, monospace; /* 1 */ font-size: 1em; /* 2 */ } /** * Add the correct font size in all browsers. */ small { font-size: 80%; } /** * Prevent `sub` and `sup` elements from affecting the line height in * all browsers. */ sub, sup { font-size: 75%; line-height: 0; position: relative; vertical-align: baseline; } sub { bottom: -0.25em; } sup { top: -0.5em; } /* Embedded content ========================================================================== */ /** * Remove the border on images inside links in IE 10. */ img { border-style: none; } /* Forms ========================================================================== */ /** * 1. Change the font styles in all browsers. * 2. Remove the margin in Firefox and Safari. */ button, input, optgroup, select, textarea { font-family: inherit; /* 1 */ font-size: 100%; /* 1 */ line-height: 1.15; /* 1 */ margin: 0; /* 2 */ } /** * Show the overflow in IE. * 1. Show the overflow in Edge. */ button, input { /* 1 */ overflow: visible; } /** * Remove the inheritance of text transform in Edge, Firefox, and IE. * 1. Remove the inheritance of text transform in Firefox. */ button, select { /* 1 */ text-transform: none; } /** * Correct the inability to style clickable types in iOS and Safari. */ button, [type="button"], [type="reset"], [type="submit"] { -webkit-appearance: button; } /** * Remove the inner border and padding in Firefox. */ button::-moz-focus-inner, [type="button"]::-moz-focus-inner, [type="reset"]::-moz-focus-inner, [type="submit"]::-moz-focus-inner { border-style: none; padding: 0; } /** * Restore the focus styles unset by the previous rule. */ button:-moz-focusring, [type="button"]:-moz-focusring, [type="reset"]:-moz-focusring, [type="submit"]:-moz-focusring { outline: 1px dotted ButtonText; } /** * Correct the padding in Firefox. */ fieldset { padding: 0.35em 0.75em 0.625em; } /** * 1. Correct the text wrapping in Edge and IE. * 2. Correct the color inheritance from `fieldset` elements in IE. * 3. Remove the padding so developers are not caught out when they zero out * `fieldset` elements in all browsers. */ legend { box-sizing: border-box; /* 1 */ color: inherit; /* 2 */ display: table; /* 1 */ max-width: 100%; /* 1 */ padding: 0; /* 3 */ white-space: normal; /* 1 */ } /** * Add the correct vertical alignment in Chrome, Firefox, and Opera. */ progress { vertical-align: baseline; } /** * Remove the default vertical scrollbar in IE 10+. */ textarea { overflow: auto; } /** * 1. Add the correct box sizing in IE 10. * 2. Remove the padding in IE 10. */ [type="checkbox"], [type="radio"] { box-sizing: border-box; /* 1 */ padding: 0; /* 2 */ } /** * Correct the cursor style of increment and decrement buttons in Chrome. */ [type="number"]::-webkit-inner-spin-button, [type="number"]::-webkit-outer-spin-button { height: auto; } /** * 1. Correct the odd appearance in Chrome and Safari. * 2. Correct the outline style in Safari. */ [type="search"] { -webkit-appearance: textfield; /* 1 */ outline-offset: -2px; /* 2 */ } /** * Remove the inner padding in Chrome and Safari on macOS. */ [type="search"]::-webkit-search-decoration { -webkit-appearance: none; } /** * 1. Correct the inability to style clickable types in iOS and Safari. * 2. Change font properties to `inherit` in Safari. */ ::-webkit-file-upload-button { -webkit-appearance: button; /* 1 */ font: inherit; /* 2 */ } /* Interactive ========================================================================== */ /* * Add the correct display in Edge, IE 10+, and Firefox. */ details { display: block; } /* * Add the correct display in all browsers. */ summary { display: list-item; } /* Misc ========================================================================== */ /** * Add the correct display in IE 10+. */ template { display: none; } /** * Add the correct display in IE 10. */ [hidden] { display: none; } @keyframes spinner{0%{transform:translate3d(-50%, -50%, 0) rotate(0deg)}100%{transform:translate3d(-50%, -50%, 0) rotate(360deg)}}.h5p-hub-publish,.h5p-hub-registration-wrapper{position:relative;margin:2em auto;max-width:1024px;border:1px solid #2c9586;border-radius:0.167em;box-sizing:border-box;box-shadow:0px 0px 20px rgba(0,0,0,0.1);font-family:Nunito, sans-serif;font-size:16px;padding-top:0.25em}.h5p-hub-publish .h5p-hub-header,.h5p-hub-registration-wrapper .h5p-hub-header{padding:1.5em;display:flex;align-items:center;width:100%;box-sizing:border-box;border-bottom:1px solid #d5d5d7;border-bottom-color:#e2e5ee}.h5p-hub-publish .h5p-hub-header .h5p-hub-title,.h5p-hub-registration-wrapper .h5p-hub-header .h5p-hub-title{font-size:1.458em;flex-grow:1;color:black;padding-left:1em}.h5p-hub-publish .h5p-hub-step-panel,.h5p-hub-registration-wrapper .h5p-hub-step-panel{margin:2em;border-radius:0.208em;border:1px solid #e2e5ee}.h5p-hub-publish .h5p-hub-step-title,.h5p-hub-registration-wrapper .h5p-hub-step-title{color:#1a1a1a;font-size:1.250em;font-weight:bold;border-bottom:1px solid #ccc;padding:1.2em 1.8em;line-height:normal;border-bottom-color:#e2e5ee}.h5p-hub-publish .h5p-hub-step-content,.h5p-hub-registration-wrapper .h5p-hub-step-content{padding:2em}.h5p-hub-publish .h5p-hub-footer,.h5p-hub-registration-wrapper .h5p-hub-footer{padding:0 2em 2em;width:100%;box-sizing:border-box;position:relative}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation{display:flex}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation button,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation button{z-index:1}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation button:before,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation button:before{font-family:'h5p';font-size:0.75em;content:"\e91a";transform:rotate(180deg);display:inline-block;margin-right:0.75em;line-height:1;position:relative;top:-0.1em}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation .h5p-hub-back:before,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation .h5p-hub-back:before{transform:rotate(0)}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation #h5p-hub-share-in-process::before,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation #h5p-hub-share-in-process::before{font-family:"h5p";font-size:0.75em;content:"\e928";animation:2s linear infinite spinner;top:0.5em;margin-left:0.55em}.h5p-hub-publish .h5p-hub-footer .h5p-hub-navigation .h5p-hub-next,.h5p-hub-registration-wrapper .h5p-hub-footer .h5p-hub-navigation .h5p-hub-next{margin-left:auto}.h5p-hub-publish .h5p-hub-tip-text-field,.h5p-hub-registration-wrapper .h5p-hub-tip-text-field{top:1.5em}.h5p-hub-publish .h5p-hub-hare-error,.h5p-hub-registration-wrapper .h5p-hub-hare-error{padding:0 2em 2em;text-align:end}.h5p-hub-publish .h5p-hub-bold,.h5p-hub-registration-wrapper .h5p-hub-bold{font-weight:bold}.h5p-hub-publish .h5p-hub-row,.h5p-hub-registration-wrapper .h5p-hub-row{display:flex;flex-wrap:wrap;margin-right:-1em}.h5p-hub-publish .h5p-hub-row .h5p-hub-form-element,.h5p-hub-registration-wrapper .h5p-hub-row .h5p-hub-form-element{flex-basis:100%;flex:1;min-width:17em;align-self:flex-end;border-right:1em solid #ffffff}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-row .h5p-hub-form-element,.h5p-hub-registration-wrapper .h5p-hub-row .h5p-hub-form-element{min-width:calc(100% - 1em)}}.h5p-hub-publish .h5p-hub-columns,.h5p-hub-registration-wrapper .h5p-hub-columns{display:flex;margin-right:-1em}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-columns,.h5p-hub-registration-wrapper .h5p-hub-columns{flex-wrap:wrap}}.h5p-hub-publish .h5p-hub-columns .h5p-hub-column,.h5p-hub-registration-wrapper .h5p-hub-columns .h5p-hub-column{width:50%;border-right:1em solid #ffffff}@media (max-width: 576px){.h5p-hub-publish .h5p-hub-columns .h5p-hub-column,.h5p-hub-registration-wrapper .h5p-hub-columns .h5p-hub-column{width:100%;margin-right:0}}.h5p-hub-publish .h5p-hub-sharing-note,.h5p-hub-registration-wrapper .h5p-hub-sharing-note{text-align:center;color:#707475;width:calc(100% - 4.9em);position:absolute;top:0.65em;box-sizing:border-box;padding:0 9em}.h5p-hub-publish .h5p-hub-sharing-note .h5p-hub-icon-info:before,.h5p-hub-registration-wrapper .h5p-hub-sharing-note .h5p-hub-icon-info:before{font-size:0.5em;display:inline-block;margin-right:1em;background:#d1d7e3;padding:0.4em;border-radius:50%;position:relative;top:-0.25em}.h5p-hub-publish .h5p-hub-sr-only,.h5p-hub-registration-wrapper .h5p-hub-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border:0}.h5p-hub-publish [class^="h5p-hub-icon-"],.h5p-hub-publish [class*=" h5p-hub-icon-"],.h5p-hub-registration-wrapper [class^="h5p-hub-icon-"],.h5p-hub-registration-wrapper [class*=" h5p-hub-icon-"]{font-family:'h5p' !important;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.h5p-hub-publish .h5p-hub-icon-dropdown:before,.h5p-hub-registration-wrapper .h5p-hub-icon-dropdown:before{content:"\e925"}.h5p-hub-publish .h5p-hub-icon-info:before,.h5p-hub-registration-wrapper .h5p-hub-icon-info:before{content:"\e93c"}.h5p-hub-publish .h5p-hub-icon-thick-arrow:before,.h5p-hub-registration-wrapper .h5p-hub-icon-thick-arrow:before{content:"\e91a"}.h5p-hub-publish .h5p-hub-icon-check:before,.h5p-hub-registration-wrapper .h5p-hub-icon-check:before{content:"\e933"}.h5p-hub-publish .h5p-hub-icon-close:before,.h5p-hub-registration-wrapper .h5p-hub-icon-close:before{content:"\e93a"}.h5p-hub-publish .h5p-hub-icon-plus:before,.h5p-hub-registration-wrapper .h5p-hub-icon-plus:before{content:"\e939"}.h5p-hub-publish button,.h5p-hub-registration-wrapper button{font-size:.917em;border-width:.125em;border-radius:.208em;padding:.833em 1.65em;background:#fff;color:#3c4859;font-family:Nunito, sans-serif;outline:none;transition:all 0.1s}.h5p-hub-publish button:hover,.h5p-hub-registration-wrapper button:hover{color:#3c4859;background:#e2e5ee;border-color:#e2e5ee}.h5p-hub-registration-wrapper{border:none}.h5p-hub-publish{border:1px solid #e2e5ee}.h5p-hub-share-error{margin:2em} PK*\:h5plib/v127/joubel/core/styles/h5p-confirmation-dialog.cssnu[.h5p-confirmation-dialog-background { position: fixed; height: 100%; width: 100%; left: 0; top: 0; background: rgba(44, 44, 44, 0.9); opacity: 1; visibility: visible; -webkit-transition: opacity 0.1s, linear 0s, visibility 0s linear 0s; transition: opacity 0.1s linear 0s, visibility 0s linear 0s; z-index: 201; } .h5p-confirmation-dialog-background.hidden { display: none; } .h5p-confirmation-dialog-background.hiding { opacity: 0; visibility: hidden; -webkit-transition: opacity 0.1s, linear 0s, visibility 0s linear 0.1s; transition: opacity 0.1s linear 0s, visibility 0s linear 0.1s; } .h5p-confirmation-dialog-popup:focus { outline: none; } .h5p-confirmation-dialog-popup { position: absolute; display: flex; flex-direction: column; justify-content: center; box-sizing: border-box; max-width: 35em; min-width: 25em; top: 2em; left: 50%; -webkit-transform: translate(-50%, 0%); -ms-transform: translate(-50%, 0%); transform: translate(-50%, 0%); color: #555; box-shadow: 0 0 6px 6px rgba(10,10,10,0.3); -webkit-transition: transform 0.1s ease-in; transition: transform 0.1s ease-in; } .h5p-confirmation-dialog-popup.hidden { -webkit-transform: translate(-50%, 50%); -ms-transform: translate(-50%, 50%); transform: translate(-50%, 50%); } .h5p-confirmation-dialog-header { padding: 1.5em; background: #fff; color: #356593; } .h5p-confirmation-dialog-header-text { font-size: 1.25em; } .h5p-confirmation-dialog-body { background: #fafbfc; border-top: solid 1px #dde0e9; padding: 1.25em 1.5em; } .h5p-confirmation-dialog-text { margin-bottom: 1.5em; } .h5p-confirmation-dialog-buttons { float: right; } button.h5p-confirmation-dialog-exit:visited, button.h5p-confirmation-dialog-exit:link, button.h5p-confirmation-dialog-exit { position: absolute; background: none; border: none; font-size: 2.5em; top: -0.9em; right: -1.15em; color: #fff; cursor: pointer; text-decoration: none; } button.h5p-confirmation-dialog-exit:focus, button.h5p-confirmation-dialog-exit:hover { color: #E4ECF5; } .h5p-confirmation-dialog-exit:before { font-family: "H5P"; content: "\e890"; } .h5p-core-button.h5p-confirmation-dialog-confirm-button { padding-left: 0.75em; margin-bottom: 0; } .h5p-core-button.h5p-confirmation-dialog-confirm-button:before { content: "\e601"; margin-top: -6px; display: inline-block; } .h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-buttons { float: none; text-align: center; } .h5p-confirmation-dialog-popup.offline .count-down { font-family: Arial; margin-top: 0.15em; color: #000; } .h5p-confirmation-dialog-popup.offline .h5p-confirmation-dialog-confirm-button:before { content: "\e90b"; font-weight: normal; vertical-align: text-bottom; } .throbber-wrapper { display: none; position: absolute; height: 100%; width: 100%; top: 0; left: 0; z-index: 1; background: rgba(44, 44, 44, 0.9); } .throbber-wrapper.show { display: block; } .throbber-wrapper .throbber-container { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); } .throbber-wrapper .sending-requests-throbber{ position: absolute; top: 7em; left: 50%; transform: translateX(-50%); } .throbber-wrapper .sending-requests-throbber:before { display: block; font-family: 'H5P'; content: "\e90b"; color: white; font-size: 10em; animation: request-throbber 1.5s infinite linear; } @keyframes request-throbber { from { transform: rotate(0); } to { transform: rotate(359deg); } } PK*\t6h5plib/v127/joubel/core/h5p-file-storage.interface.phpnu[ array( 'type' => 'text', 'maxLength' => 255 ), 'a11yTitle' => array( 'type' => 'text', 'maxLength' => 255, ), 'authors' => array( 'type' => 'json' ), 'changes' => array( 'type' => 'json' ), 'source' => array( 'type' => 'text', 'maxLength' => 255 ), 'license' => array( 'type' => 'text', 'maxLength' => 32 ), 'licenseVersion' => array( 'type' => 'text', 'maxLength' => 10 ), 'licenseExtras' => array( 'type' => 'text', 'maxLength' => 5000 ), 'authorComments' => array( 'type' => 'text', 'maxLength' => 5000 ), 'yearFrom' => array( 'type' => 'int' ), 'yearTo' => array( 'type' => 'int' ), 'defaultLanguage' => array( 'type' => 'text', 'maxLength' => 32, ) ); /** * JSON encode metadata * * @param object $content * @return string */ public static function toJSON($content) { // Note: deliberatly creating JSON string "manually" to improve performance return '{"title":' . (isset($content->title) ? json_encode($content->title) : 'null') . ',"a11yTitle":' . (isset($content->a11y_title) ? $content->a11y_title : 'null') . ',"authors":' . (isset($content->authors) ? $content->authors : 'null') . ',"source":' . (isset($content->source) ? '"' . $content->source . '"' : 'null') . ',"license":' . (isset($content->license) ? '"' . $content->license . '"' : 'null') . ',"licenseVersion":' . (isset($content->license_version) ? '"' . $content->license_version . '"' : 'null') . ',"licenseExtras":' . (isset($content->license_extras) ? json_encode($content->license_extras) : 'null') . ',"yearFrom":' . (isset($content->year_from) ? $content->year_from : 'null') . ',"yearTo":' . (isset($content->year_to) ? $content->year_to : 'null') . ',"changes":' . (isset($content->changes) ? $content->changes : 'null') . ',"defaultLanguage":' . (isset($content->default_language) ? '"' . $content->default_language . '"' : 'null') . ',"authorComments":' . (isset($content->author_comments) ? json_encode($content->author_comments) : 'null') . '}'; } /** * Make the metadata into an associative array keyed by the property names * @param mixed $metadata Array or object containing metadata * @param bool $include_title * @param bool $include_missing For metadata fields not being set, skip 'em. * Relevant for content upgrade * @param array $types * @return array */ public static function toDBArray($metadata, $include_title = true, $include_missing = true, &$types = array()) { $fields = array(); if (!is_array($metadata)) { $metadata = (array) $metadata; } foreach (self::$fields as $key => $config) { // Ignore title? if ($key === 'title' && !$include_title) { continue; } $exists = array_key_exists($key, $metadata); // Don't include missing fields if (!$include_missing && !$exists) { continue; } $value = $exists ? $metadata[$key] : null; // lowerCamelCase to snake_case $db_field_name = strtolower(preg_replace('/(? $config['maxLength']) { $value = mb_substr($value, 0, $config['maxLength']); } $types[] = '%s'; break; case 'int': $value = ($value !== null) ? intval($value) : null; $types[] = '%d'; break; case 'json': $value = ($value !== null) ? json_encode($value) : null; $types[] = '%s'; break; } $fields[$db_field_name] = $value; } return $fields; } /** * The metadataSettings field in libraryJson uses 1 for true and 0 for false. * Here we are converting these to booleans, and also doing JSON encoding. * This is invoked before the library data is beeing inserted/updated to DB. * * @param array $metadataSettings * @return string */ public static function boolifyAndEncodeSettings($metadataSettings) { // Convert metadataSettings values to boolean if (isset($metadataSettings['disable'])) { $metadataSettings['disable'] = $metadataSettings['disable'] === 1; } if (isset($metadataSettings['disableExtraTitleField'])) { $metadataSettings['disableExtraTitleField'] = $metadataSettings['disableExtraTitleField'] === 1; } return json_encode($metadataSettings); } } PK*\  )h5plib/v127/joubel/core/readme_moodle.txtnu[H5P PHP library --------------- Downloaded last release from: https://github.com/h5p/h5p-php-library/tags When no new tags are released, a specific commit can also be used. In that case, the version number used in the thirdpartylibs.xml will be -. For instance, master-f3579c0. Import procedure: * Remove the content in this folder (but the readme_moodle.txt) * Copy all the files from the folder repository in this directory. Removed: * composer.json * .gitignore * .travis.yml Changed: 0. Open the new version of joubel/core/h5p.classes.php and at the beginning of the H5PCore class (around line 2082), check the value of the coreApi minor and major versions. If they are different from the values in the current Moodle version, instead of upgrading the library in the current h5plib_vxxx, a new h5plib_vX.Y should be released (as it was done in MDL-80544). The new h5plib module should be named taking into account that X is the coreApi.majorVersion and Y is the coreApi.minorVersion. 1. Replace the $_SESSION references with $SESSION. That implies that the information is saved to backends, so only the Moodle one should be used by core (core should be free from $_SESSION and always use $SESSION). More specifically, in h5p.classes.php file, into hashToken() method: * Declare the global $SESSION. * Change all the $_SESSION by $SESSION. * Change all the $_SESSION['xxxx'] by $SESSION->xxxx. A script for testing this part can be found in MDL-68068 2. Add namespace to this library to avoid collision. It means: - Add the "namespace Moodle;" line at the top of all the h5p*.php files in the root folder. - Replace \H5Pxxx uses to H5Pxxx (for instance, in h5p-default-storage.class.php there are several references to \H5PCore that must be replaced with H5PCore). - Add "use ZipArchive;" in h5p.classes.h5p (check that it's still used before replacing it when upgrading the library). 3. Check if there are changes in the getLocalization() method in h5p.classes.php and update lang/en/h5p.php accordingly. If there are changes, check the t() method in h5p/classes/framework.php too (updating or adding new ones). 4. In saveLibraries() method in core/h5p.classes.php, check $this->h5pF->saveLibraryData is called before $this->h5pC->fs->saveLibrary. The library needs to be saved in the database first before creating the files, because the libraryid is used as itemid for the files. 5. Check if new methods have been added to any of the interfaces. If that's the case, implement them in the proper class. For instance, if a new method is added to h5p-file-storage.interface.php, it should be implemented in h5p/classes/file_storage.php. 6. Open js/h5p.js and in function contentUserDataAjax() add the following patch: function contentUserDataAjax(contentId, dataType, subContentId, done, data, preload, invalidate, async) { if (H5PIntegration.user === undefined) { // Not logged in, no use in saving. done('Not signed in.'); return; } // Moodle patch to let override this method. if (H5P.contentUserDataAjax !== undefined) { return H5P.contentUserDataAjax(contentId, dataType, subContentId, done, data, preload, invalidate, async); } // End of Moodle patch. var options = { PK*\?@ @ 2h5plib/v127/joubel/core/fonts/h5p-hub-publish.woffnu[wOFF @ OS/2``cmaphTTVҒgaspglyf+head66rhhea$$hmtx@@6xlocaT"" maxpx _name:Spost 3 @ @@ 8  797979.#!"7607>'&"5  % 3 %  @33%4&+.#!";#"!>=.+;>=4&'...tk L]]]f 16&'&"0121!"3!02127>51 TE20  1E  1E T F2 K5&4&/&"8#'&"882781>51 Z4P4YG4:   ZOY4:   '   7ggggggggYgggggggg #!!3!5UUUU,=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5  /?>/  4FE4L  6GG5  2CB2C2  +99*  2ECb  b L32L  MO56N_  S78R  Q55Q 4M  I//H  M4{$'.#" .#"3267>54&', ## ## -   "#   +  1  - ## a   ## !%!"3!2654&/CC//CCNrC//CC//C!"3!2654& 7/CC//CCOOC//CC//CPO!!Ze ZZZP6&'&'.'&'"'.'&'&6767>75276767>767>51((a88=@p)"hEFGDi!)p@=98c(( E*).022f220.))F>y86..E C3)//e340EiiE043e//)3C E..7367o875.*)E E))./c3L͇ī_< ڿ!ڿ!, J:R8d|] c      n  4/h5p-hubh5p-hubFont generated by IcoMoon.Font generated by IcoMoon.Version 1.3Version 1.3h5p-hubh5p-hubh5p-hubh5p-hubRegularRegularh5p-hubh5p-hubPK*\(ss-h5plib/v127/joubel/core/fonts/h5p-core-30.eotnu[s+:Gh5p-core-30RegularVersion 1.9h5p-core-30 0OS/2j!`cmap60gaspglyf_Nlhead/6nl6hhea n$hmtxOnloca=pXmaxpwq$ nameMqDposts 3 @fgf   fY_B eY\xff79ff79ff79ff!-ff%}0 ff ''<<==ff 7<<== f}f #',053#73#53#73#53#73#53#73#53#73#53#73#5GGGGGGGGGGGGGGGGGGGGGGGGHHHHFFFFGGGGHHHHFFFFGGGGff''uUUff5\.#"#6&=#3733267>54&'#"&'.=467>32267>7##"&5467>32.'.#"3%.#">323267>73354&'#"&5467>;%2#!"&5463%!"3!2654#53#"&=33'#535#53#53%#546;#%#532#'#53+53#53#53 2)   '      ((     !          mmtBBv$  !! !!l  s !O@@AAAABB 3 ! f  (+,! #}  q]     $ %$  HBBB6@7     ff(Ek"3267>54&'.7#";2654&#"&'##33>32%267>7#"&5467>32.'.#"%.#">323267>73354&'#"&5467>37  j// --E   0?     22 '!   ) #"     !  T  -! ;-!!- )B **267*.!  '      v   ff#`#"&/.546?>327>32#"&/#"&/.546?'.546?>327>32#"&/#"&/.546?'.546?>327>32#!"&=463!2#!"&=463!2#!"&=463!2J+b$................EEETI,b...........///..f4f$7 !7! 7267>54&'.#"'35#44a    88_6_    Rff%6\%"&'&4?62326?62#7"&'&4?62%"&'&4?>54&'.#""'&4?62#}"A33+*0.++A" .*0.++4333+ +44++0/++U*0.++4444+f5fi62"/#"&5"'&47223!:7>7>7>764=4632"#!*'.'.'.'&4=463t tn              t  >t &    &  '      ' f5f;]>7>7>7<=<5.'.'.'*+*#!4&54&'.'.'*#81#0"1*#0181:3"#":;:3>7>7>5465!:;:3>7>7>7<=<5.'.'.#"&#:%*#0"181.'81041<5&4=<7<504181>78102102362;::1021818180181810"10"#"+"&0181810"1*#"+*'*#0"181.'81041045&4=<7<104181>781021027:;:3210218181010%!4&54&'.'.#"&#:3>7>7>5465!:3"#"23021818101009818#0"#"+*'*#0"181.'810410454&=465<104181>78181201:7:;:#"&#*#0"181.'810410454&=465<504181>781021:362;::3021818980181810"10"#"                                  H  E        l                                      +  ]  +          j   f6f _%26=4&#"1#<54&'.'.'*+*##";:;267>7>7>7>53265.#%465>7263:;:323#<510#*+*#"&'.'.5<5!26=4&#"3Hz   4  |         4    r             5  n/  5 ff-"5#"&?>01+67>76'&'.'&800F7'&-\   ]6++5 C**<I118/++D  V436-&%7ff!+"327>76514'.'&3#5#535#53360/FF/0660/FF/0`XX33/:G/0660/FG//65./G1FFy33ff'5%'676&'&'&'&2727817>'81%"&54632#1o &%,,V'& %::o"C^^CC^_Bjo%,,V'& %&,,V&'**o!M_BB_^CC^ fif "-9DP[`d6&#'&172?64/6574&#"12?'3265'4&1'&"7%&37261'764/&"!!!!eg ? ?( l.? ?("n!@ @( m'? ?(.} m)@ :")m #? @( g#? >(#m #> ?( 5ff)9^.+#>3:32&353267>54&'1+532"'7##5#3533.'.'.'732654|+  0 vB"2 _ !'   ^,^vppv  ^ B9*" *) oT ' –    fof7l1"#*#0&5.'0"1&'.'&63>7>321021>7:1%66:3'.'.'.5467>76"167'.'.546723>7<1.'.54601265<1.'.5461205>'3810#"'"&1&'.'>790230"1.'*1.5761o%  1g2%* E ?2k   % &   & $ #   D D $M#4 $" 5 ) 30  #EM Y ),[0             2     $   @# D #M#6          ff?"327>7654'.'&"/"/&4?'&4?6276270/FG0/55/0GF/0V!OO !UP#JO !O:H/0550/GG0/55/0G !PP!OP "UO"J faf #-9COY]a3265'4&17'&"7%&37261'764/&"6&#'"172?64/6574&#"12?!5!5!lhE>>" m-> >If "> > m.> >J\- ff>@@(#m !@@m(? ?Km (? ?:Țf.f9%1'.=46576%64/.=461&=4657 > 3 > qdjq ? 3 > dff =J"2?6&#!54&+"3"0#"&1./.+"3!26=4&#"&54632#a  G uLL M|      ^ ^  p  ff#764/&"'&"2?2?64'g????5>>>>f;f:F6&'.'.'.'&'&673267>764'.'>732654&#",4`)+ GmG.0HqH -))A 2  5y$$]7 GmG&[GrH 2&%-'2  ' 6ffG%"#*#"#<54&5>7>7>740#4&'.'.764523:32300'46'.'.'.564'467>7>7>76&5"#*#"#2362323:3*#>7>7>74654&5.'.'.'778o787 (" 787o877 /%- . +   ,+,X,,, * # ,+,X,+,2f3  %>}?      9'B+-`4:6Z#E)5#, 7%8  00  6#5  37      D*'    ff#++"&=#"&=46;546;232FFFf2f-6Gf;26=4&+"%'.+3;!#3!2656&'5254&#"63>556?64/&"2?;065g ! Z U+   f&YY=  s t  ; k + I    +|gYZ3<  ko  = f f+62&'&'&47>64/&"27x<@ / 0055e+,$$2,   !""/ 055e,, 0<@ /p  fJf<JXf#";2654&+"&546;246;2354&+";5#&5%#"&546;2#"&546;2#"&546;21FF12FF !! !?F22FF2   E22EE2 2El""!!s ""2EE22F?!!]^ff2[7>.!&6.'".#07>1>7661'.#*#.'*#">727>3.'DB3}:'V+73FD'X,'L##L',W&A2=#Q* ==!)N&=2f!E' :;  #E %?#L&$E! E$&L#;#&$ ='&c< 3   ^ ff3D#'0"+"&'4&57.5467467'.5461%32#"&57:326?x ? lxxZZ{  pE2 " 8w{#22#j?;jfUf;X"327>7654'.'"'.'&547>7632#1"327>7654'.'&#G>>\\>>GG>>\\>>GA99TT99AA99TT99A4-.DD.-44-.DD.-4\?>GG>>]\>>GG>>]rU98AA99UU99AA89U2D.-44-.CD-.33.-Dfmf0381267>5815814&'.#81#81"8181#5814&'.#81#81"81813813#81"0181381381267>58150454&'.#0"1WW FF/.  .f8f3?W#"5.546;04714&0"#.#"*1";2656&#'2#"&546+"&54671;2651K1F2& !$ ,* 1FF11FI1z"" . - sE1*> E!!#m!!F11FF11I Y !!..!f+f3.#"347>763235"&'7#7327>765##)sC>67QK=)).3XGL3XGL)sC>67QK=))..7Q67>/))=+$GLY,$FL.6Q67=.))=`f!=B%3#"327>7654'.'&#"'.'&547>763235#ZZ-]QRy####yRQ]]QRz#$$#zQR]JABaaBAJJABaaBAwZZ@ ##zQR\]RQz$###zRR]\RRy##bAAKJAAaaBAIJBAbYY`f #/<HU#"&54632"32654&"32654&4&#"326"32654&#!"32654&"32654&#X3%%34$$4X$44$$43X$33$$4394$$43%%3%33%%34$$44$$43%33%%34$%33%%3494$$43%%3}3%%34$$4X%33%%343%%33%%33%%33%%34$$43%%3f_f&4FWf!"5.5463!23.##";2654&'#";2654&!"31!2654&##!"&5463!2#";2654&#f8P5%=  E:#=   )8PP8>8PP8Y4%%55%>%4  O9!8F  r%5 y *P88OO8s8P %44%o%55%F f_f*;G!"5.5463!23.#!"31!2654&##!"&5463!2''77'f8P5%=  E:#q8PP8>8PP8Y4%%55%>%4jnmnnmnnO9!8F  r%5{P88OO8s8P %44%o%55%mmnmnnmfcf8D_"&546;7>3232#!3!26734&/+"&=7"32654&'>7>7#"5.546;>79QQ9@ /!2 A3P824&D!11##1 9P5&u3232#!3!26734&/+"&=7"32654&'>7>7#"5.546;>7''77'9QQ9@ /!2 A3P824&D!11##1 9P5&u)noooono;7621"#"&'.5467>7>7>764'.'.'.'.5467>3237"#"&'.5467>7>'.'.'.546327#"&5467>7>7>7>764'.'.'.'.'.546721 bM  Maq  N ! '    " M'        3 b p bv    *&['  ]&   )'-,V%&    !)Z)"    +f2f%D^z'.+3;!#3!2656&'52%56?64/&"2?;0651#"&/#"&=46;7>>54&'&"3267>54&'.326g ! Z U+   fb=  s t  ; 9//9 T Ik * I    +|g<  ko  = 9?:'( 4>##? 44 f ,f,<^{.#!!676!327>767676&'&'+532"%#!!!!!&'.'&'%32654&##7>'.#"#33>733267>?3#7#'.7%2#"&/#37>7"767>'&#(wPB#077n33(+ >%#Z0/0U#$ "<*\g#E &'>uN].&%< >&6MM6Y)   XaX  L%%sY)  YEEJ)/4- 1 + C`Y ,# &" %(32n771%< P%-*12b--!  (j) }_P ='&+% (L75M3 & J,V+R#% J<"*a'N*) 0 +T.H L IPf8t67>76327>32#!"&5>?.#"+.'465463!2327>767>7>;8321#0"1"'.'&'#"&5-.RR[310Y(("V [-yE.++J  } +[-wD.*+J   ..RQ[301Y()"W VJIk $!V \,2 +$&  [+1 *$& VIIj $!VJf<#"&/#"&/.546?.546?>327>32u ! #~u"!!v   $vv " !v v $  Jf8k{"'.'&547>7632327>7654'.'&#"+"&=467>54&#"#"&/.7>32+"&=46;2j\]((((]\jj]])(()]]!"sNMXXMNt!""!tNMXXMNs"!+ j F$"b&'.'&547>7632#8"327>765<14'.'&##"&/.546?>327>32j]]((()]]jj]])(()^]jKBBbbBBKKBBccBBK  C` C((]^ij^]((((]^ji^]()ibBBLKBBbcBBJLBBc DbD Jf8#!#81"&'.5041467>32!2, 2 1  Q   1 ,! .  1     1  . ff/?#!"&=463!2#!"&=463!2%#!"&=463!2#!"&=463!2.! // ; /.! // ; /&.! // ;!..! // ;!. // !..!7 // // // !..!7 // // ff7So0#.5<15<1467301#.504=0454673101#.504150414673010!.5<15<1467!01!.504=045467!101!.50415041467!01%         $  $  $ I  v!!Q!!v  P!!w!!  v!!Q!!v  P!!w!!Jf=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5 0??/  4GF4L  4HG4  3BB2C2  ,99+  3Eb  b M22M  MP55O_  S87S  R56P 3M  I//I  M4ff1f%47>76321#"01"&'.'"#"&#"'.'&5'67>76;4654&54'.'&#"13021>7>7&K22:922L8+ )H  812J))qEDK kIHSRHHkR> )  :f*)$$66$$)3Q/ &5$#)a8..A :43MM44;Jw(A  7%Lf$n#"&'.'.5467>7>3254014�"1#854+0"1"010130213#0"1"0183061!0126540150414+0"1"018302138126540!$%!!]99GG99]!!%%!!]99GG99]! B  ?? * W } ~ M8FG:8]!"##"!]8:HG98\!"$$"!\8i \ j k  Qj j Jf8T"'.'&547>7632"327>7654'.'&##"'.'&547>7632j]])(()]]jj]])(()]]jXLMs!!!!sMLXXLMs!!!!sMLX:'&,,&'::'&,,&':)(]^ij^]((((]^ji^]()!!rMMXWMMr!!!!sMLWXLMs!!Z+'&99&'+,'&::&'5f I!"&5463!2#"3!2654&#81#"&/.546?>32>32;QQ;;QQ;& <;  ;R::RR::R < ;<Jf8"'.'&547>7632"327>7654'.'&#j]])(()]]jj]])(()]]jXLMs!!!!sMLXXLMs!!!!sMLX)(]^ij^]((((]^ji^]()!!rMMXWMMr!!!!sMLWXLMs!!Jf!"&5463!2"3!2654&#x7OO77OOO88NN8 8O ff$'.#" .#"3267>54&', "# #" ,   #"  G,  1  - "# b   #" J f #.54632 @  &&   A %% @  Jf)F81"&/#"'.'&547>7632#"327>7654'.'&# 3}EYONu""""uNOYZNOu""(% . 922JJ229932JJ239 #)""vNOYZNOu"!!"vNOYE}4 !-^K229832KK229:22JJaf/#!"&=463!2#!"&=463!2#!"&=463!2a v   v   v  eff]f:"'.'&547>767327>7654'.'&'5#gZ[''! rNMY?56OdCCLLCCcO56?YNMr !''ZZg''Z[g]SS+, ! `;76%47>7632#"'.'&,,M%%UVaaVU%%%%UVaaVU%%gEENNEEggEENNEEgX u 6 #bUV%%%%VUbbUU$%%%UVaOEEggEEOOEDggEEff:Rk#";654&%&767>7654'.'&'4&'&7>'&7>54&'/0d  ( + + (   0%&55&%02I@  0550 @I"''"]@  "#P--00--P""   *)a769976a*) M* b99a  *  B&&CffK\"/&4?627620"'81'"'81'&4?'&4?6281762812112764'1&" S L  DEDDEDDD  <  [d L  DDEDEEDE   R  `f!Ck%&320616&'4&#!"3!265#0"1"&5&67>7.54632#"&##"&'.'#"&'23267>54&'tu'%4]  F11GF2    (3 y54$A("> $$22$$3 "   ) $$ ff$9'.#"'.#"3267>54&'!3.5467#!5#"&'5 p  4 JIq'  4q5 J|   l ff!";!532654&#!!z 11 L 1-$ 1  1GG1  1`f7W47>7632>56'.'&#"3:3'&'.'&576>7>54'.'&#"'&67.'.'&#"&"&&'.'&01006767>7>'R77?>77R3 nIJTSJIn nIJS+801G7o6  =)*./)*=VCE.6     + ' ,d  ((q<=((, )w>77RR77> *SIJn nJISTIJm iP43;.7 /*)=>)).Ju8o     AJ)(e-- &/ I.?a*`f (6364/&"7'&3!26/#2?'654&#!"i^,d <.y Gf^!^ <.( k, ]=V r! ]3!467>;2!2       < <      <  <     ff%' 'rrqFf$`"'.'.'.7>7>7627>54&/7>54&/.#"'.#"326?326j2BB21sBBBBs12BB21sBBBCr1RR  RR 0sBBBBs21BB12sBBCBs01CB2R   QQ   R 5f-3X(]z"&"#"#"&'.'.'.'.'.'.54&5.'.'.#24'.'4&'.'.'.740'&"'&"'&"13"&'4&54&54&'.'2010634&'.7.'.'4&'.'.'"&'.7&'.5#<5465>3"&'<141>54&'.16&'5&45.#"&'>7:326&'>762.'&0*#>703"13:362;26'264'&47461>3>36&'0&#"&#.'.546762322>37>7>1.7>2##"&'.#"#216662?627627>104'.'&47>7>56&'.5467645<'.546762#6263263263>306363065>5>123133027:32>53""3."1>7>3>30#*#2'2#""'&'02223#13>32.'.'.#".5>77*#&4'.#"&'"&5&'1'&"#"'0321#"#"0#*"#323>7<54&'818#"&'.'.5467>7>3254&'.+54&'.+";#";267>54&'.+";267>5"&'.'.5467>7>321"3267>7>54&'1.'.##"&'.=467>;5#"&'.=46762;232'";267>=4&'.+54&'.+";#7#"&'.=467>;2#'";267>=4&'.+  @'             1wA ;L0/j99h0/ML/> O%X>1B$#C//B$$B1!m ,AA,$B/0B$$B00B$#C//B$$A10A$Mm!"m!!mAAAAA    &<   %) 0[)1KL1/i99h0/M!5c+w +B$$A01C#$B0076m7766h0C$$B10B$#D10A$#C0/B$$A1I7k67M776o66M666f:W>32&'.?5#75#73267>54&'.#">54&/.#"326?8   , xH?`I  3  w""\ \m  ,   y_@I3    #"w\  [Jf!!Ze ZJZ[Jf!"3!2654&# 7/CC//CC/PPJB//CC//BPPJf #!!3!5UUWTJf '   7ggggggggfhffhhfhff$BIio ;7>?'764'1'.+"1?3#726?64/.#'"?/1'.'.+"';26?64#'73.1#5.+'1;26?5465>'4&'#'73%./'"326?64/7/7'7'&4?/.+"1;26'#'731764/.+"81;267#'73% C'  ($ K %266  +: ($ I (!& ,55I% K !PP  K %365{  @#  "' K "66  +< ($ K (!&755 PP! K %% K  55<< v<< x 3f33f{A GF7B B///c G? B  @;?-/-/B : 7 @ ///  @ >9@ ; ////[ F @B  ?<>-..7  8 B?  Y///g g h e XXYJf24&'#4&#!"3#"!>=.+";>=4&./.sk )\\]f `f.2?/?/?''.#"326764''7>>==3ff32ee3ff32eeT  N  aa? !??! j56jj65l56jj65 )5 5feff8&'.'&'&654&'%767>767>54&-78p43%$!//j66-%34p87-.65j//!#H"-  g "ff/?N^q%4&#"3267>5&"27>56&'&"32654&'&"27>56&'&"#16?64&"27>56&'&"3267>'6&'.267>'0&5/ /.! @@  O@  / @?  QQAA  l#b#F1,?'r)P93((&,,- E>  ? - ?  [NM?  "!).C**l'&38O'm'`f$IP.'.#"3267>7>54&'#"&'.'.5467>7>32%''#_8;BB;;`####"`8;BB;;`####/W54u;;t55S  T85t;;u41X 1o%B&`;`####"`8;BB;;`####"`8;BB;1W  T85t;;u45T  W54u;;t5o*A%ff (2?6&#!"!"3!26=4&!26/&"3v<     ff)!"3!26=4&#&"3!26'!"2?6&#<  u6  fgf"'+5>CHLV%!"&5463!21"13!2654&#!#53+53#"&'7:;'>53%#53%#535#53'*+532su // 0/V    zEEFF66o 0A000000E660  00 $,   1111000 -OFFFEEF%0ff/?O_o!"3!26=4&!"3!26=4&!"3!26=4&!"3!26=4&#";26=4&#";26=4&#";26=4&g2     .   .   . X1  1  1  1  1  1  5  5  5  5  5  5  5  5  5  5  5  5  5  5 ff/;IUco!"3!26=4&!"3!26=4&!"3!26=4&%2#"&5467"326542#"&5467"32654#"&546324b   =      #(('''::')99)(('''::')99)i>++<<++>p ;  ;  :  :  :  : '('&:(';:()9(''(9()9:(':+==++<< ff0BRdt%#";26=4&%!"3!26=4&!2#!"&=463!5!"3!26=42#!"&=463%!"3!26=42+"&=4637#";26=4326=4&+"!326=4&+"326=4&+"3|        C&&C&&    && %%   %%%%/  c  P  P   <  <  =  =  =  = !%=$$=% <  < !&<&&<& <  < !&<%%<& <  <  <  < 9 <  < fG:+>_< CC5 ,ffg O ,d O ,:L`^~v d < \ * z$:lF^DL| thtRr * !!n!!""n"##z$$%8%%&&'J''(J.h./ /8/P/r01@1123>334>45j6Vdo    x  ! r        4;h5p-core-30h5p-core-30Font generated by IcoMoon.Font generated by IcoMoon.H5PH5PVersion 1.9Version 1.9h5p-core-30h5p-core-30h5p-core-30h5p-core-30RegularRegularh5p-core-30h5p-core-30PK*\k1ss.h5plib/v127/joubel/core/fonts/h5p-core-30.woffnu[wOFFs s< OS/2``j!cmaph60gaspglyf ll_Nheadn66/6hhean$$ hmtxoOlocap=maxpqp wnameqMpostsh 3 @fgf   fY_B eY\xff79ff79ff79ff!-ff%}0 ff ''<<==ff 7<<== f}f #',053#73#53#73#53#73#53#73#53#73#53#73#5GGGGGGGGGGGGGGGGGGGGGGGGHHHHFFFFGGGGHHHHFFFFGGGGff''uUUff5\.#"#6&=#3733267>54&'#"&'.=467>32267>7##"&5467>32.'.#"3%.#">323267>73354&'#"&5467>;%2#!"&5463%!"3!2654#53#"&=33'#535#53#53%#546;#%#532#'#53+53#53#53 2)   '      ((     !          mmtBBv$  !! !!l  s !O@@AAAABB 3 ! f  (+,! #}  q]     $ %$  HBBB6@7     ff(Ek"3267>54&'.7#";2654&#"&'##33>32%267>7#"&5467>32.'.#"%.#">323267>73354&'#"&5467>37  j// --E   0?     22 '!   ) #"     !  T  -! ;-!!- )B **267*.!  '      v   ff#`#"&/.546?>327>32#"&/#"&/.546?'.546?>327>32#"&/#"&/.546?'.546?>327>32#!"&=463!2#!"&=463!2#!"&=463!2J+b$................EEETI,b...........///..f4f$7 !7! 7267>54&'.#"'35#44a    88_6_    Rff%6\%"&'&4?62326?62#7"&'&4?62%"&'&4?>54&'.#""'&4?62#}"A33+*0.++A" .*0.++4333+ +44++0/++U*0.++4444+f5fi62"/#"&5"'&47223!:7>7>7>764=4632"#!*'.'.'.'&4=463t tn              t  >t &    &  '      ' f5f;]>7>7>7<=<5.'.'.'*+*#!4&54&'.'.'*#81#0"1*#0181:3"#":;:3>7>7>5465!:;:3>7>7>7<=<5.'.'.#"&#:%*#0"181.'81041<5&4=<7<504181>78102102362;::1021818180181810"10"#"+"&0181810"1*#"+*'*#0"181.'81041045&4=<7<104181>781021027:;:3210218181010%!4&54&'.'.#"&#:3>7>7>5465!:3"#"23021818101009818#0"#"+*'*#0"181.'810410454&=465<104181>78181201:7:;:#"&#*#0"181.'810410454&=465<504181>781021:362;::3021818980181810"10"#"                                  H  E        l                                      +  ]  +          j   f6f _%26=4&#"1#<54&'.'.'*+*##";:;267>7>7>7>53265.#%465>7263:;:323#<510#*+*#"&'.'.5<5!26=4&#"3Hz   4  |         4    r             5  n/  5 ff-"5#"&?>01+67>76'&'.'&800F7'&-\   ]6++5 C**<I118/++D  V436-&%7ff!+"327>76514'.'&3#5#535#53360/FF/0660/FF/0`XX33/:G/0660/FG//65./G1FFy33ff'5%'676&'&'&'&2727817>'81%"&54632#1o &%,,V'& %::o"C^^CC^_Bjo%,,V'& %&,,V&'**o!M_BB_^CC^ fif "-9DP[`d6&#'&172?64/6574&#"12?'3265'4&1'&"7%&37261'764/&"!!!!eg ? ?( l.? ?("n!@ @( m'? ?(.} m)@ :")m #? @( g#? >(#m #> ?( 5ff)9^.+#>3:32&353267>54&'1+532"'7##5#3533.'.'.'732654|+  0 vB"2 _ !'   ^,^vppv  ^ B9*" *) oT ' –    fof7l1"#*#0&5.'0"1&'.'&63>7>321021>7:1%66:3'.'.'.5467>76"167'.'.546723>7<1.'.54601265<1.'.5461205>'3810#"'"&1&'.'>790230"1.'*1.5761o%  1g2%* E ?2k   % &   & $ #   D D $M#4 $" 5 ) 30  #EM Y ),[0             2     $   @# D #M#6          ff?"327>7654'.'&"/"/&4?'&4?6276270/FG0/55/0GF/0V!OO !UP#JO !O:H/0550/GG0/55/0G !PP!OP "UO"J faf #-9COY]a3265'4&17'&"7%&37261'764/&"6&#'"172?64/6574&#"12?!5!5!lhE>>" m-> >If "> > m.> >J\- ff>@@(#m !@@m(? ?Km (? ?:Țf.f9%1'.=46576%64/.=461&=4657 > 3 > qdjq ? 3 > dff =J"2?6&#!54&+"3"0#"&1./.+"3!26=4&#"&54632#a  G uLL M|      ^ ^  p  ff#764/&"'&"2?2?64'g????5>>>>f;f:F6&'.'.'.'&'&673267>764'.'>732654&#",4`)+ GmG.0HqH -))A 2  5y$$]7 GmG&[GrH 2&%-'2  ' 6ffG%"#*#"#<54&5>7>7>740#4&'.'.764523:32300'46'.'.'.564'467>7>7>76&5"#*#"#2362323:3*#>7>7>74654&5.'.'.'778o787 (" 787o877 /%- . +   ,+,X,,, * # ,+,X,+,2f3  %>}?      9'B+-`4:6Z#E)5#, 7%8  00  6#5  37      D*'    ff#++"&=#"&=46;546;232FFFf2f-6Gf;26=4&+"%'.+3;!#3!2656&'5254&#"63>556?64/&"2?;065g ! Z U+   f&YY=  s t  ; k + I    +|gYZ3<  ko  = f f+62&'&'&47>64/&"27x<@ / 0055e+,$$2,   !""/ 055e,, 0<@ /p  fJf<JXf#";2654&+"&546;246;2354&+";5#&5%#"&546;2#"&546;2#"&546;21FF12FF !! !?F22FF2   E22EE2 2El""!!s ""2EE22F?!!]^ff2[7>.!&6.'".#07>1>7661'.#*#.'*#">727>3.'DB3}:'V+73FD'X,'L##L',W&A2=#Q* ==!)N&=2f!E' :;  #E %?#L&$E! E$&L#;#&$ ='&c< 3   ^ ff3D#'0"+"&'4&57.5467467'.5461%32#"&57:326?x ? lxxZZ{  pE2 " 8w{#22#j?;jfUf;X"327>7654'.'"'.'&547>7632#1"327>7654'.'&#G>>\\>>GG>>\\>>GA99TT99AA99TT99A4-.DD.-44-.DD.-4\?>GG>>]\>>GG>>]rU98AA99UU99AA89U2D.-44-.CD-.33.-Dfmf0381267>5815814&'.#81#81"8181#5814&'.#81#81"81813813#81"0181381381267>58150454&'.#0"1WW FF/.  .f8f3?W#"5.546;04714&0"#.#"*1";2656&#'2#"&546+"&54671;2651K1F2& !$ ,* 1FF11FI1z"" . - sE1*> E!!#m!!F11FF11I Y !!..!f+f3.#"347>763235"&'7#7327>765##)sC>67QK=)).3XGL3XGL)sC>67QK=))..7Q67>/))=+$GLY,$FL.6Q67=.))=`f!=B%3#"327>7654'.'&#"'.'&547>763235#ZZ-]QRy####yRQ]]QRz#$$#zQR]JABaaBAJJABaaBAwZZ@ ##zQR\]RQz$###zRR]\RRy##bAAKJAAaaBAIJBAbYY`f #/<HU#"&54632"32654&"32654&4&#"326"32654&#!"32654&"32654&#X3%%34$$4X$44$$43X$33$$4394$$43%%3%33%%34$$44$$43%33%%34$%33%%3494$$43%%3}3%%34$$4X%33%%343%%33%%33%%33%%34$$43%%3f_f&4FWf!"5.5463!23.##";2654&'#";2654&!"31!2654&##!"&5463!2#";2654&#f8P5%=  E:#=   )8PP8>8PP8Y4%%55%>%4  O9!8F  r%5 y *P88OO8s8P %44%o%55%F f_f*;G!"5.5463!23.#!"31!2654&##!"&5463!2''77'f8P5%=  E:#q8PP8>8PP8Y4%%55%>%4jnmnnmnnO9!8F  r%5{P88OO8s8P %44%o%55%mmnmnnmfcf8D_"&546;7>3232#!3!26734&/+"&=7"32654&'>7>7#"5.546;>79QQ9@ /!2 A3P824&D!11##1 9P5&u3232#!3!26734&/+"&=7"32654&'>7>7#"5.546;>7''77'9QQ9@ /!2 A3P824&D!11##1 9P5&u)noooono;7621"#"&'.5467>7>7>764'.'.'.'.5467>3237"#"&'.5467>7>'.'.'.546327#"&5467>7>7>7>764'.'.'.'.'.546721 bM  Maq  N ! '    " M'        3 b p bv    *&['  ]&   )'-,V%&    !)Z)"    +f2f%D^z'.+3;!#3!2656&'52%56?64/&"2?;0651#"&/#"&=46;7>>54&'&"3267>54&'.326g ! Z U+   fb=  s t  ; 9//9 T Ik * I    +|g<  ko  = 9?:'( 4>##? 44 f ,f,<^{.#!!676!327>767676&'&'+532"%#!!!!!&'.'&'%32654&##7>'.#"#33>733267>?3#7#'.7%2#"&/#37>7"767>'&#(wPB#077n33(+ >%#Z0/0U#$ "<*\g#E &'>uN].&%< >&6MM6Y)   XaX  L%%sY)  YEEJ)/4- 1 + C`Y ,# &" %(32n771%< P%-*12b--!  (j) }_P ='&+% (L75M3 & J,V+R#% J<"*a'N*) 0 +T.H L IPf8t67>76327>32#!"&5>?.#"+.'465463!2327>767>7>;8321#0"1"'.'&'#"&5-.RR[310Y(("V [-yE.++J  } +[-wD.*+J   ..RQ[301Y()"W VJIk $!V \,2 +$&  [+1 *$& VIIj $!VJf<#"&/#"&/.546?.546?>327>32u ! #~u"!!v   $vv " !v v $  Jf8k{"'.'&547>7632327>7654'.'&#"+"&=467>54&#"#"&/.7>32+"&=46;2j\]((((]\jj]])(()]]!"sNMXXMNt!""!tNMXXMNs"!+ j F$"b&'.'&547>7632#8"327>765<14'.'&##"&/.546?>327>32j]]((()]]jj]])(()^]jKBBbbBBKKBBccBBK  C` C((]^ij^]((((]^ji^]()ibBBLKBBbcBBJLBBc DbD Jf8#!#81"&'.5041467>32!2, 2 1  Q   1 ,! .  1     1  . ff/?#!"&=463!2#!"&=463!2%#!"&=463!2#!"&=463!2.! // ; /.! // ; /&.! // ;!..! // ;!. // !..!7 // // // !..!7 // // ff7So0#.5<15<1467301#.504=0454673101#.504150414673010!.5<15<1467!01!.504=045467!101!.50415041467!01%         $  $  $ I  v!!Q!!v  P!!w!!  v!!Q!!v  P!!w!!Jf=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5 0??/  4GF4L  4HG4  3BB2C2  ,99+  3Eb  b M22M  MP55O_  S87S  R56P 3M  I//I  M4ff1f%47>76321#"01"&'.'"#"&#"'.'&5'67>76;4654&54'.'&#"13021>7>7&K22:922L8+ )H  812J))qEDK kIHSRHHkR> )  :f*)$$66$$)3Q/ &5$#)a8..A :43MM44;Jw(A  7%Lf$n#"&'.'.5467>7>3254014�"1#854+0"1"010130213#0"1"0183061!0126540150414+0"1"018302138126540!$%!!]99GG99]!!%%!!]99GG99]! B  ?? * W } ~ M8FG:8]!"##"!]8:HG98\!"$$"!\8i \ j k  Qj j Jf8T"'.'&547>7632"327>7654'.'&##"'.'&547>7632j]])(()]]jj]])(()]]jXLMs!!!!sMLXXLMs!!!!sMLX:'&,,&'::'&,,&':)(]^ij^]((((]^ji^]()!!rMMXWMMr!!!!sMLWXLMs!!Z+'&99&'+,'&::&'5f I!"&5463!2#"3!2654&#81#"&/.546?>32>32;QQ;;QQ;& <;  ;R::RR::R < ;<Jf8"'.'&547>7632"327>7654'.'&#j]])(()]]jj]])(()]]jXLMs!!!!sMLXXLMs!!!!sMLX)(]^ij^]((((]^ji^]()!!rMMXWMMr!!!!sMLWXLMs!!Jf!"&5463!2"3!2654&#x7OO77OOO88NN8 8O ff$'.#" .#"3267>54&', "# #" ,   #"  G,  1  - "# b   #" J f #.54632 @  &&   A %% @  Jf)F81"&/#"'.'&547>7632#"327>7654'.'&# 3}EYONu""""uNOYZNOu""(% . 922JJ229932JJ239 #)""vNOYZNOu"!!"vNOYE}4 !-^K229832KK229:22JJaf/#!"&=463!2#!"&=463!2#!"&=463!2a v   v   v  eff]f:"'.'&547>767327>7654'.'&'5#gZ[''! rNMY?56OdCCLLCCcO56?YNMr !''ZZg''Z[g]SS+, ! `;76%47>7632#"'.'&,,M%%UVaaVU%%%%UVaaVU%%gEENNEEggEENNEEgX u 6 #bUV%%%%VUbbUU$%%%UVaOEEggEEOOEDggEEff:Rk#";654&%&767>7654'.'&'4&'&7>'&7>54&'/0d  ( + + (   0%&55&%02I@  0550 @I"''"]@  "#P--00--P""   *)a769976a*) M* b99a  *  B&&CffK\"/&4?627620"'81'"'81'&4?'&4?6281762812112764'1&" S L  DEDDEDDD  <  [d L  DDEDEEDE   R  `f!Ck%&320616&'4&#!"3!265#0"1"&5&67>7.54632#"&##"&'.'#"&'23267>54&'tu'%4]  F11GF2    (3 y54$A("> $$22$$3 "   ) $$ ff$9'.#"'.#"3267>54&'!3.5467#!5#"&'5 p  4 JIq'  4q5 J|   l ff!";!532654&#!!z 11 L 1-$ 1  1GG1  1`f7W47>7632>56'.'&#"3:3'&'.'&576>7>54'.'&#"'&67.'.'&#"&"&&'.'&01006767>7>'R77?>77R3 nIJTSJIn nIJS+801G7o6  =)*./)*=VCE.6     + ' ,d  ((q<=((, )w>77RR77> *SIJn nJISTIJm iP43;.7 /*)=>)).Ju8o     AJ)(e-- &/ I.?a*`f (6364/&"7'&3!26/#2?'654&#!"i^,d <.y Gf^!^ <.( k, ]=V r! ]3!467>;2!2       < <      <  <     ff%' 'rrqFf$`"'.'.'.7>7>7627>54&/7>54&/.#"'.#"326?326j2BB21sBBBBs12BB21sBBBCr1RR  RR 0sBBBBs21BB12sBBCBs01CB2R   QQ   R 5f-3X(]z"&"#"#"&'.'.'.'.'.'.54&5.'.'.#24'.'4&'.'.'.740'&"'&"'&"13"&'4&54&54&'.'2010634&'.7.'.'4&'.'.'"&'.7&'.5#<5465>3"&'<141>54&'.16&'5&45.#"&'>7:326&'>762.'&0*#>703"13:362;26'264'&47461>3>36&'0&#"&#.'.546762322>37>7>1.7>2##"&'.#"#216662?627627>104'.'&47>7>56&'.5467645<'.546762#6263263263>306363065>5>123133027:32>53""3."1>7>3>30#*#2'2#""'&'02223#13>32.'.'.#".5>77*#&4'.#"&'"&5&'1'&"#"'0321#"#"0#*"#323>7<54&'818#"&'.'.5467>7>3254&'.+54&'.+";#";267>54&'.+";267>5"&'.'.5467>7>321"3267>7>54&'1.'.##"&'.=467>;5#"&'.=46762;232'";267>=4&'.+54&'.+";#7#"&'.=467>;2#'";267>=4&'.+  @'             1wA ;L0/j99h0/ML/> O%X>1B$#C//B$$B1!m ,AA,$B/0B$$B00B$#C//B$$A10A$Mm!"m!!mAAAAA    &<   %) 0[)1KL1/i99h0/M!5c+w +B$$A01C#$B0076m7766h0C$$B10B$#D10A$#C0/B$$A1I7k67M776o66M666f:W>32&'.?5#75#73267>54&'.#">54&/.#"326?8   , xH?`I  3  w""\ \m  ,   y_@I3    #"w\  [Jf!!Ze ZJZ[Jf!"3!2654&# 7/CC//CC/PPJB//CC//BPPJf #!!3!5UUWTJf '   7ggggggggfhffhhfhff$BIio ;7>?'764'1'.+"1?3#726?64/.#'"?/1'.'.+"';26?64#'73.1#5.+'1;26?5465>'4&'#'73%./'"326?64/7/7'7'&4?/.+"1;26'#'731764/.+"81;267#'73% C'  ($ K %266  +: ($ I (!& ,55I% K !PP  K %365{  @#  "' K "66  +< ($ K (!&755 PP! K %% K  55<< v<< x 3f33f{A GF7B B///c G? B  @;?-/-/B : 7 @ ///  @ >9@ ; ////[ F @B  ?<>-..7  8 B?  Y///g g h e XXYJf24&'#4&#!"3#"!>=.+";>=4&./.sk )\\]f `f.2?/?/?''.#"326764''7>>==3ff32ee3ff32eeT  N  aa? !??! j56jj65l56jj65 )5 5feff8&'.'&'&654&'%767>767>54&-78p43%$!//j66-%34p87-.65j//!#H"-  g "ff/?N^q%4&#"3267>5&"27>56&'&"32654&'&"27>56&'&"#16?64&"27>56&'&"3267>'6&'.267>'0&5/ /.! @@  O@  / @?  QQAA  l#b#F1,?'r)P93((&,,- E>  ? - ?  [NM?  "!).C**l'&38O'm'`f$IP.'.#"3267>7>54&'#"&'.'.5467>7>32%''#_8;BB;;`####"`8;BB;;`####/W54u;;t55S  T85t;;u41X 1o%B&`;`####"`8;BB;;`####"`8;BB;1W  T85t;;u45T  W54u;;t5o*A%ff (2?6&#!"!"3!26=4&!26/&"3v<     ff)!"3!26=4&#&"3!26'!"2?6&#<  u6  fgf"'+5>CHLV%!"&5463!21"13!2654&#!#53+53#"&'7:;'>53%#53%#535#53'*+532su // 0/V    zEEFF66o 0A000000E660  00 $,   1111000 -OFFFEEF%0ff/?O_o!"3!26=4&!"3!26=4&!"3!26=4&!"3!26=4&#";26=4&#";26=4&#";26=4&g2     .   .   . X1  1  1  1  1  1  5  5  5  5  5  5  5  5  5  5  5  5  5  5 ff/;IUco!"3!26=4&!"3!26=4&!"3!26=4&%2#"&5467"326542#"&5467"32654#"&546324b   =      #(('''::')99)(('''::')99)i>++<<++>p ;  ;  :  :  :  : '('&:(';:()9(''(9()9:(':+==++<< ff0BRdt%#";26=4&%!"3!26=4&!2#!"&=463!5!"3!26=42#!"&=463%!"3!26=42+"&=4637#";26=4326=4&+"!326=4&+"326=4&+"3|        C&&C&&    && %%   %%%%/  c  P  P   <  <  =  =  =  = !%=$$=% <  < !&<&&<& <  < !&<%%<& <  <  <  < 9 <  < fG:+>_< CC5 ,ffg O ,d O ,:L`^~v d < \ * z$:lF^DL| thtRr * !!n!!""n"##z$$%8%%&&'J''(J.h./ /8/P/r01@1123>334>45j6Vdo    x  ! r        4;h5p-core-30h5p-core-30Font generated by IcoMoon.Font generated by IcoMoon.H5PH5PVersion 1.9Version 1.9h5p-core-30h5p-core-30h5p-core-30h5p-core-30RegularRegularh5p-core-30h5p-core-30PK*\1h5plib/v127/joubel/core/fonts/h5p-hub-publish.svgnu[ { "fontFamily": "h5p-hub", "description": "Font generated by IcoMoon.", "majorVersion": 1, "minorVersion": 3, "version": "Version 1.3", "fontId": "h5p-hub", "psName": "h5p-hub", "subFamily": "Regular", "fullName": "h5p-hub" } PK*\Ž -h5plib/v127/joubel/core/fonts/h5p-core-30.svgnu[ { "fontFamily": "h5p-core-30", "description": "Font generated by IcoMoon.", "copyright": "H5P", "majorVersion": 1, "minorVersion": 9, "version": "Version 1.9", "fontId": "h5p-core-30", "psName": "h5p-core-30", "subFamily": "Regular", "fullName": "h5p-core-30" } PK*\s ; 1h5plib/v127/joubel/core/fonts/h5p-hub-publish.ttfnu[ 0OS/2`cmapVҒTgasppglyf+xheadrl6hhea$hmtx6x@loca "maxp_, name:SLpost 3 @ @@ 8  797979.#!"7607>'&"5  % 3 %  @33%4&+.#!";#"!>=.+;>=4&'...tk L]]]f 16&'&"0121!"3!02127>51 TE20  1E  1E T F2 K5&4&/&"8#'&"882781>51 Z4P4YG4:   ZOY4:   '   7ggggggggYgggggggg #!!3!5UUUU,=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5  /?>/  4FE4L  6GG5  2CB2C2  +99*  2ECb  b L32L  MO56N_  S78R  Q55Q 4M  I//H  M4{$'.#" .#"3267>54&', ## ## -   "#   +  1  - ## a   ## !%!"3!2654&/CC//CCNrC//CC//C!"3!2654& 7/CC//CCOOC//CC//CPO!!Ze ZZZP6&'&'.'&'"'.'&'&6767>75276767>767>51((a88=@p)"hEFGDi!)p@=98c(( E*).022f220.))F>y86..E C3)//e340EiiE043e//)3C E..7367o875.*)E E))./c3L͇ī_< ڿ!ڿ!, J:R8d|] c      n  4/h5p-hubh5p-hubFont generated by IcoMoon.Font generated by IcoMoon.Version 1.3Version 1.3h5p-hubh5p-hubh5p-hubh5p-hubRegularRegularh5p-hubh5p-hubPK*\PQPQLh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-greek.woff2nu[wOF2QPPF?HVARZ`?STAT$'\+| /V tT H0J6$  ~ ~ Ư;eR=42a񖑁`6_0c ZV!2K&cN`eD bNq"7F͛EMzIOjQBwCDAHe2Wu5Ntf1/>|'Mb9W'')l[%'qtq85!Ѽt!*y4!~զ.""e=-,$A(25)FACPRvyNvL'P'$aPox#n?:NV2L>DQjhvM`ARRňVL.*];eA=+Q(,(jEy$k8zWg~۱,,0Ɏ!p|Ӣv@}{y:-ejiY,ڸ3[@>@Q&XIC H@))ݏ羒KSXZϤ;=A"<|۾ޏꭎS-26N{8MD.F! D"?o}ґwno=Wo_g2 f B!ZiP`өhvOL_kfQXs+E0DCn<90ɜ~i ֿ3A&B"g.6I`cbﵕu@2^uL4=;`zRA|.ĺ,:ԆGq9F@-QBϵ,?Y Y&@OvL|@.P@ >^iA-`?V;#w~ǹ.i44fFJ6'8΂v%' %}\v[nwEyg,/k_Le.s |mz m*j4 2e૏jG2/v0"߻$4$a}F 2ܧ@]κ׷>ƖL"5HS.A~dw>{WUSYFK`H| a4f=CXj@hzz$y2C@o X!>I~(s)oҹT8喥}惸G0m=mm_ƶNO3spך9}pjK}į+O߽Iq/_roYn=lOYZzo׹2ta*IyjjJX,L8 09 o3;>I~,9I_sh 87^CKp6f }p[:_2ۆS tae\E^qX=nXP{p*& 8mز `RJΉNAWX)+~SB#5U[rU c #3\{|Za#^19%! E8=q'g)e*9+#"<" )Ȁ:OH U>rwvEsV]E<-8q|3L3vy[ l0dj :=6+}Lp)!ꧣzf:T*mAFq 7BY/篕!E@>?ywH.x+2ypyD/u6~|~܄2EH޶,COē5wT(yp~(RaWpJW|[)VU)b_ QLU(Eo>V휘EnxF}z¦p c(Ԝ>f8$:XN']1a"h@ͯx~< pO?:} z\pu+f(˖u薇Vp]o߻{ !62,KWЏϊÿ Ago|7wVOޅ7 ~x__C^K遡jx`^ V1)a|r)Jh);دMEB_ H-|@M P %܉D]R"x P!ira$<\lz1 n[oQ;ƿ r_(+:Kc*(ַM-%f>(՜*rv6kHy(@M I$ԁK~ Q- @P%;- I: 7\ߎ)^D1G`G=dg. " $dy7ZBqsKDB~/mۜ GPKIu'6@,*a_9U \p:T ,XܙUHK.ۘLB _Rd>8r:²Cst%\-:k,R:\翏9ÉG. ٿD*_m+?aO`=F]Xb"?q?9 nj65Z)|fˠӨr HtTdDxXhj7:b/oq ?^*d;::zрxgX궱dPoąv_qS-o078v3>@C)wВ pkaE­<D2d.ǖeK&ܺixwJ x3A]#wգ%z$C|ω E@lUTMb@,~l7[јsST;?-_8TMz1DfѨvgR7ѮAhc׻6Gl3ݼ}465fƖZQѡptc\6pK1>nbE&+B=O37rz{gi{#Q͎(#:^}pPET )h"ґ`)ߞ*R>%:yfFM61u.A9wC/ޫmNǩhKQ S&"H$r ,kwN/I?bVjZ5tvPf#y~xeFkrB#>F)z;" Jh|_qNzvG85Hǃ¨=j̑d@^$5o@U_dчNc:.NDf,>f<ltMr.CNĒ:vKW S$xuk\.R[|x mqu qt:H7&!=p%Llr"ZM Ăwϡ_ˠBZh+{AaV8KA1Wiq%Wʌk[QnlhBpX|^˖*PU4 zD`546!6`Pbͮ4OW04fH9[+o4y5 U/̡ȳ{ ܉kΔ ٦?j6k0RuYTx7 w2ӌV`0FS.rg}a0H%@4-uf&Pc5G\Z,LAsi/^$rtVP3(%vh%Z.YG4{jGGb v۟ )㲅 s'c 1\i+b$AfYՉ(Qw Oʡښ;-CX3ZqT51c ! T8${ $YH# 7 ?u 2dJ,,B'mݽwwdޏ0iᆜ<; #R+)6a=n,Ko*䜰 ^i߱M4`9ikA8U3nqϢs): A;i*, >]>DzSW? ; "n(805xH  Dŷs">wcB ffJur>B jVs*)2FSǀ(smѪ5L;@*N E@M7]]_Do#dL{5#JG@ U1/0i+*w.\N&!@&I)Y/غTLէje&甋:qNrIa+Gځ1.̞Lsa9O3JbQ/^饌)@p^Z3շ-7D|W{7C3%[>t_h./5BjLw.El)= Í&ux`P ǃ_O l Nf9*B< IQsQs8 Zt:aEs _y;#2ko2dn3ͩwt՘*ZٱXNZ"C0$덫Mzx.倞0-qdHz?(q1֘#8XZNq0ɋ*G.C szjdG64j￘ Fe#` VnQ %@i8dtވL"vfnjץABqD/I Μ`-+ЕMآ-:T1,Ȭ Pp$H"M-{`Qp埉〗7:rѣbK!uQԟyoTk{V{/UNLZ8$ +++(c}aksMvjk&د` oPF.Uӧ2{Q)x#UQ>q۾$L &OLxWGچp4) UZ\+: %(h}pc U*Q4q6#bjj<˽gPovAq\Ojup@f⧋OQ _?+&ĪRLz8[eh(6"ꪒD^9Nb3yUm|='P<ןarn156FI6T&Q "|p+}$u-@} sbt#윻Mk*t_T91)Z\sc]5XT? N"C0c8J< =:Km)=;ao/s'`)DAɚ p{Bф6|O83dTLX H[P Mr,>crL5K9z 5yGSS};[6]h᧛wSӷɪoMmOSRHJ߻HoZs7زKhm(yQfב=k~8B6޺I~紳Imæ.[}{ש*H>RҪq}3(KiG]kX-/zT^ u"pjۓ f4\wYYGBV..,hJtAS^βJ<@k)$fDJn5G[0[v3Ofo-g/Me"}N9[7zɚ 1+:󞍈6=ȳU-(TPVm+GW quܱH´yʺjf2'm;ظDJ1.4ƒƩ S6L}"5M;ȈM+ښkᖹ)9aZ;/b Ѷ,|-t%ju>'-5Ts] 0DT(8\ k+Н;(=*!w$!;haVr5xLd7o[s>|VuuJ; DFFZQr{%i*Sȍ>*0א)92`ܠ%zXZun% @COEb(r^ݠ0ٗEveVu# Vdet/'9BG18hsPӡj/ҴUcdtItf_U36Z*!s#S'E%JP:b gej,',w/0-H9#ʽ a!ccˍ?2+,Zb'M7 >SȻV]~勸>7¨`=׍?S1=&&$x}2 $E}ItSnIPg.ʾB\!{;]a\owkF=(h=`z8ti]oiԉL#];\/כQWi!fk.~!Ǯ M1)Bu&I8ic+ILڃvc}̾{⠀XO8rL(#nlߖ;n-ԸZ Iao^I*Jω0Ppa?ci_n9Gw1Q%fBJ@eI@Z䆙H:䗒byoAMcz{!ݑ2 꾞xԢ'~m( nS;ʖ汬>>\Mȭ,u<`cɖ>k{b+!:`d~4d_P=4k&݅5P?s)'XT!Ubi>y!NF;+ v%ƹ8͋zzڿ$9͇K!ܞ|.-Nf?GPڰ :t>d"o/ x[G}4B?s'#* ƊZB~.CI{ĢѾUx u>Neggxw‚z`yuftX}&XEikZt%,K)R$_g*:W+&? 厹.z-Fn)=zǓÌcg~VL+ǫƬYkz`Lꙩyi_+:ߦlff/2KsxleԵ[V?>d֨~,^M}7_aXu p_/|m L$ ( Pў PޒiJ\L!xh؋]5uS{ p#tMsvWdwP N㺛A890v$>E}d؆ D ̑O_!a vݑsM!s~K͜x;a vwo.=B;gB(2Xq4zˬ% b@eKf G/oշ Bp ^y`rM>C'|,m]+ $/hg-2ҷ}kpZ+w&mSZ97FQ[۫3@RU*=Olvg Q9ao:dߩ8( QcZ ȣ8Jٰ4ul/cV(?w^Eڣ>UW.I}47  9UTUmDa܊ΞPx$51ɸ;-o6dZ̈iT؆[4ֈ m _Ѥ#QKGs#`%E0=sMȎ"8{nmĤrq~w ovk;D*D|$:sJ*{Up+- 8~]_ߔt` \e)}Shs/}d)$)tpe1£̹t&~37^< ¦=0tהp$V!| BAhO"h: |U5Z.Yw9?ڑ iߗA'xaSd1ѕva#S-ᗡw^ ,z"e4-Ӑ٦eQ>F)]u ,[7TONeW͵m 3;uGR.q,TpjꐤLuAޑ|溜 J %w?xB_АQ$'M#lvޗOصz Z T0=3SjLvGtnoO^SɩjA6[M@+'O:OjL7-h%R$)لrrLǢYl:={ꯤBSc&LY@X^1,@8RcMooNu!0n>#1/ "0Kw\V]!-6>Kcc_(sec@;sIeA`"3^nRR4'm Zni5<dfCHSTfhy4J >" "X{*`t }y*ge%9%q^܎v wp$h0)Q{ (:61BA[T6 @(VEb7=/ /S*NF| H@{i[Ae(0n8Cl by["ǽ#; J]d&J9ۄ{k&@ p*NN"ݙ`PH'ҊXs@00@VxH  ɖ$ˋf?Ul(Cܶ;q- Fi!+ukY)  A[=E>@E^fOfpN:x 03܃A$F'楢K>Z域V'x"Yuop{1 VAxDxnvbPΑg!B+Țrb!߄Lzw>$kvt%Az^U} -vs^{IsBY~`S& 6E /dja88$X@d\5Az 7GA FL^RJKQnP 7U(=~GVr+_q- I" wr;ALj;[sS9+8y`1s։pT{F`̟jE3Fzr.[dHYS  Z ܭ8]9A@H%hgfq)|_9C؉;K sP֮8&T܈y<[ܿ3-CJ-9Cr?} bC ђ !ցHqk*ttKvO J y)wrۄqpG] LD^ 0n.>v\Tc$`?)7UFp5!fZ$1w)7CQ@Y3gMqY{xZt:=ZG"܎g] 0•Q'U!Qĉ"?`ʼ2&1:D5CI{q6 JI^OɠdR  Lr]-\2Yj.h-X9݁9ĭmdyzgy\j|.:!!ǜ{Bya ,xXmٵY(kIS 汣#deuЊDp 1?"(SԨDM:<Cϣ1>=&ΏԕHi:qv>l=?T4w$d]|$3)S6M> woө;+p]k[䟲>E$%6NH\ص둺.pl5 *K|V07| |ӢT\@̼=7VǭWPr0"JKk؈ mM($us͒`5|LW=0ιBw( &sáǭ*wp /:R Z]X!m2p{gW둣+ e{\P8yx(Nu^ίj2E '<ᷓH$d͏~%SDtA ]ղ Mo}ѦKY/hwp&̱9").=}oR*6Ǒ> id9C)8 s,q'YFNDj&T3U/as)R@PHh G[J.>l)Pи{;|U5ixްLiqe[+->m h IF)Gs"ҙAR´Fngdɓ#XƤ'kW( Y۝NGiqF&i-q)R:r)ǥ%T.rb췪(Hbf }) ^ ImU 3fiGo+qf$j.iFbl\{䔼J Q2ZK[tpN˻I׮7ffTi;'džϘ(`ch8O8i$yyRE2pPMNj"+2x2ɒ 0ДL&id $N  w.>n@\uEY ;[cstA-%k옂W. YBv.V183pM-vS " EdCM UB/{',01١mi2PwtP1T-PQR2a(qJf|c7J 0 HOM$&mnNa傚k38N@egv'qYazY7ck̚dZؐJvb%nPYZ!Гeunjy׃=8] %gƾX{I72/.H$ P } Na`G#)vT8~8m 64b٢vfJA"&пD8i ^s rT_ uJ #h;f~abĄDD9fIqu^1410|*l)4W~qnhƍG6["$]feE4Tu֑'헩#wP$2v;w0uy,42<ޅ1e_IG֥ycgG*HGrfƮxbϸ5ӿik]2ͼ{Wb\)QҨbsGKq1y{r*,G\f]<5\W(c6] +:wlĹ49Oq+}gA2HJù,i~=D<]RnEf߂ b44Ǭ?8Ƒ{bca/3q,#\0+Wp 4)n(kA( MۛhhX05:?*>aAUVԕS8dhex)+*\|]?Ѯg,oNk<!o'Dhp0lǍujdZ$$nݺxG ̋!p6Etxy^:('a<R$f}XcD󥲑H2{Lru\ka2ȰI(}SשZ(ood1W݋e[ /p*Fnh}VMjΟI{M:rJIE>2JZW'-]c@5f}4q5E!8-9@=W ˁs7TV &"E5sjc wvi$ܸ`-Hz\)M&2&~c+J!HIMJh:go &'Ǹw&2yo.9XR{[a&rϩ1 > =VZcx>f0Ǐ*=>NK;v! 2E[mEaP<)HoQłfNik\9rKJ^ ]1`7hbGSѰ~?gWTK"+ z'2Nj5}B>?x0Qͱު*גv4eWtoEr {V#ʘ) Ʊy'! d1ch'Ē_d{|M =MOf2nkI(?Yo>ZWtG(6',xm0.R89IJIc /fMh&DfMuqGF9lpNbk*/2AKw'I R)@z4LW~${2hH*EGȣעwVRk|s )R!fQi=m?!KQ~pBez8r%Q]جh'p[GfQQ@c&OCb& dACJ!ֶ*?߂qi)>%Im ,40m%є~oUdۡЪ- "y;^~~T(I*47GrP[&zzz5JcηhA%\ ς\ x\\y?t-`KvkչF żt8g&nܞՑ?:9y7̌z 3Wǀu#GH=~29$d7{]'V5IYǙ؞Jae<[JQs"ZEQ]kY`=t)FM3x;ֺ|^o"zVlhiZOg{e)UP~SG;&i1e21lވ6v$ TVTNb䌉twB}ĝ,.bB!Q X:yhuװDgopE!5Ux;x-/F0u;è>SMI3$iD*Rtb1fj͆OUތp`RS~"'ש|SjI%qTx\ր*:Nm>uQRjKxh40/.x/ I8l$p@(pU7pv$a Y%RY%hں5$_e9cQ*lY&h'<4 io6gwe1~ZES{l"waΛRZ5VgHKA0J!eirr85d5s>J2i7fW u$"vK!M>pfU@3˼'"b@뢼: I)pAG>Lit&],̘#~Ta/xz\O.:fϒ- Xx.{n^$ 񻜦!#h(ɢ"{">Ic"%=bIK,b`#I<ɀ2Z}b {02zǸc=ęoD0)M[: 4JJ*NaG2v!}oF 15?2+j̰ fu]O)ci X(t"7\X ɨ$Skg{Oɗ'ct|{` } VbSo[bG#d?4u ߺCBPjtjϝX=@`3V#rkz?nhD)&gF.bn{ΚRٲHyڢtϬo- {x5XPb?B!7AX)z'ILh5ށ1$d"V"O$;e0ߟab.$WaKBكۗNRڍOrÀ ߊ5̧7>ȝsNhT3h8%Ieqnik4?փ:ׄH%R~`1;MJ5:U=@!LC;sz&Nh#ePiP\ػ'tf`Ȣ"{z dQeuC+W[ y`4]~?NNQA^-KC)]-I}Cp܂iTC]Naѕ<`ү#;5:W96rB7=syشwԩ/#>؎sϭ\Ϗ4@Q`]E瀀;apVejOej3~<1\ - c/IBB^y{V\w/9o'yXo?3dnަaߵ--#֠ `MaU^iP'2܌z_T}0MEt'{7iO+d+nkr)UXy*F2OnijT"f՟IjKh+ԷwMb {\y ЃTYhG[Sx~p6 -&$pCix.-18O^tZv\:-M",گҊAZ[&=6gq^cy|z^N0Kp:\~'͟sict, 84C~{&hȒn%IyF0`IpoU%Զ)쑮R.1Dك}vsNremsڬ :׳lf(\B`e2Wgy}}^A\Xp[69q8cWoESqdINK<'Ny!(:F@BQj#u]}ͱsmunMͤʨ+DMdTFEQIQ& RˌfEdFf_Hf^"&⻨b;=#65 m?%= lTM2ܕ !Q̰KH¶jXWe bg3LKOa2hsHg.&č렌 a x#EhR%dmbsýƵ.&! duNFLr( 3S3bbazb،vJ;Ҧf&)t ;Odllg=/S2uݮ崟ˮlgDGr3?"=Ț:cg|Nt72 Qr쀎&854;N~XhTU2_~8'|bΌGq]62QE9j9pF;6sPK*\rAATh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-hebrew.woff2nu[wOF2AsdA#,f?HVAR:`?STAT '4+8 /V d $0P6$D  Rm%lW/훰ɶ ΃Qw6f߃H:pfGd(k ԙY(t*ODw*Eum$Gk~X2*" I5Bݓ\@?tR:ĂdX7i>ºc i x|&ke{}>I.9w]"z!FE,!ĤuJ *:׮n^1*JlǸ沚'=abՌZx?O;3KjDWlsН6M_u{c.d)E(ګ.V jE MP^6-fDvI:Kзy#c˒i~Je(XL$WN:۽}} j>@>C*%&i2! sK-@HI@ }% yhwDJYpfmuf~"9g*ӦVSWg}D8[ﭥuZBrτa8R; ڇW{|-%州G>}¡̼*Cby,Z[ͪ'B3)ڿjtRFlHUV*Al4H]Ei7]$BʰOɅ)|gp`#p%J=O8O=S)Әij 1.Cl:7[ HH47@R'#C;tH\tuew6TthDr3r}!1֪uk; 'e ӞLT8ZvSB(:]hAR@d<Da K_*(M r",;(#B:lͯn,Ñ | ˙K\KhtWy=&wVv,iͼi[[QiMۑ;Ƥj]ڽTxjOFSX %ݖLaُr7Q}4hgf$@O 4X:j:p&6>faV"F.^Mw[Vwa9F|~gZN ^n~̡Խ~Kd;wОX9ОTmhΕ"h/6'P+z'{2ƺABXX2D4@;8@ / A4W<AHUb t$Hp^L.u->(k}wY<XhukRlSZ=hTfl9Yq)̩& ni+>Tǹ":zPᢤJb-%6ѩdЕƘƃQV*L˯8?̟ WcYk9s!}>I}'sS̬=Yb*~?U/t^_GkpJ+Z- m>?q .ٸX`Ȓ,>.x0+Ӈ;UYٞFd{'c8iscyyJT $Μtq5/U:iQRA,HWb N|y2@`w`tVK"yhPͥBaV99 tE) B,cPH#~0B+1:!73FE3L~gHlQfpS:8D‚ w/C$%ӕ,X$fKS@s:Me,Z3X'1+ 4L CJNAMu ȯȏ\wM%>HA'߷}Ǽwc==;) C˃|7 $fW5^I7qܹrh}.dX\ n$j[il(VʦLlEzU3E V֒ũN|ޡ ۝C@Ag a uѽEBAwN&@&ОQYtE(P`imM#fBE?/A fr-gIuv%X+ Eu=2Ī'5jRRh2F6Q: tI.f#һNβ}k LQ m5kȪp9ٳ{΍֯[fpg+/[ڲdI'Ǔh8{G5fه4hiq) ӡj=FtL5"o\8[}2KCURo;P]BU}[`:asLٖVl+Вf0}XֿÞ2ٌe`e-&؛Ug vSߏ)Z݈UaDn@22 :ˊ1:x(&kc;Wʥ*}/ˁDrsĵ0'V3ťFYC6g>a VeV "(y4O1=G׹No!D *' ToZ oF>Qӊ|nUYNXINnQ!q= 6'˗({"okWUrlh\J3Kn3T'~0]w߇'ƺxF̧Ts}9t4&B+pfs!KBVO IX7{((P7Ѹp#I\wC4Y乜%WB{Lp;Wf:h4؟QRxjU8Lc߽p Z[q;r`Z+*f4V~@JNjCo!NGpΠe1>WUuֶ'HbO 6{,_z/YΌJh}F=ZQi{J, (j+h43#7 y[b;[d1p STdF3wnf^a"wXb!~ϼ_%De euT=]bWZq.'DL{ayvTO8׸A7I2jÅc4q g8m_nYtGuJssՍ-VhS~|u33p.xrQMءL!OzeRaIb4<(=؁#,nj)6:FXXӗ ]0wH[9ZI63;%:K1Bvcxr̹ ejw G3eJlKy@* dnlɽuT_↕~t8\0ԗX'6}RLZ@2Q?H3V6ad<, )/VxiDw7j* Q5zλ@EH8>lmmXQ^W;ӵ==JG[[椗Ǻw?ݱD'N+$Γ^:Hd]ә[0Qz?hԃF!ow,ll-Ußnnz(?+𱁕0TxK# Vхd%Wz4cJ֝f-4qaF2%I}y[IWkËv+K/xNщKgETDSor5u4~S*xҼIwp#QGW&  H*$$KARJ{ !۲3XeŖ|,U9iKo{I;5 ^gW^haO#Eiy<4hGd-|V]fGR<=Un0=qy3l1"i*ϴnOO*MjL%3 ^ƬtҘ.njK6`#Xp1eL3CLfp!%o /FT>VyXemU[bYrFT-M<şs^<8i[>xK=| nrܳ#C&{2m7 \ӋFTwRŝg3lR!ܺ>tƾ(ޖ^WǽW|'kI42]C _듲ԨK\7VuGsMJ`1CČhcX~?q?ԙ,n*9=ߝ[6q.kXVQ4;˒"yd3W=M9M$6\zO9bi.^ fܑ'߹D^?.gEx3Ƃ]utnf[iC%fn1:vR"SU5We9Sمr{QĕDRS’9cm8M |PtQ[cJt-kGg5#[>ERǝ=y2'E^тi_ms?UZ1D ^lJc+ 08(aGFL9Ј+6 E{iů(]fTH4= '{LvuN;?~[(Tv) ,T [Je{c,zxy k0<-)Kr7|2]7﫠}ݙK[3 ^g!+]=\&̥+u+2WzkInSFAOt-jڣH +?0>,wn}Kwhl vHNړ2}݊'O9fhy %%XX؆Ҿ':כF>MF]ǩݲu/ ]]Ջv&e5hFNKvV UO{0LT`WQf9d(,`N92depb]v;.j%;67d$h;}dKػj5Iz.;'Dظ-; D\[{m"c?Y,BHDu k I>*O I!-7[cky8Ivf,άkͼnr;[ϰoǶYXl:YO3W=}^2(Wou%aQ9FCfpTM,V9qLRVaC5-ǘzT1oi_9D@,a`ep+Є~EZŤ/{G(ח[YU@x̚eޓN.`XY|w`GJм.|e&\82嘄qMqc(:h5.XNȉfŠ)Ks“W>DAҜTM1PZ$35QؚV øRz$eHSj\߱}7^,D64E9ל搷Fnl!z DYpSO :0hAjJ0SZQl:Hc0bL ֋=^XvOĸ 4 }ősG \̩k*/?nNOnjyy&r0 kRl)g^dY_Osb9Y^#O1A`) $2Fb1L"$' RM|r.Cwɟ[B\h& w&(55J}(N"AKSZxr#ҲO9Hg1>?' g1CW<| D|Zk;erIF.&(-CDۢTlz!Wp% S7Tk hvbӽ*vsYb0bdNBmJ|SsRj Hlq, Q] [Xul ~rV hrء됃b,v{$.Ueb lWfX68"Jri`ס 6LJ3?VhׇFUxXF1,l &5EHPB96W]C2;I 8 xD=MB v 瓓jF-$DAv]icJeʯ@ *;Q#j+P6T:M3\#iTSְVF`"2TPj̴fLB˨KRNj]6!ʰxcز n{$@ٺ#|w*qXN1"m)ճC쩎K h+dSIvHA&ǹL:#9; zrBb (Rf:?9:R#}}i~M{'ю!qU%KY|3G է $JJJ\BZϧdqy)chRQ$SB>z:ኦ5k%|19Лx!>1fF\B:ɥtbAa#吏hb$ϰG\F$N1!5]Ű z=eD[-uZXa|w&ƒRlfT`20(FX[Vd*E Wh5mu}b+гP_d_Њ$`1T,WZĨT*PB}0Ph0j#0¡!ngfشt 'zjzb+R)%iop{-F1́ۮBXِ7d؝u#z"ulv#:f505i(:pi\2ʆusU ̍ПY*l\) 7ȘW} D{˦i =770C.D@0Ҟи_/P\pP4W @™ 6#QX _&j<+dpLX6t:!3Ux Tw$h[clF#%gQɤ҇m|./VȺ T&Oty=1b icgc&_C<,3Y+)E Sl}ƏÎ2b\q3&2CY[.!? 1;֭M:>2|̞:Jֵ,UlH+ۊ`˘qG5MΏ2lұ[:`$yvbSE#%s" eřQKVjz0VbLQB* mN,oUWy.NFiWIFHVenS|tY!g>; jI k-'j1n8+%ƂB+셈t,1N@~TCMVɾԈ MFM #nH^tL0P*U6CR`^H-Y(]G¤wwg_}Rk1J?S΂YBl6 O ԾYJx 6 ІcY15iXKƇT=>^b\)%!pv:JvEnADjsyt1pۣUZLR^A-{WI[c' _>C&U,=sdۖg6R!XxT6""8p` a!Z-X")ce`Ï4hIhPk `!kB aƾ!ڱdp6ӂZNrЗk+sVWzzOHJgJKMp5cVƫTz0C12zR=ߘ Wö"_ idW&ټ7>WkbL$e5d3yQ 񹒟5.UF(`ٿRƜ&vX&De.h[,Mfz.Roi+ZtIOb}ؓ.⌑rI3L1ngS .H֧U肇'd{obV}ÜCQ8p4C7K+wƿpvm~;wya=`DGh'Nh=Pɼt@U}05֓a\Ac*7KmǨ022R6'J=i8o)Y/mk{>-&!1a..XՖ6e%5DP[ r\H ]㒙ft uH)"d[46M+(;{5(N.x-.Ė&  N;+aI1񚓧ƓOC0R3v=Ÿ תgcb@!@\S ||\KKQkE\i!2n4!|nwhx4"Nbn0랷hnKh4$˕$z %Җwzn_-`Y:J`DsH\V8J;M}.\9Uhb6&T R!yn-RBoi*doaUP-Wa%dB$p.{%*W<(oZZEYiEy|{YWr<vro쵫PN٘)6OBz$89"' fM97~Kc(@ƤN Dwܵ Z++ٶOC^XfPHYǷPO#lenknwkHMzײ$1n<0w,zkDæ*~ʲo)Z@ PAN#[ϧS||<y+fk5i+s~]h{4w%v♠|tFM1udE凪}JqIT;ʤ7t ^Iq ϻ]X2l}BD'%)y slggLTkA0buLfiD Vnjzb\&RGKo ߐxcYaY0Ycm?bAv L8 H\NҡGsa]):[>Y70 )eSC-Yv#,X pxR{D#lyO>H,ƒ_ q ~(F?Iy>s!zcyOUDZV$msl5lAk3pۍp@ƙ݋M1]ҔgOh8fh1{p @.:udɍor%&$x崂&op 7?d[+˺Sut_y)7KYzP:"[C,&EUW+/41&2%8ZvɛF l,x aDlU'+a29=@)m2RTJ\c'!(MGإ(xЋ^.$8O! ޅ%IKa@XJtԵC:7H钾K8lAa;-Dw'EԣtROTIo"Öc",S7t~2 Xb)prˣRJdIx8HBȽR1%έ $JAS*\YVyD/r 0@@*B,Ȫ~Oӈ{餉e°6U4Nң uv;< uv'rgq^I̎d \쪊!59KP2 v :V!$-[AS.sJMUb<]7Qd5eɫ~0]vU۴tl^;a>)#Os$J(+n#ڥi6CNhT:"zRU+W͵D ɮAj:> YamTRH`N=9 ;hRZI2pauMӡ^;Fq.R0ި54D-3mJu̦A*Tq.,$e\eiUR{1V?aHV@> ʭ$>K"6pR2^|w[@ BX[J°_D2<.WHY^{#- ێ_`d4^Lr)\o-QɺWя|'YYd室`n^PףP D8ۀ"R4BITWRE w|Fs>VxiMhRF -reX1łUu}}E=~ @T?t>r)ɗa~T!RHiaCgr: J'ڵ~0dS-C2Xk}Nc[U/袕&UZ2BSɔ*":\=HC}ެj1yicz巢hM_XqX}luk|@p$#"%!&a0%΄Il 7:2AUDB%Q$^HiB sЈ-P4f"UG/dGt8fq.4T6_UjƫePB O2TRm)+&”K PLXhH[4pjo有,X*&v(dc4 镼kԷ:pF4t?Jy}m@!2O&KQۄd*RG0k6t?ISQ~Bw V: }L6?|"Wkk;.>4>OuX ؈\/H8·![by%IWh1ӽHD06e ȓ~_ C+`칦7 RC`ˬ}܎YnV63M `c+'$.I\B"ᔪwOsswHe\]CLi&h)1U.a6>c3δ_ {[80/?[AINHGZه3s^m' uG܍r;9ɯwu93Хi ;e9K:5_W;~m|__&>׹o邏l>BƯY"*NX]NrsRYL?+SzԘuu wJ/br%nŒo?fe:-VFg5G9_>yFǖ~Ix3//X<6 am!ֳK\VFVvxB0iҚqq1;獊 B;] S2&^v1 ]&ẻ`KKM. SB8yWp Հ(KU L aF"S7KOmKMQZPAqT[ d&з@AyUtS+S>uTyV/*8vP蘏}ֈ-R!}ձ=1edd.*2&p<И8ȉkrVNiJen\"'̴(.ѩ|rErmCOC;1fsT6F'KdصK1öjl,cx;P'1z,GCM$-ڜOoJUPjޘ  뒹d^㇃ɂɨ7zRrI \+CzY4aS]qtg\w/Vk|n5.fq|B |ˡy\/3vҳ&z <ѣeiح+@1.ԔY,h@[-=-VEG<0ǰm0$F),øhr!\AUO1Gy7E'\:PBa0m$VSf:,RC 1` 0+&hBxk‰\rE j/gr5-StcP#ɯTc_b06pk]ԸY.gU#2^FOYs_fKrOjOAC3P\s sK0^?< =]FKE>(R.AUB ;c*㭑i@TrBѹAZPK*\!l``Oh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-cyrillic.woff2nu[wOF2``<8  ?HVARg`?STAT$'+| /V (4 06$ ~ %̳Q$zF8@+Ld a2?d$ !qp }ܖ\kd\INs'-!QTOq~ l,~< |i i I ԴZ,jaCQ)jtܬhQ5y<\$B/3e.&7]y1.ܫ>hqP9ۓ')6FxݯN$;60 I({j *bv@ D0R_D1.sj,|ܛ n‰HFG<""{+gfNA˙ Ce.W6WyzeD;Ԅj4@i=t$cLc*C@_t_H<H #w,‘5!<#ߴ~LKOR﮷{MKb!@ !ŰX#8%QwNƣJH{ԚpPћ/ OZ$SKt( )tAq?7mGjSlgq.Iw琥w{tVQ:Un1C`fRzȕ ҁT8C& )ڕː(^ s ݵJEr /A6<ΰhrQsӀhB6H0G䅡SwC EIsx+~,t(aw*1{]l*"X7}˘Z,YQ=Ȑi8rĽc,nFJ#0X ;5!bu%/;P#2y`| 6enF)h+rM.b-PT|wY֬g Sv QP_`*\=>ˁƀNz=cKnϊU?or IM]^xvL}=Fx^=}^R/]W{o|b{ O?}6c~כ# _5LMyO y|7ys׏~B(oDHiіqn=]0|7Ѕ,n—o}ᔀQX daC]Ԃ8CwHv"xT2N]@N @ C>Hce~GКP9^gHC^53BE4:Q=dlbNܕnyߡT;<;ek]ֳ9sYN>2wGR`zRV=w^  '‰$% #lyB lhI}BFS%09}XTOˬh¸<0wU-"qx>= Z@Wmtz"!HT'*,Q͂ /_J,]KmQt4c; 5W;"!CTP+¯-@6#"X"o?BA(Zߵak#6ѿ<QD7[Oy;W3N=ȷgq"깊O>|+cjsjkA 8 @^/2Q#(iO#y{Ţz92LV*^'G3)WX\)Z!2:dW,YYn_ҨJ$J߸q(VC:Feз.Bގ7~oDQM!elkU}oֻW_yMbjM_|&pпRcPy;s۸EQuRVjYr~O㭎5Ha ٖseNfܻlU#C‡{%GOk%;(VCyL854[6S Q&q 5Lhzs<ӴF?KfPI^t (1dI2-N}R6&oʲ(7)%-iu)v68mg/+YR+aHtL41#(L,tzp>o<,oxq#h%ю_or'WH =!i_l:#iP >-)LXO.c[s)5& ʜJ`cQb3c ~X~zCxHa(A TT@<7IDȵq4T}ۨ{Ƽ b5C4H4@}P$]Ih"0(`N|`FR _y@n(w l3 T`Uxx7П[&J.6-`^ .8 B(pR-l"5~awѧ@ˮl,6 X )L \jrs4I*lq9h)k-'j۷NN+f^9Xբ˅n5_iX*wu8gYawLp)8d')Hk|) 8|#\B*\*=!W^3LKI Sɲ.l9 't*H*~I #.i!Kj\+񈭶_\SC۫jrʿְj#V06&Vvbo{O;|xn%P1X>NCoxXkz'7wć63Ձ䩺-4 8Nu!X0a(x`)J[׸yis@6Dѻ8&)udA m}*(Mmz{M;crSRfF inu=bqKL!* +v^˦rVd$YL-XUgWB&օ`35:s 4iܘ6C})9,w(3pޱ(1m lί1؀(6& gMS =K 51jV:-p@}=^  jRˏ~;rLCcBt%jV}!mW3LAoX]2shH[ |?[|ұ=kA #bօ-Hչc@?y(ǽ/okN\`_XsDxwALo&C "NKk+tu ٗo8?(hwvi })rnIς-+a].L)LJr#d5W|\Fwah/ߍ5%Jq|eGmŏi{W($.YW7/+8\,cDO^Npm/7 CyGRsr?9;zX&oM%g !;Ga8Qa^Aq9 Vyc?dT٭ UEމ6$>B"\xGW<>A?#u2wGW8thf{8X8YRT\oҌq>r=>l0^%.Ye U9@{AUҫpm TPN%鍦]cpu<.`"\t7qM_J,$orեaveJ܇]]v68_&3 KՀYξАwVC׈ggu=6iͭ_Lg]FDwb&)vA v A7v4l#?)w. ZԈ|zn'_k?րʛ/ *_s/ΠIYk]%hbv\{F.MnqT,=@CѺݰ@iWw81m=D//4"]V`ty24"gylS-Z6z 9kbMzVԲԉTw?ů"leL?^99~ʽcdeղ^B_xXA4/9_I(g˓OQ_)#;ìzOֵPnq|YPCt2;jC$dHAq}.1cE)ɖpXhb-*t|u:|Jx;m~%9426E>̻ yܠ׊t9jg7|,CaSD>)[PŞs 4hqN: KRy DA@s6d9/痕nNmm=G?[Ͱsq?'@nl6UX[v`2*<0J1 H%%ыHEdÑY b˽OZak,"[{ƷVg\M<1ռtꯠh\P`KLqPw:A=`O9~}H]ZRWUO xB~GC<9gb5.kbzsǐ;NjoRϱ~l&.(ōI?eNpSWʇ*$Mت7f-=$_^2*&<E ~MNFԛyAi[MxR v?mKRqFFzLAn{"+4؃}/Ӥ P6ӹy֕9MݗZ%B9L$Spݕ*0>"~%?qLϏ9NIq`ߨ6xhT5`}GY|^fBG7unΚUD7֢UY$4;ó c-QR7~[, @ ~ ̞$rj I*τէz]OV?kpDbVi +q. $D NxC_0ۋ KSoJ*W.;I,Ėz'ҿԗhXU8um` &*p p#-BFpǀ />LtCNV``_C[0wwFo6{U.9 @n!MJ$ !aU)@f1c#~|(EÂغ 8a<(}V+:?3H?|4xkgYYjٵ:D+)ъΟ;!V  O@pW:P1 cW.=VS΅c *6>\'x-P 1=ԸUՌ-kp&ܶDRg{)ÂDx&Pv$WZU [ޥH.X[H 󩐶eO~[/{3li#+DkT5ݫÐB~;l]6zU_ Q0~&fV^)d ppW~<`5ޮxje^TE)+1IIU16]drbvD,߀NU"e5_[{рg߽,6k|N~c{+{sG͍ݭݬcBS0h|s>R,U/m@؟;@%5 1@wŴW&Sr#u>0 -@Ad^i 6X !40d 5,"5RGCk ZSlu{o{}1GHާZЛ# \ښ_ AH01Wz۵O]〰I^AeABrmx8x'@4n@c#;Pq%0ѝ|8ܒlQ;lv< _d8Ra B&*gJ mn'+at!"zXcf?-d+3lD#`kxt6t;i&rR$U8qrY1 S90g'| CZtm擴Z#'ښAuZ܊E:z3?&]E!OJ i8lSڴ[J98l3iI)ͦ@U @2xy@~eo5X[)=HGV9GQIÒXЩ ^PQfd]UB;Y:kEBn{mC{ڎC>1b]jRbV/13T8'~ۖj8~Q9X]fȘ_A/+V1ᤸK`g7BZ,[U~~+LlUa4}YG@Sq?|╦cUN Dlת$S̎sy1s4g`P6ULLL(uֶ6|QV1zuB/"MOݝ4N V($d "hd[Zj;>7 R嚁kT1@8ԧ#w4i c'>"kSYJ9íP@8Z6^C!no,E{zEucڷBks[ʌ5ATInBRk[ocޛuK("T^G{ʹzfEJ1{F6/dl?z:7ά""knzRVR)4K6ZE+lVVɖCi&"%Glɴ" u8-=0dI)5Qj,qafv#YJ=ь"AEjxw6{s̍&.gLfGcvɘZ!IQQ4\sNQkriS ~en΃iVƲ_!W坃j V5[דl]#7%[9)NHdNֆuP-&;^zuˎ CODjZf[V`-I}LzkY#Ĺ |I5!bKo5q#x3$wx"崢Q  !drY e8wFBDRD$MԚUX8/nɠl^ 5C-?k )ɱl >+*xx7JOsNNv$H 7wrf~GC/EڟmW%m+~G~8Y2\Y--aZ?]9\[5 8n Gs BGȋg?DZ"w(^CPk%3Oʁʩʓ*HR u*UUejj&j,eUC=V L$Fc0Xql{ +fpָ>ggk>o 0) ]o'_¤jjo`:ٕ)wRb_f3M8 {Ýwͷy b aTIȒzxK:Ů"[!}j.(dZ{MpBUȳh8_*nbgWh%&d"'?p" WEdž;$Ik)VV + fxrA b+7|=8cḀAJTx93A(`$UsUxMF"OP_c<˖1r TNͺZZsi* ԙFfF'):߼|hզ3.0lp=*dAMիv&CJ ?rT ,""Ջ(x~蚔{nNs&G)p5l:k4?,$Rv۰sW܅ kEr{6ET ҋ?IX7Ij_VcÍd_a՜t,6ӪVd9Ba=$+IFN%UpR@}5 ̰K}MQ"d7v>q8hB[0Dޯ|): }RB2HA5Zny~'^?.. 2,^cZIv=zkO4ko>ъtxӉ kZ<5<5B"2x6 RIJ>Zl H{p o\OvvyۍE):h6=a;PEܪ#bpg;QKlAP% OY͗qv<ʬq }bK|iuaYF5!BھVWr]^t†cS Gg'(f+\+&&p?"${~/ˌLi::{i>Y@%pGUAH#O;Iy㹮Z F,G0Oj(_ )/DlqhK-ymz Go+rZmty<6mi*_A›zt):Ud)rĂQ]zdl6s6G:%Ӄ!e;sJkIa(-9)Z}E3!I T'&-RބH-ʁΪҗ|숉q\°(N# jN !ՄJb/ћ˂S'Y.a"T9R}_fPi'?r]#+}GлRrI,+xLoDj1pZ23NC*g5Sb^-=h%ʕVwdy.&jUoP-Pi!շqXmxjԖYGR5Ӽ>Ff ݬP$>XM Cg6i {Өg"(IXD܉=`sw ; :`n$Nkwj\n3)II~l"!1/D2,Y~ԑ-q&r4"bV}udЖPΆJxFnaY:u' Ǖ5 FZd00rmʪkn_^qq$7d;۶#"εbۙ站㐒ؗjσ #fdgHZw=9U_ Vn.W>7MZ'lvÈR\f^+Šժg:pKfɐqeed2Cn;TCzugFh!ECBf}@SP qDr{ :TOL"1HN 2H@;^/X‡j>!O+Y(Ȭ8/ 47B5AAg_s0#%bI ++z$ӁhSDjmOMn`av\Hb[I)MKJY+|~,p'ҊBk:܉^K%IO :rWIkFU/GT$E%)ɐ>yrô+9 , .. 5V(jh(^~ن@%)ʠCwM^aӚܡb,:T,Qo@{aVicC KnͬDPY&h4^7/V#,t)b 2 a".SOϟqEڞJYpB.h^TJR K+j qt{ װMc` $ ݲ s;˫)ʍ%^mGZ^"Tv]9X/*h3` Ȃ%.{YϩCE[ɪڛD~ Fs~uf:2c? -ȽIkӪd:"N2g-(+dOmۋ/^)ӨLAݢ9tI`LYr~0XF`QjOCY_WiL*nDIہg{>}8I$"nZUB 7MǦٌ}"欛j4?e8+;(TҢ2.6O.k%-k0Z,RK166 *N[5`㸤2O ^?Z d+RV~OLc͈᎜}٠HĪejztMLHS]N(!嚭RHF9-oOFCZ7#P%x_UItl 7Z1sBG&.@$W`׆4-sLsG[oj5FXl̰Mp6 O`B6WY {A)qW':$uZ#Ex\1{T+iSX8PU*F"1eǜ/SwP59 /<#IOmg "N$BaIܵa8.d|5GqB:M/Jʎx:$(|O|!o~P~>s'7QwD^;|;65;cO,I(xY\ {t ^1va?QrȪjS"u%iL}$pJn1ׅ(Bi(DbR@~ʲNRFzȞͺ]WCBF?oY67,B304j4[h>cʰ K`pvm U֮6E>ZI9Zu\bH%f=F"H4^ !EjrHXH6YDꃽ90\(XEn.sX-I}S* 0e kmUc9 t+MfY*f`;,]˲CXyqC`z i@HS9a#M-Bo [׬3IQ ҫ.JA3ᮘ'lڍP ˶q4+ۗ\#]yhXں&2{D3`L'Mqpd$pp72޹rhWL.RP*Ntgem R- e, U&LQ8|$? ̿su :e ҵxzl귎liCjq{jl"< D!"ﴛv`I#CXI6_HZ(9 j68Qq $D,;i mh0}ZV"<8;8e-J:Hfr(F4)UR ޼e2YwV8xK0VR`)3cRiУ N"~ FO ObdlAa6 ܰڄ!Uo2tF (U&BD&xo^nyҭV耕?pQ]kA]qlk9)=2)\)) x(q8 +xkg)ФX0A qP\HrӰ`}O! Cvl "ɔ(^z*؎µdثe;9gў~CjSpnD@EYvS;IrϞ@$M[JYv Fe,_Ȱ?$4 TF/po1Y;9~8䖗œY xbzyx0re(uuR)H:VzOk1]GP35i*4![*[ptzs]G>F/Z@fup֮d 񚳟zJÅCF9$XhVoC B4[+Gъw( ~R<{zSn~Nh{ԛ\W㾱[?8LJNV6{'ŴwI,̱,wYLY,&ȝ&1b 63^ij{"%$a{\_ŏzPXuv`'g!&l4,&Ҕ(dRWx"^`Ѩ^NU( 7kE.-Xq0ř~vi4}4e>n#m˸`4B X6#[E5{dA.\9A#)m8tK+fso=ݯrk"83ì lMmp2ē?B· G+B{8a/'fDN}bTRy@i5Ꞃ@laK6܉և 5[y8SQE^ X1OR6- ܤ,Ѝ# cWTq .5Kڎ*Iwi/BBQ!YH@Xe\~AsLoţ9yCa6n~OVA五@Yў.>6*ATBoe@KE밾 ݇'%WIf KS:#gM EScw 9WD@J0 Ppe{haYzI? څdLet4Y20^/Q(Wzs+A1 z,3TPp_ wW~rhl{>da=G]CͣTuu'a3|WR tq'>}]z)T3A0d D3gvJڭh)pNpV!F\;}߂p }%w@'g GW`+(68}moc w!GZB"븪IRΗ^v+k(hAU5&C<b #&r<&A [}f,pwQT',cIyVLC^FBO_\GvX]Q-:t*5tZ06U+W/k r3v&VYZ˪'hw3*J"ϫ1bX+^fOn =hzf39N&F]2WtA3G,7zm{LE !L_#UQRҶ6iʘ5^Yb D=UQT՜|=&:CR$EJY"߿ (e,b:Q <[AlANk:rO#)2NX,Rz9S:3n@kh5)%x}c +V-+K˽MER?sy8]O&IN |kZ;9EPwa%,~uhs&"20ȣG!ͱLj F,~#AZy6 lߦZO; ˿wCȱOC=lƌ"jְ~Ý$_@>@q3_koƤq3Md5V'o~#xK{>Do8c}_rt<A1z'd#S&hnvi,68Q+W-˹0eS6ɐ00Ϡ6,pUև/Hr͌3ͽ6lު '-rYBF{:]PmAI`4dH. _ϟZ2'ﯟ}z;Ԉ }K\ܪhpc eIfb-ݯ5?R=$a b̲<-.@ U*%FnNʹYa֛)tk"(U,—3#C5- p%{Y$b3. <2 !|ǟGNx!X(HT^#Ɍ.݉4Lk='ʤ)n2Kf#Z42WǐHߺU} fVZ[vZIM,ub4zaejKZ۝FIqq7"*~7⨾|Y;iԖ>|GkCQ;;5lqnKb,T<=sgG^6((@|R5Уs=cOp\ uZGh;ڌh9FȪ"s{?Q[55_C}V񓥌( lO!|vH\:/g0~;Bs`ʅ:& |nH;;j=iYOjO(zs]<^;nCi{c&v~IJַ݀pmz{LЄm̫j[~9w|YȠuPm hC*Mdz|R\ޜaFr:GڐRizGAҀXVk$zFۉ!8;Dv^8(9*3Lj;f!b/`LM8hF4 Teut8; 6&'Go{0︆X?q'= dqa70b7A^n.H`9`-r9vޞn|\af*emf?^8o[j{{&'!0o{` kήsDL.FY>pKwI"and=5 Wu0ȏz$Bؕ5GkO@ m<L(V31LQqf?c4&0lZ4aj>9nM Ø!nx6υ;=eU=1jާ^O`aIKJBGZ G#&uuJMdWYl5+ZU@4J5;*^4e'Z\7{d<ܬx1#뤛&\[Ukݫ)N&QZ~TNz(lcEh}P= Ph C<.z0@aXHBQ`IUbfk, U2)'10y M@4ׅZ};%POi(<&BCic&+;6A1˙H"H)nθu?KH@ %=.LM^Zp8  BϫR ²CO1R' K(`3 1jD>iFx2V6pyPl J9`c#vtEw|R=.WtM]) T"E_d )$;(v`v/G{QI {6p=AޯeXw7!9{9{uWsm$LH8aMUދw Kpé˔F%_PBJky7oDE J)\AFV*4[~ qݓ`3Ww JϻB[f|?z3MHID}E/gweYOHR:ARwm;Ke'kO_ {N1i}wLml]iL+@R$[S^= - ͮZZ?VUdaYKBG )Il4y!4Ȓţ@q]A,j-}q*"ZK)^?^%7l]gsRcw*FLͤUDakYߐwB7Bo>驕 M傥tTv~"oŧ!͋m>"/o6Hn v:pG@ADG$F:>7Pg]仗 r(9ꜣ p6',x @&)5(RL縠19rk`Oˑ< CӨ|̢h-vb+$ .HAY(YP5Jf4s<tȠJVeFIbqDb*S4C:KR_jnwVഒy##Чs)*[Ew.}ƫ9>|Wke;.Ym)&7#Hty@GKqw͐8["yY>@):P&R]1eSY՛G w{!)i2Wp( [1G' $?*Rf ?zm_|nU8QeO kʀ' kYW<,rlVA0V Hݠ[„a ydTp4ZOFEH,& 6Jޠ,qm&j't;ގAP`oëqVP ? [HME"Mބw[r /߸^'nwq4 P,G0`63unuēu2dbם0n DA @2Zŋ;K(^z5hߖ(J iZ9lg4x$Hm`T{C0ˇq` &Bԙ=V wh{Csڍr>kZ` [c fa\&Xc=>@Ym/O[ ,P&;(_~gU1Bkm7Ls-o~@33lK7ݖYcg 5V쾎 YrŬ3{y~gO<~{wܾukW[F=˗.^8-=9>:Q'5ShXZI$txx7B ,3x=/ڜ׻dI_Λ\X!Z(t ;L@ n /JyE"g)IA% eΰu O2Xt Gd}"ٺDTMV]iS\0j;0Z , ) #)zA+wD%$G>~4Ee-vJWζ8;t Iȁ5 k ^[ xgȓwH,c`O4`!\b ހ$H ;Y"6aMhuP4\M*U(7qx~uNJc macStX]58t 0 edbP,z{AҰsCDrMtBhS`q%_0Al3Qt}F%P[È+`y«;W q, (=IՑ"0q9.'AfLiߐ栰Q:L F`hT)30Jt(9D1~kxq-CDU8?yEV S n~T~IM .XV 7 ‰/c ! H/&xe tF_9Kyuid,jr//eV)Ϳ=1oa2537&A`"ޭxÑछꏙFB]''fb yڦ=]W3eP2-@n`Z2N,x`ЋgOTN>]{8ϹS\@*ɳgaߤ)3?_P/Tc\}k?ޖntǟ!.1b^eӭoԞ_K~=?ѵ1ˮ] GNU6m3RÞ61%Qbbby @7tWKN%%K [&1|֒83 mgKr>- aL/J}S`:C+z^WƘ_>yo2#/obLhӟt4^_/`)Wo6'9=+nM9EzAlu*$ws 7в+ʰjr[˦8x;#=kX=d?R3һYaOfOZI٨̀]zhx񰽧`FޓrIڂ(Igr5zn 1uc_b9TKg?~k),gADh?ºs,Tqq0_n^Da覦~=,,T <&8˿>S'9L3{#!{u C74㍾v7 <ֻ_`O?|!͗!F7/m}p+'K/>t_ʼn?vĪY5b?Pc4ZG?3LTw*@^`0- [U%8{a}^WW ,V^cytyp(c`46%I{4p)`fڸiacbO'!U^iܞ-ub)gm[䚸 Ns}+勸QMkt c&NSNK3elHdDN$N>sTq-e+xN8caXt sC V?<$Aެ >Ugrq;mv8d*yL(hW[F KcG#>P91ai˰u`Oŏ1CuE\s 9j6ԏfh5}yZ1>D_985k%T[-7kabSЩP@ ?OaPK*\'Oq44Wh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-latin-ext.woff2nu[wOF24< &?HVARU`?STAT '+8 /V x8 0H6$   g5iqެ/cnsNفtR{#O9*cIPp#$Ͱ^ƍ`h@4gRN8gi5.C.GnɵhfK90iv&v )t՛K n,@EɝM)=P`|觠tɂܒD³G0fVO^IjhW\/R3CK]&jչP-ᱴQwF"(2O йn`^Zka ^#yqяOzZZq[1C墽5FTK)!-ugJZw%>D4@MkERPQ P$j]Fm.\D]{`N+%Y8ԤIv% ] ڱL~rPrBW&A"g|ܪ>Rft;eE%GA4@ Iιo=kvSfBGDIQT@Tў]y"k;z+^WU3{zxǻ{/*损~fmnn HJ R"3?{dIELcMS'  { VoV $è&Խc=4{&dj%->44ߗR/|JcC@BA9'lʀQHRWo'(@sRQ)}/̻&%đP};"XB̢]bAȃZjM8j|K{VI6&BL'Duov,pklpTRV`dyal?#˻ F O҇'+0?H! IQTSK[h{M_Zˉ(uܱWlq) e|Z%!nJؽ.*T?3A)ʁt$%'$#7G-M)4+2ZoB}6SGE?6<w:9Ј6MDA}Y"iå{T{ʕ؄U ѣ>G|7Zm풏HBޘOZP((v]?ˍ͍Jx-{7at2I\a ' 999<{5t| 3eMd1?`l'[VCl4 &N<a#[K8SwPy.@^Hw Ujv 4ǝXDAOi8l4- r H" up!$^ퟴNR@+h8Ӿ g8PI![D^MݬMFD'τs%#&S3=ٻ!?@ F{ҏYŦ|&m§kFܘa&}/ /D0A q=kWGP<a +(ď 0@*ߘƞ9{sbqx,O>p޽v _P`F~XϕiմoGkK PŸsD b@V \Uhf ` olԭ`v FN gx#$^6sMcc0Ni=y(h %8R'Vӆν&<-Ja 6@ )Qb|N#cCpl'"4vIRUb2|'F*܂VZ$BO݂n`_aSA og͇ӹ$|zn/@{6t"]B \ͅV6t$%AT H b. [F+2J$ Siɰtuhྋr'~OͰL+oۚߜmm[.J~yXl#bݐ1I"0%R͓eԚ4_z-Y}^LTbu8}M{hE呍j8A*BTvꄮkJR@(s!Q6qGʄ:G=-.E5 Z]PuMŦs<)Mшo}hQV cg543aC3CFhly'~=;.|v4}{ 3F6TZLM}0CH6SzgԸ(Cx￷fFlic9 tp&&\h:7,fT$id<nݲY3rP/Z.Ix,F$ `zx:.,_ (LVz!;C8,^³è#XZojvąWB7 &<5B00}rWJu_%{h@>cj.&86M¯v/uQwlYumɇct+*ERN qFw+g ۛ Ή2φ%y\;2a.yYٲj%$xFr2%_ ) }ڮiN b'7Y% ~bp6OvLyI) eG JIm73ɼ ra<݃ޯT+~XC!hd*(O8OD[in[ 5l~lD#U KAOo&?ͪq}ڰA)I 45zƔkaTݠd%6Xܛs;g6/ͷ eҞwQ1`[|n q}D>rÅ $g]sMgh3"衬G|i[޿?  F{`S7|.瑚.ڵ[y\\v=زAkTȚg3n`3&yyڈDͣѻZeK=I@M|\Ϟ`㗺Ԫ"/}&\/dìt,^]B=fNĹLxZ3i68tUl`1 nz~ET$|XNC:Ev$3c=lurLu*9n;r̝) nJ1 ~P!Bki .y0]a(`XAϹ?hGvk> #gyv* ?*X^F 1.q\I݇ za ­,2¤9HM0,A&pE5X_e"妹&q-W!aCD-SidhTNUd a2j~Ƀ3i*(3\V -VZB ^pZ*l;R\A~")hY2V9x1Q@huX#Qm.[NBW+x$ȉ$v=!@~ml 7JjN&W:tOSr"rSS/ OРPؐ6=C߿hۡaxn:6#zJr&$sePwYQ'wu>N=br$xjE_~$yic%syM#WR,*+Rt_\@HW%s{ۼ `!:8aYBBp<;[X T~0.U_DiQzp<9:4A >VQK$j>ķ;xX?*r't*I;<:u8G;88h:sDJLoLjhu@uh lC$}^Wz<t 0}>]3Ki~Icӝ93`;]UxKЮy\|[~9iZmR[:-&w*4]4Y7tp~/< Y # CDP3]~&>etxrQM [ٲ 0 -q?)U^>G$ :yKN_пYznfx)h[ iWCC.ZQDϠˤ.D8zĵiB}ۈ*zC{lR9oψg(g?{j8!V=ȚI=oqKG7.1Dz7YF#*w=@1u'.' 9酓,lg~\})wH}݅;prJ1]c}I._ǹ(U< 8fUn]ٽ@P SQKxj4°!]o==kXٳB]n|t '&BTE'}Aƥ;<YnV&xG{9 z1s#,T? jԄCm~SjD̹pSٰ8e|"e]*+1c=wLWFUIF2 i%ly=,eupU4[QKvJurvM}VAaC)BH O`p#?,< `r{BbOU;^ rWzlA.TV6[?EߦEgwtfT֟>iuHUݻ*w6VHݑk!/>6E*.uT6VJjytE6<1|:ՅxCpH2Ӛy) ýMU{mN @b`~A >F }Z^j/?H?5pLl;q ~;ܟX4'VATkFGr:[ o95UrJѮ,9B$B-YBPF4+(BمyYjأVNwHZvAJjDDs(K t9x Sf98#"7тh/p0 wQ۠%5&$ץMcjJF%J|:6%pKt K0K$~YEێ3$Tx..Noc2qIsInV 9X>MTϽ> H[m(]59c8't3纤aIIg;zS2b'DWBy1zj0$ALc_o!ڒǗ3eꌴLu%JtAb ]A0trkZ,1%nc&xo.d:7[묞fp %;2ܛjcLqԅ.Ƥ,69p4ҍ{bpR=[SSk#RتqXw_E/k +u QWe scxD7Vʭ,>ԦS +NvNtE {Ai+znt)՝b[S?gLeȣ[}ͼ*eMɏaMV}2)N9/>([C6U!AiP7=y]~xَc"Y3NbӔ'Z[* n&VTcK$-gB ^C{:V5Ve)[ rmfeʅqD$Ԉ 7\~^,l.;@ؖUS+J-?6߬} dICΞͲe$3?pAF0y 15ϱ8*z-! {Mlf!us&YS6KUWRe;vDп%)c&Kہ֝oE;~^l#^Z(@ m(ZJ3KͶh~ĊJif~NUwc4SrErw}#3bt%QHdy-<=..DJDF7ڵ%e,uzG*Duv`.mY^+*aWfS-]g5U&ц1њ-=ӯ0Cp!FlrY3L)ڴu2S!8(:U# w, a9pk`A4{ 8}|'7=N3&ΛG v Tm؆CR F.4!im[J#[}UJ]>:ڽdŌJ}JgxsOi&+_?9[]{: B-[ěOu#0#3( t3?|.O>ۢE9]o_(i^ՖmEN?$mhmx1<=(W%i> Jjg$J,ueβq<ʼny4f Rz7w|$*y&,+?亐*TvӒK NgNHrBXϴ,~CJ^q {fj#6qOޑk3OvEy<50׵1) a2 Ev9tɱަ51ڋ>@fw1鹀Soi1zͽy*ܔ,CZ/:Ѯ* ͦsyGW^%`(%G;JWY FUTl{cCBQ+_ɶW\+ w߷gvҸfDn.91~WL+VK µ` H#;AF,;W|q dlJWjzY1ꓭ#Q\fKįk" fj<7o=0oY"^v5jDV{oL ٖvm^sf~ªrrs3|蹓4ӟ -ʯjf;`ɷY4h nv `UdwCpqiU$ڻY?n||͂YrݒZ7SB)m6g&Ýuŕp3 M'(m/ N$k==, bR*tiO\dExmeh1 t#ZWX%-ij * &pC e?iX'<^U aT52{"-)ݏS{h8G\:pu9-2-f+.7Eyq&W:(gf k [ zAˊV7tVs`1KϋGxT' *pP)D(? ^pFp@_9(>` ^:jrGҙ{=,ynyRrYu>J*A95bR)V Ue=AhM.zZ`X_0F - aMT}JUQzxvQV+ & yI9ܧ3JgJ3!HGKшb[ӈd[f%Y !33i]BUzmWQ|㯳Ymi^quBTb; _* Q [APO:}rwU()jgtc~Q} <)\Y! УGЛ_-1£'/rgIxnAGsq`Z,i=d(,H Vdˋ>dk2y8#np_htn~חB8b7/_ȌIOm琊ej䮞MN$dVƋ3}.W; ;k_+@gAV%~RB2g`bm$s͓on,:~ o?IF3?$f]{Ϭ:Քt-} 3p)_ 6L3ȇZ >w5zobª[=K&JP YevKm6KL AjkWl3Dg0flDI]|b`\ Ŭ݋1Jv~΅J"ļy Y1K9F+VA._)/ Bs=(TLbi1J';uȬ f6= 7k.E}O+Z XNVB4GZ)j7ykA@F6 P]LY)?D]z>ZvW (xQOvki-D' W8mX{܀kH/mʳ5je03˥ZٻN 7fD=G$\B sP'm õD믩 ^Uz, /,c9LYUd5FŐD.̗ l'cۃN}@@XweyVB5Dk5Zq9b\KE2өuvm-0;Ӝ.y'ϓ'v7^NU0[+,eWV$l3%!h_0hnmBDQK' Xk RQיx嬒$_Ұh&83[@]xAQ,׵8SV~x[ 5!sg¨M9ǸΔk`TE+DK М$.8>W-m.;4}D{Bjk&Ddædom9u _}txiLHjgoN$Ok{4wp*<nG~Um!IH.RR,&8&/j M@st! 3Y\la&0, ʱVlv}¹48;7=pbߋ?? A.ua"U $IQ$ )TK!.^&p2$Vryq栃A炞)0J %RNlRRS,j%uL^i  =z-W EӚhoѤaڰɰjpJl;BQ1q"H($ȸ3L̬gebyD[11c^Ls '4p\Ü>r,0N\ƍJ9Zw##/J'LDCޤ$Wѣ=ˀ846"գI+e>LJ(aYIBbq``~Ca;K|^UQtq3 ;] s =DCkjhL,K ..O=6 YCa‘ȋ|3!dm*M)L!2h%J[5 >nqFu,[VM*0eh'+1:|e_LOw'gU9|@ U_;Ơ g'KˆJ .hA9ՄK+A>J [,Ml^v 1.W jvİa\l3X(fͽ`>tE[>PM[3U;r B ]߃MGc) ^\MfxMq{ilD;!]D 9KMZ.ms% ?K-GD-M] B +]~ߌ ^l_Tb='n WwTT{z{$1 DpР:7mCO#\っ 1 |4 jۉ|6Q0j7W4^&qrpKjبxwdW):pAZ6rmr`om.te)[|Ͳ$dDʨWbx49obBصVE@א5=c"#P_ jwFU*abv?y|eBo=D`ߊ#C[/o vQF)=&y^TD,@C!/Ѳ0 2Α^ƋkGmh!`1#ɌùzBJ!aب1lAo~0$ƵPIt0 f(Mߋbcһ 9!U l2f+=;Gywh<뫛úǫ([: 1ne'e֕2MHLpgfF? <{}DTrSÀʲSIcfr Z4JC;<`F7X1$&ՠ(fzJl9Y,v1r1N;!}c맶,?}v<T ^VvZFf7N#q٦oF[=nOzWhlƃzk/Ȑni s6$d6OO NjY3m QxW( $Am\K"V}fP"^^h%-=ō!sLnsu>3&L;x*}Zr܄:x쮘?b]H+։ELcV:VrZK2Vi6>pTH-ۧ|ai 'ǠycDEe($!/OzŨ0+Y![qR :rgW_CQ6tcdLa),8N)Qț-RH0nPkq,0TLNrl2 0ޣ.tp_X\u1a֫sh!swdqpUhmc}{z)W2[-KHy^2rk3>+ '-2^u?9ٷjiNrs μrObs7!oNs,#x7S;Ė!Z J GnB$oS4&S&ipɪN!s9Dh= 40`D0zVkW2y:=jف.8_͸ GO,뎣~z֜ +J8jRM0/MsݨIAYbNjd6t"&9pR^ ϣ,b'D&,oGGgs"AVS i :?m2vr\{APJF{UB) lNd'1 TwD(2%eO_9ށzFmUb*n5o"jz(w#9SfspXoH;Q@UC\k1ޘ0@HQLgdZUiQ/eA@ġJDgF4Lvya8HEG0ƸJwH{M1l4Ujh`Xmgv[ \Ȳn:"K{6%Ď8"" -b{s?u6Pfs-J nAtX _)uP+2)Ҳ >z~= ,B}p/:zc?QЫh.rӥ3=ÝI~o&Ƚ.Tӽk w@dePEՀFR;G*$HP {E_R;,o/TYQFa-TTИAFK/rk@4ɸH9 sgjmHT$EO#i[H*KW֥ȏnt+,Z"QZ-t̑t ~oIuxlE! n˿.uĕ[I˱Y!?"sx`j1MKȆB07&qXL2؞S Ӵ!yx1:$XFJ Β'B3]岌<)@jYYy\Vij |sG*[yzjܨn~). ,K]jn}g*ΰPҺ%ɄLxUΪj\XheKaG~!J4 x1VZ2tI2Js ] cRL2JSSGg]bӝv 92EIyr{YPoW .9xmr9E#gەy>=o?3a߭7+B .Gp(JL_ pJIg~-I:0-iXX2Vz :(Q zVԱɦ'5?TcrZOx.;ط}W RvJ3e ġG hCyZUױ&&!yten___X_Yq%tyQS)y L>y*MԘl6[&ɅRbhYQuls(!N@֋<%laa٠y"Q }hamK/Ǫ x7.m" >.:$U7{чm{A贈 \xʿ4 ci3T(0>HlRC)îz~ERMKK}C Rs ]K]UCt^-x@5G9V5m6u`D rc# 4J F0YFdW-, -*ZK:.}SѩHtԀ7WԳD톒K`Uk[b$f{<4uhkRx\e-d&}i H^k tyaw-SLxXd+. ^FuM^hcR<V`M3j8ƺ}$B"pD(hi>׏ㆸx:3ncA5K}UU٦z^`1?-̙VǸn\O6-f}vj}aDbe3aFʹ}?Ⱥ-@;*6b `B7e5`@9V%xa`Y{O4HD :WA7qSi.MwV&'Qh+ ްhn';f% D0_%ĻrXǜ$ өsd|aDpl*iaI㵩/`=ƌ7bO :嚹wLS/֮"v)2N 4_3X!Cn-%n d87yxoA)]49+;ņBkQTj۾C[& dH\ -C>L"؈>:tCn.=d+ SxBJfQg Jg;F(Db0ªм( g2L ,N2رVitM9R$bӃkp!%*.DcNj*LWLXByD2S(/s&s;7ںiHAӊDkZ͐cݩ((Mg>"W6nVAF[aJ5mr~_Zńbʚ>ycDhReL"qmV?|y$ 38/胇>VT5^JU<\”FBp /.#Z<>/E؝&}@be`l58~Dr>J3ȐiǷr.NʗIU2yh BRNOVR9 Z)f:=4ՑDC4?6_A[D8KHNr 9A@ρ33Ct{W#UeIQ+ 6$B#{ IEK[jGNo;\IѣSTy$˒[^#kHNg1ޑ HӪJ2J}a5-\Q!Nτzlc)~}'!JOHgxVB2=|Uo{H dhF2Ĺ݆  𣾟aN  >EqC# :a:ot,ov!Wa=2h8ŶÉnx1rP&D[n`r _N3\9$hr{/pb1o\k00ryF}T(+`o$E{Xh)xek;& 9ju+6¨-Zm.Y*a{S15WeU@ =9ҭiEd|}{٭$΄Sfpr)j&j!4NIhZVJ*ED'B" HB9&%sD-j¥2L@ 3 5I/j^mFtڭhgTDITM?T U5GgY7AdEF?d?,I=3fbVK6Mo[#>qY;d"Ƚ5ioY _qXH+4L,ϔqP qNsgLGyej!צ;`#.XHPeV% vj(գxvcvߦWr< -+kϵ5- \~TrSrD?$BIN*yY"FZ Prm (A@Q*≂ BNUlDX%kWV<238@ֵ1<p:\P:cX09S%.;9ad4| `AE #:#gI|Zd㻬Q*SY $!J0 0+tqO##g/Df#RU0 Z=D\O*ZޥI X"`17wuawѠpoлmB0M ڽ(dA 8 v$2z#/}y;} Bpc}cL˔;02g $$vǖ @Y>fU=\(yLe: i_n+`*C9KfvR+]5' b3O~{#N9'l90&B ,k[-T*f?KogDN:km']GSvh ZIRf?D/gLe74*o-Vs1P5S;ZF;nV]oGQyk%inȹ-#Ov w4c3h72R ^_qJV<ɢU ue^ljDA̖6|n9:t ޝ6u}A)g6*ZI̯>qŖz: 9hH4/ _.A+Uө:d'$ /hC+]M.Ώ` IӼN~o2±dN}5Z^SۥPtv|2%F ɸǘfeL1X92OeJ??q ;[h&.玌x8=kOKԣs5#wiy>Ƨ~W,jO(pkEt& H>!y%jy>\tXV:V*k{;*<ܨ^zRn;lvb{>5˂_;o<;7?P#OZkNf #ر[mj:T5-W/ qALi3ے,:Ui r&.A+p0Lzy-y#@;RGz1zh50Fmɮ|&l[kqZ:rHd2E@s,[V.%+gDw2͌-æb>~,yw/'hCK>83B@JG' G5}.q/, oU{=/͵cgt])$,siN:D ܆6g٬>OUq.) BfolmFBA@ac;< ]|{.b6- n|6^c膯%2v)vlAkOՌ]3AQףmFR.OM-g0'l=f?y^o5_qг, r4%N.FPgRHH ?~v =,~teLw;,(Kbwg`|:V>i|bY{Ķ 59&N3!LFM$Om|eاFLdǒ\ mĦJp, yrsi-X,GQ\m⿑,4]`5ᔰlzP~ɜgS법|{Uc۱l|e6"pMd"#kփ[*ӹh`ж{:=TY{o"3 ™7'2`:̿xM!@YrCw*xdbP:Ro hFq0jcH)|wq/p" R >D@#917WdЎL"$82TG1:8@1j_FKNUoa}/C(C{`H$3WRCY!sau4vXm~ldfݫH2'Hau3/~B/YxA+}eG"!OTLj2q !Nb9#*f%nrS5&3Q/ n2:+O)aCSg؋P~p [Љ}6.,`,+ban>8: PW+F]lnh`|,ԅ{hA+׌dDӜ7lOi( "mΉ^:/y)eofNdw_i1k\t^=Xg4ɔgx7tGG61 {-x(&<}19-I>W{E|=$~<9pfg cBF@BM>X3%' 6WVY:m5E31h3lxEgX/̳U_;JE=O )es7]2 7ވ$(xNۊpw6Pe1)^H z~*É~(*N|4Ovy=Ə4_pF;ࢮ>HduO< ܦkw1{٥r^b~1bUR= Cn)0,nAjZꗚKzEy$0uk m[Ҍ!ȸYKoimqt`) u'fzry (w*,iMl7WU Pke7-5Ru?-o|ɄR O'fεS.M83PI<ՅuUo| 0w@;1I3DZ 脶!n`(!~@01!R[[{PDkO$*E(hHUF)H&a )6#F 2EGK>꭛/*a:3 WY.J̌jo7~>_ic)&Z$ ++ #KV* DHA~_I^n}/Fx{f2v^Chtbsor¿<"~U\QK#W2ɨIM6 . :+>, 묅ԄMiPm8 $ʟ~HtݠlJXƫ!FggrՒ٠ↈDs"سbOSS鍲lS*tdW70iuc xGHÉ|URťi.rMT: L@ '2#F̸nbL ㆤ q?1S:H< (i4{/q|q:Z) }ik4gC T)ZF\ ĽRJFe#ՠ*h%̒XxZ"l\]RG~V Eٌ4^g[,)Ѝhh,z-@0:-Ml 4ŏ:!tITpASR-̕ (D3ee5bӽ O Hj>'A'HO[.5vN1\.z'աgZ} [cr>x_OV]SYӑ-z-94 mFm`T VYJZwa=S*"GRLƸ}w~ :%Q+ 9s&>}ZH.'0ƾTfTԈ\FPbuۯ q&h^6f}%,JU?:IN(6S̚_>fM-MUAmۺ.Ujb 08軛_a4Ă.1jQ* z(YHQ@*ur:PL8Z)b>YವP/RS#XBCK @,,yLxVv.,'K&[T/'`<牪xm *ѻޕ:w^?]_jQ7L/Fa]MPbVNK2R8]ebrIܘ/DŽB䄒v뇄 lטWRul"Rk' Q4}΃ Ze;Dը}!0/K@A/=[0aR82oloMMQQlw+b='쿕 /b?)'|9NQw/nY\x\Z+i[~$^LiX+Bο{rDZP&̌IƳ| -QT9xJDÎ 2D_ v}.~;ƠJaA] z'0 tM(r;}^Y1ZTdh~Y ;Jq3I)$\3>h/Y`~m:jP!ۖ[gPvfn/z@8Z$Gjlzy&pSy9ȆzL{1H'*cDqQ\lFв^*]&RhrEoTH͋y IJ)q5*-Gn|uOgz޾NC#*1OJXb͑ZNC7tè#U nh<geACx] U|;agRH98ۉL]xiU/T tFA+iB6!($87HR_nk5_md,aA 3Q L܊g4XE)+\ hXY>h0Ge1[=x|f;zhqmP3rzf+ )E+6&(Nʐl8};}΄cjqN5 APQmv] nCjB9dP84pom!ʜCW 1{Ӷog¾8/Tr!vPr|(Jun..4k! T )i?cA. S#d{k๣ġv,f\H: (y0Wa^( 2sJ$y )y11 g̫@prؽ`{:W]k.&}wKm4B"_֛o&Q|I+cc<8m IE٨S`)HᩰQ'|E`# qDQ_|F [ɧ?8F ֠87"xAQ QllbC8. <qd/ڴ|Rsg/Ű`[{7cDJtD~0*෉x<# &LX<$PL}:HIfV#P)c;PAB$ЦHzJtW~]HU^^/g>FŹ4ib(tLg!v/ƔЀH~?R}%ɾGiCY;iVed77@'~֨|20͔ U[4*I|ָ}g"4K| H,jYo19dPe U6D̪;BVzPjxlDP@$<%#2lacꤹ$9q--LilK9ݿhU9}!W+"aϟUeo AM }z=ˑza./o~~)3t:; {Z2_2Hc-礇$4.-$]>"w?oI^|T-)3&0[Ҡ(DtQ%pbNМF_ ˡXሺZ <44?OQ@r,}ՙ̧h4Z6T̫ZZ?2&j_D+Zwɦm8ˁuoti$ 8B |B*,GZw;D>BX!.[ufM_OxK$EQ 8j.Z -:=_-bGS-g{K(cJBpnaG8Fm; ΙڹcǢ0bmhܣkk?זg9 ╜&_(%ְ{i2ΡC ]u&DqBXTwjkb6[wQbIX^􀲁hp|?&Ui"a "L>hK嬤>=MkO )S[Jl6\ l2Z'E|,=OVp&?J W9Db &J`%_Ԛkw1ZA`E)9Y5^iu="m^9ٱbŅBԪps`o (r,iqo8Gh(^ m,ˊ:d⽅9P1Wa0LuiSYgD̕".H`~خ+_{'/NWFvЂiγSRZy7݃ HZ/k(Tn=6aL!SE jZ-JA`eq|UD7F-宩6aH7ڧwQcv5[uw;'`@z_xl@_?CW?E1 <&FFe#سL+I)z釪Ӽ 94jDb^)+Tof,ҝP'hS8w6}ndci.DLDy <(]M*W.@ !1內 6rc=?P^b#qhU`ϥFqtnM:-b*փ5XCŏ` %Uj7/@懷MRXyR2('ƕZ9sýag!1Џ^np=ܕ>mv =݌z5G:Go^}=3l?69kq`Ta%^6 a墅g'^ +|g{}W}hKr9]u%3&q,q^c,7~k Acw C"⴨t7}&3R)x%O|ӵpm2:38+ n^f.}+lACO,ȐN؇^3G?X%b^^&f\ Z)'>&,5#6 ETO$~6՘{8jS{Vyh )J 0*bRjH ӢLu\TTPx_E[)+Sŭt">h'^82]u\G'x !]1I /T$j7QjK*LR/!c5qy>lp?u{\bϡind=?qC*{0⾳TE]jBϒ{{|o&m:oB&ċ8 I8n}黃B;DTP̘~ag11gʆ6FkL(1J%35߁){FA4݀-7bb]h36:(?Ŷo 6mCԻGD$I^۾+W|큸w%` aWXDibVW:OD"@ V,b1~'kPK*\%>>Mh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-hebrew.woff2nu[wOF2>p|>awDf?HVARE`?STAT$'4+| /V  $0 6$D ~ Qj%x`vR͛a@cfg$"8 =ni'$ Q.w0LG[њg7f[a& /c|m JX[;/ԑ2R%n?h~B/I"IdR1!%"[ +aݯ?i+[8/3x{zeYe[%Ŷ;V5I׎JtQ1}.fh݁S`FW{f6FU3UnD==}i)D e@F%#t6KN~ET 5-_!ӛCg!X =;UQf" {zb AZ%6wZ Lqiʻ dk†ڤq $YTp{"I[kS<$=~"X xb}F7WW,@BiK[o3&o ZfwLhXNZ,a쫾,y:jE>zrFbŲ)Uv`t\u#se_E]?(=$}%M>Q͐sH [R(4f8CʕyܺKWsow=9E(ug-I CZ&&l]$@V7!gl~Z,zeljsL-(f@(AG9 cQ,PYW֥[^^} [ Aopd @Ek|4~.7{K%CY ,՟Wjϫ2Soñw'=ēo|9W6UXC/]\N^<1vi޸h1qi˳ZTmwe&2}eKd)+&4.kE5ۯ 6:,M]u,wxVf$05JKمN`L4ij(MRAh8f8H+ ߂ (XB^8zF׸ D@@/TsvNphck)qGӔ5PB񚹕AiGSmԞzT?5[4]R#jv׵j亹* Jc-ȎK_oDqd//˔:9θ+sG3? eY;fD`TOj_h5Gbn?uO"ˈAjHkSv\ q=W[o:qzK}Ɵٗza?^o"&2mȴe:2=4S:l!b/D4_7!TIb;C@5%=A B1TK`zko9+%0\b}c\W?B(m8X,U7r{>>**d!l+Hj?lyvXҞ (]`.[M|}!K6P,52:֛Wb|^ Z ˕D r-j6:ko5>xq K ډWszЃ ׮D?gIɒ*84/Pnᵙ3M ~}hk=I("%H0RF7tCgGof2[/j RahzuvϾF/ѼGOr|DO>J;ˋ1>k|d7Mms)̛WV$JlI}+k٩kjtAtUR лox_jM}1OQ `eK`gY@ȑ, ("@|v"p?"RҚN@@ UA#z֙uy O<9ʐ8 bē\cgԠHA,񊝪?*eJ_} c{հ򖕷?Q?>-[y; 'sW_41hHb@"C?D a~ΐj,2M ,ԶeG]SPe &^ŢN'?a^V5i~1m6Uh̹:|a gݭF+}ώý#Q֢ش݊;xC&J p E`p>Nƣv-ul4tMUdIxezQX粙t*vn_+.ϯVG*[JIL`D궱A|6.ukٴ`T5pպ iDÌ1gg>w7]8Pࠎ2tQJ@mz؟2Q[["«doV]-yMƂh &6lv"7R쌨KVН.l$ ES+F8^* %T+I vk"Č )͂]󂡔U Ȍ JlJذ z*rtLGh}>XI(jEnxE8('Ứp;g&g <ފuud Οn7Hj 2 ۭ:Վx& bi@Qҋ»;m)\! x}: իP{9< Pfв N!cmakU:7(X_DN`LeGa_撫$_f<H15=q5][yN{$"qI_(+[T'XspwnArZgEi[V=n{ |9!^WGz9ҲR91 0WidF+,oͱ.ۭEpXQز\2ߤ#!hX<@{Z7]VԨ!_ta]J_g' = rĺ=N5ZnZzKr*[0M6ai 8&B:u]d͏uR`[Ha%CL{@kxTYv mO8`{DVk+8D[dj9%iŌa˥64مU;*[:<4#TNmNnqiA3DvXe 0!c0hlR.t2`H/vȞE0tyè͜J[CK~ۑ !J^ x#websvW=Q 1[՝zs.Z{Os.5-C f.u:ǖL  6zW  4(TgbH_HFK] 1 |}~9r @Z8^EC״|XpPjbg0u.8xՌBp{rJ*!Q.i dJk ș^SOf {g iwGu9]X*|}Db=LC˨ `]Emm:\qX EW-F4E-Tz >k ǁ7mVQ*Pea`J3t51/ѭpY= pnӍRz-w e1SHqRįi.-p˻;\cXhvM#d*Mnբ02𚡅 QfTa֤;tQ@ApGQIzgϊ^zUAm8LW4m5l4g4\5x$|ǽ?5.L)].jvh8Q E Nlq9@FԘ:Q ժRK`/^=Ql@ktIWaEʽ()NGW_~6"uP\jO+uZK {WeKZ//р ]SˎlHGzim3\%lwC;Pū2<Ӈ ܕ%n5>Q!T겺lY& (rZ$=ndXtZ q.*Vk 5x ⽆gҫ\GPyuAƇ\29y놫L&7? Rdo d&/TKI9+ɀUN.A2mO֧Uݰ05ܭN.!h4V xdN\Eb:8tkYNۜ\RG):k"*|r-m|XŎ !ĖRZ$xA#ЧrCRuId~3w2Gmx*י}7>.wjZv,ZkG)8p\S9=Zq%=[s /49"\}9[u&.Ǣb-^𙜡t|>(E|oH^NKNgqqJv3hM,jrD;ս u `&u_$1/[F֡iۭs-3uԪ@h} "2^Zw%Tĉ U ܮV}jggI/D(Nun m+ ݦ*i.W`>XZO"VsFhl=ȩ\e\3 cAdXw@jii"=RrQw6N`F@3S\.pIʤ})^L晓 YI#"ڲ90M` 6k'3P11֍l >/IZ6"ۨPdUwcU>sEmV65q&#ݭ?CHR`xs2M%q4꺧MgL4@2+ HP b}>Qe(4{F}=O ] 5cv"bLf H ;~ct%5g9ٌVp%'87 %* .>Ⱦyl0wUފx۝mw'3nO=Br9(4U x.CLp|OZ!ے?S)QP 7usO(4knvVF]=}I{MgGhbKeBNA2 nuVL/!6=B *W=;]Π 6R^do|FR2 c5dK7&mw,j ڢ j!۸V*U>AՀ6" qvHHH<\S++) /Lr@wo?mtJ)XkûTf X  !k` *.߾ul^4KIg!;%, 8XE[ ­+ )O1!pEвwGp&|Sᛯ ţ`$JO_6@C>yckҸs*ʉ8*G.~;a=]8 Usϐ DO!DХ1!ͣ1PB=䒸v=&/3-o/Ѩ4ヘ.< UA |֫JS lUlኘnKv<k(f? R&vn׽ɟ{kL XQIEOMj"vXFp|W35 WKR_Ùdujm`icv-=)yYZ$QGB JR\P=t6j류ݕLI,KT.m%rG~7-5ګtCfwLEo_ovUj"0F@ɓ :$VOk,0@ 8HCF EAyɏ}(Ph[&!.- עJc.8ZqT J`1ŵgHtۺk.W%< _a[R e6gcl?gl8&u\oUR4,+.u(hAHK!1)Q{W<_[ۯ?3-pCҀ6_{D7)+8 P S)h %j]sʗςIq_01$_pE1$_ȣN[CQ+^;~qQ!a_@-M%O8ҬGB|,@FSe4"1%b%)]Rihv@_A[8 #ie҆tUKWJ}ALȟ3C}U2&fmusY,O…XJp4qv7`6tH#*g^9jNɱz.l3Y[͈BFs$Q]DQz}r3zV(?E+RRӽ#̺.mZZf]6c_brD6밙1z}溒l>_(\N2S5Tz5! 2t'xLaKڃB cGރ7 KOh0 ,͓ɘAGa޼O#kiƄB̍~gme|,sull H"<{,pE=sfh $Q, :1o#¬&f\wCKwu*;bJXA{2٦H -*1a^ak0 ݉^s0=n w)9e2MdM`*k2B&C)mPv.R;hTLqZ)C IG/9Fg 0]5Ir2, unZ\Uܐ w< oAq3jt°h"âő$#۔VRO/naťRJkzHƦMˡXYnS7$(+܇J빅tSбKh}ĈXrkiҜa4ݕرlPc-֨lYgԼ;H֙HNXjj3Ln}hga&^[]Y>rdkfջ. SD fOޚ`n()Ӝk5^hX I~GPD4\=әbbb.vO>KK[w~5e:Z<¥=60O-XBA)T枚zUϯ-eTY]YQv *Ï|2M&8|'H˿m=%|yT@o^9 UTfDq!t2NRF) #Tċ([(zȭ1@jHj) li@_цDٸj.1C q2 &ZEg6͍ʌz1w faͶA)mxƙԯ:;;uo>:eS#/z#QVfyKf( |w Eifbkw2}ӿ׳]>¢ 9<@I\?^ & WQy}f$J-ǂbd? &5:POmȃgFHiXiĿGoRsApIJ}yЎ iH ZLY'LTed`5dIzC:: i&_(dENj0=$wgE>s0WיQ?.a@ML(fA'63$Iڎ <;]e< h"$P(Qr2u,f2սre*t&QECz5yYliKhi=K?Z d<4`Y*f RQHHM3ƌ >eڎE[|IǷd<}/γF,o7*HmJ[On.&UIix΁Ժ#$PpQ}SГD-XWg{g7}m {T%8L4cqׄ86n/_ثW*`ܕN/?Ea. }]@@zP8GT1>ΰIR=.w@zX̘oMGtvVh")Q 7Mo~$0 b|o!?ţt4G6;-nET: F^//IYh#vj:);M?J{ap")Q^ BB&.Y+k+AaDhcǑxϕ]5y 7qA @/<>uA3SS-#(`B4 Urt^vCe^`Za Lgӓ`:̂> 9Idm\u~ub+\ <. KHaP $g8Ggiw!).vUc2YU\?hk3mY& ff5;l?G`\voS\ZyI68^PR[ت*;Zv;_6Xk)u{Y~v.΄}XSrǭ]tH\Gjg"*Ĺ 3U V_թʼn"XC<3VЂ\ 0$10)U}:BsqCg;h (:x:4l=U[gπޮ;r{OeUU)pӹ^-ه`WjP ;G`À&螄eJ0ES5Tk0ēd1MF& jA33 <0KucRH4-vAI<9viƻ@k0G"z)6;'+F*ʕƋufMZae1#R:/M' ~I=io)}T7~1Wr)NTí  ksq<^ R0 |zt,w{7.*:t=vWցDO JkTwβC!UɏђQHƷ$YucAu0YZb02J&.} *3yj#n1?9-UѼ$%$lh>4&ѹ*bBxVDT4:h'cjQ_wtC^j2'sΫRWԉatZ>ݝ{)k$|)yc5qTpاQhĵd}MP=}hF sT)Sg_0%L+s`جqst::\L5`R툂$ҟO%X[@0_ B-\x p}dGH$0PM7D#.$ۉf|5%4ݩI'"d78^X}E`{(LffP~s G]C >J("o>~xlZ8& bW:MW 꽬ȬA:{!g99:CXO 1]M\C=6vqϏA8HUb9 ̚%_@b? Pw f)4qqݸJ}(KG_GVrgapJ z[.#7%H_W׊UGsQ+AՍ,c7Y?R@0Z=y[8X, `N,LZl -V3?H 2 (I+Zp`S Ugb-L,u?yNZWX4ȑ<#%Z9.N;YP~GZŲ H5wW7{ ],pԩI UՙxC|q*- ՟y8=1(l=qΞ`Ir`lu+neѠe +Hl*_Э4ԟ0f8Et'>;2 =F4LP9~sEX@,,vrH`>DiuD"0) #:'1x)TX I Y.WCYbTdrF62(=U4.)_c.HN:V7LPGy:Ov<.ŝߥF>K<2-Ah[=Z[ȔDhX:n]R>6]U4֪_Ce/rFJ@+D&2F ~bζо0з\а]~ѨGA-e6irq3m|cKwΏ۹6΋ꂭ/X]IXdLҦzqRǗ>~G4z#+OttWʭQx VfF*tW\zţboLS5S)w)2|2r)O(i\s!Qf_2m}0%'yX"X$*zJ'\ҿAPb}N~hz&UG6⹺&)3StX֕*eں$%g \ߡHEi1UGCVƚ"keJERGlp:¬W~ekwƞPK*\E66Qh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-vietnamese.woff2nu[wOF26n 6NJ $ }xg_z)"^k# @Ցj@v!fKσ4o-rOњݠ $P|4ʄ 7' $o(Pbi*9 LS6QQ\'.Nz1GJL J!E _}|]M}zR5ѮԦK~<&(|N|DSna 9l`b^5w Йzlހ̼]BEݸ,m 2Wf}:/xKEl+%VRS|MT$hqAx:!td=v|/C$N"$e#; ^3Z~"DȄE] O82nG&}cDԙbs] .jvQ DGjހ)fZ$fWqPseM1tHpѷ0@#* D5zu@d@teM{PGV=zO~]QӯvKhh0@}Iy`,[R+$ey uY)!B$ov"Za?:mKr8j:ד*%W_'т$)G:iVa)sYu$(0] m/ g ).ɦӨYidR.*([. \6N% McH8 }^۬hS]v ˃v ‹>o#XGZoBz{m\h;â z GP9ha4k<+k1:5ǻ}<1 xL'ԉ2 7ۑ 3Z-r.y Nk[tuAR ^7u+Z g `m"8gE l鱰.L[>wƅeIۉpŤ7ˍ {"$ixӶLe``]4N oЛzҠ/G!Х`BR!i2W(3.|Va,vV{j_$<&~q-!=4ǃ쌖LV縄4-|M55k1|zvȜ~M2"Od acSG\Lx9O:%áX1;28s\ݐ:X?NbP\y8Us  ["!`/ 8퇊C*p#_Z3"6+PAoCmX+(gvߒqÝYVGy mԘnYqiѨ x6LrڈF'yo5iAh o4>]>QѴ}u$|$A+8;\λfb54<(L)cc}&uc6% d_F!Ԝ񝳲 *CIdqwy^+lo+RI:G3x'X*GˮHmI\"Ѣư]U]pٕ͡t#E] !p ]miHjƴڠ-/zn8.|}%Zּ  8ӵ%DK_gKuu4 Ct} K.)9lr/p6G BD6]B˸ԜV9BkGd4SH2l^_3*gcFG@l6'2 5^iSF`W{!  tVIN(g:ӒQ?l`/[xHCzaET꯾Mb9G܍f¼(Òy6f Lx쀟IY:_t#6Sd0X!ONSH`t"TގU4lDU'.<\>$yj/̻[9|8)M;]-sTa yY[٩T2v+MAe7_q[ggf.%XA.r"+ptFFru3BB=0]izn~*cYv l_SF}lZ o8"zz*Gd~_*ْ=0S˰g`&4ǫգz-W㌖\H"Mjd$ T3U *#)%Dd(:«j12H5YAFX-[e5AT8Fh=5O(}EVZDRn:#%b/)@q^>yt3eai,oqȷ w^}szxOmgº0dW@.VnM!Uaܑ|٨Ь0J';F~PE ß_#A][LmߨO7 mERRçyR_$Ic?Gmj)k7ߢs@D#q#@yJ.ݑ􇧐8ܾ@nV>+^ Doܱdh ZY},MGuOJ HϯBfJ2IHG4o` ]~+&352 nd[/}B{RK|_`N/ݟYgUvw2UD +3mL uBn:5^zMVgvx`_k7cz?9^g]IZې?t/wjL滌.g4Xxeʰl4 n -m|ܽ<A7ZޤW+Ezd*u(V7y?a#iȁN+Ujz10S-2G'񋅱HWE"o)hKO9r zmb>='죟i;w8>fƶG\&"h7xW=hU3-Oհ)n1d@-)փzf]5@p]~wOu'wPHLͷ8茾^ Sp$}(̘/陛пϿ/}1NV.x2{HDG??`Ѯ> sfzn>8a'338FdhkaǞ}E5c*(D pOPY`7qqX[ NT^#Bu E}>'L#ێ/'9Y9[+4.!pk5GUV*GбqPA{w-o}s)DƾFon{OkOOJpnH,L4hısvc铀E*ij>4, d7xeas=@ŒGho*G3W^e3\*9+r´X&asٜ=w<,]9WNEshB{&kݘE%g?a`s,x@@5oyNoy5[/7'8Oy'pyI%h ~&ށqQqoΒ1={'$MyQLH%*=3om[ֶezYZ+؊ T䚒/ p_R3EēxaF̅Ӂ;ay%8 DH($vj)!䅇6Y? ^;OANdr^h$å@GN7|&OƉ>##%1ߎ] P [e'qc/ۑ.~ } _jv縓38b;WsO 3;MLxI<3Bӹ c.ztrn*-?".{ɫO=W8}b.WɛUl*['~49ԅhmr} B'gҶ%UQ ^u`(}\ZR5 w(sL`< zptA!ꤴ=73^ eS{/;aL IA`ha0ʨZ(H4ǡ ѕ<aIhW2nP'9EB0I0*I5k uH(j;J?hAh!+00Ջ%4 ]Sk1BS6[fEU[ilYUdz^.pI$TEZBX?*LA&Z5~CY)*D|٬i6EZ<8^`17>ikt_"!KP bI'8RZVD$B켸{D1iHIԤ+*Rk1S(N%YuP(K{T.&MaiB Q5-4R<6]،rӲnxf0@\NcNEPG*nB„B膖U? h[1ɪfdٝϢUo\eqJF֑?S4'mSM#辁@6"VkwVif@K)up=q,M@H6糶es8YeNkXl5pi tʝ 'Lpu9@Sas脜"'D *%3)?8;1K< f$] Ӱ,AebOd ,ӘP)H6E9 Ӈ0 ]qF'#}1T* ,F]~k㱎ɡExo4VPlfI9nVY5zj*-?SRqs̔՝;ptiվ/O;7`* $IEЧ{;G߈{LmX~3'6a2F+ZZgFAm«·q$LuqH!#BG[: \ /:tut.,zQ$'aJh5=T?Cx9S(CNluĭ;:܌ĉ!YzGa(m,C$TO6ֳ֔C3y * f}^=_Nw5%ALmXF]hw{Pdg^}MmUIϔo ]hۘ8`$ `4B-Eӛ6I ]CB<@Mٕi8䂜^$̤^JODX+7"wR$DzSϛB'W7!HF=* N XlܰzY`M҉@(:9uiY GT<(U444ž_nt I Qh,R(+ZqRC@.rV%k]#]Qm+z:8/6[n')Cy8즰eZ$f`&HvaJ#O[XV6 )t9^|"뽚5+Q:9.9/]4Ut7)Ѣ _a +SD$퉈`]IЊ 1 w|>h$MaQIEa SiKȐ"-ۏ|:ALpM<^IȳVcpL8(;{=AЌU^m&[#npaw _΢6]§$\.qR$XϛEeIoDhXEMZ~h}x܆-Ж/@dx0.;2<,W&W1t%l;)ꚊBExj\e;<~]))hDCiݥ&5!wME.0`Ħ@Lũxgr? A$ǒroyܬnɧȷ 8ַXvEe|<ocV6fpg_~lBWiPnVHKYhZ'Q>#G#ԗaYι!`4_~&U}rlM(tU_e=srEؼ:C1H%zGJ<A *]3m;12ETfi_^ ʭƩេ  .vaAØK' UbᒋFMnE"8*m'ͲmmQZ#?U[qݭRL|wY%@T@i׉Z$477/Yf?oETX(iϥ0Mi s gQ$ ]ƚ1(a;yxF؊F( ^y7]..9},\ӝ= P={5LuaIQ2;B FJ5{R^UNM v7)W6x*ɵ&\)=vwH.<{V(E1X'sVs8g`VZ٠I`sv\WWƫjjX j/y順ຌR %ԐS)x ,:.y]4[C- w8tFs0x֖2s\_:>+\~c;-lERnq;繓IXT nꩲa֌)j$fBĎkh64RP(0eqTbȏ~p"ClsO(|ІJ^kĥppһN*P80[Ju4+,$1dlpS:(\ZZ_YPDBޡK䰷h׺$y:phj7!H03iƒ%=oo-z$ku&c?Þ f Cr|Ǎ̠$_pgl>Dn.L9Z@%6<&p?W@3h\cO)+l@`E5kz=P΄K?dXl͠s8=&J=SD>fS3cvf+m`Xz@kfs Qlq5^F{E-Uqr*piseܿ+z;1=˄3+të/A@U8Fq/;slA9Oj`R3/9%+&޿V^3Q UգOE8@7j$borVT#˲_{b̈́ǀ,gn9@7x5Kc7=09VWo=9NJڭ)?6phggdCP]0DPwdz`O¸9P*p 4'8"*'ya|ʹ|cx0] c9/dzSc@.H9>/ct6Tjse#tuH+ma<>EOq9E|Cӛnzd<ИSLamڜE}dz}TqKsE H=j(G+%K9>I#^-xy@OK UҶ0gv#  0_ !K^P0Z˘aP_+?{,sۄÒw%UUI^2zbwlO?1QӁOLsC]3h"5 ʮ0C.w(Yorf91!c)B5DJM` $/*) `КnMG Mؚ%dR ,%"&%bHsʄ; B$ڄ(գz-$&e)f&udL,F.gJ3 IMhd*cY^ώW %Ec6}+"{wvc(Vǒ*Xm6BS5m>^ D>!E|GW+AVdXk(YYFe~Єfl{= ]uhex"E̍;is$+ UZ1|nXuۣ,iZ]1>VHLjqCѥ C(:#N$S$2b>gy~#>LH*:2 ⴫t@'o*<s\2-iưl_svWa2dgI)'Aʐ\3k טzCo8>9܁6S]]7i ˧|yK3QG$5<-""icaFEBP<+Eٜb2Boyectg\CІ?47 l]$,).P8vhV #C@GIyzf)lƮX"hqa? tٔA'zg&Q^K4CauM8Mέ~Ă@㕿82V!1rE׳&ˆ$PQ}EcBqoHP]Zn_\ٲ9+icsR,7WX1zXaO=Hd„\NQL14)[[QWRBR(0asB;Wr65`}VUiy9:pdQ8P&)mȹYjwW`5B֮*eN ֜BQd@KŐJF"7xmg9v?֑|5K?li,)U@s7LPR$ԸTtjZ]hܻ6Ysvp}-|TiwN(po( PQlBU1C{a4#_ٛ0aBGGɥc0A{Pm^E:$LֳpG)T ݑXTw9-~ٲ' (9^&:)Y{Z [l_mznaQ㝟t- Ky&` &}V8KfW5Ed[Г,˪KqZ@f&9L3f`&r= 3ZB1v|nX<8UC)i/2ޱ9+G< ^p+ zIn!| ZC Ex8*୉'PU1^~GUqxSmj'C(^gPJʊ"d"SR<_.+`bӲdlYe1(/cI{fHUBxs+Zgڕ&)lؤ\wұ ]ĥy60iS &vMN5'YMQ`^Ḟ-/R ʊ4jaRL"yGLr u3ljUZd:c&$H,i ĈH3TguUK,]:/΋@eiܚnQ(N0ƌlFoyzɁtbM0 t7Rcmvw:T`i+iV2O ]hW!p칰k2,̜hSf1vLl64;Ph-$N1QplJoMQBW(r[p ;k&bt$g4 ]CDcݳ WnQ _QmU;ʶSdnyX=Vwj剢*;vٕ |?%)Я6l#;%O6/Yqv/\U,?f}C5 n IGUZ Txoi!DZ`QWtGQW`Ly89 PK*\'rx4v4vVh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic.woff2nu[wOF2v4u> "?HVAR``?STAT '+8 /V l $06$D  5lFnL}Dq:gG8!8NV,ɢ2DFdA% g[E`+fgW!wki_kynwHBGʸ"4ߊBDj~M +ZjTLP5U&u+OSg` AHdɒwn4Ib<<5"zɮCI"B]Ml寨(baX -aF`Y.XЖ޵;\9Iѧe /c{nPakԕk|@H srLS4+ ~BQ3'Ip)Ky?뗶gL8hdhUsL8{ : b9&%O ?uDTr/A!UGGʕ\t9j gwf]G`Q @A  ]@1*tKvuXt.~L- pɍ|jl T~.;KA|L-nG>{f@P!!2[ A7!;z!:_ }~_??׀ Ϳpׂ;DWj'NFA!"]C4zƮ!I}19 ۜ>}P}pI΁L!?zt?JFð _y@z(&;eUB"[L}0w.I飴yv܍rUNtv^U5n+Aq2buo JF=6gY"I.Rv>:ɞpCCN8Ol\P3s TlNX)Ubi&qoM!$kh,,}Nw>L8a .yGYDV#U_"[diPڲ?6$3c=@ S}8XS   Lh )62JaIb`d ߩB2}yxDC0%,{ũov& \65[?e pByLPjf)6tq90Sp=dKuhh(BP/ .&q٥"WUWc#?C:cGtZqAq96ZP`B5>i#I^%l]|)Xo+ .q+]I>ME-l;+Pi,M̉ȟ7#Hot^rkG(Uoz/2vQ.T1'6ǔGNs?5zD=3m8e{0Pꎄa/\.۸h[N'ʰZu^cT @'p$.pGjyRXC ̡_}?up61P)e`(s0  w$o"y%?f^5oI9ᤕ@nZOa7Q>Z0 8O7"qtUzyeŠ8%1d@ޒF "|ԝ31O_ .P#f{ʜ 1}~ z!.A 6ѝ̙5sXa~MКn8қ:trJz1x IFpyas09`̷>iv[3S*D)&mԇ^u]QDTN"X\F|HWxBv枮y21)~˸_5i+*4FIEύj >mSژ;] ^Xw4,Yu*|I?eWu+&(9~ch0o#^s~Ui[b HvaeY]ϙ$=$7F]8魟8G> ZƲvI,! |.!t*` _(q;5* \Eס~PKA2^0 @ (@P1Fo4m`2뺟{ O.g VB* WY('P1[`yH`ɑf#TdxHJlHq٨8~gmv2$+LXr%om.NIy*p*],o<[dI)ǣKw+[X\ykg|o;;˰֥)D3lQFj#K>f0CW_,!6zmppoWg|*+PY-6RvFswq_ḢILI?D6҇ݶl{t}Q%Y,xc@%x`bkDSm[b .IG'IɆI^u'cݭټkq['ӗݙrOl3xN&ZH,y*s|e=^ ߾+܀*?|PK{oe-.E9tfS5Հd5"@݄ =cWz+TGb !h .³[RcsoS=-M*4U.´1Y7l7+0բD&Ʊ7 ifvDr]\x]lAfi]yLj&)Ď1:+8@ag"/9_|9ŅYL6u* WnZU8ۦy!mmyF4J9 )1ŖU8;ӒHF+._[E,D^oN6wq>ל>J 3X-*銝pqD‘+) :IK}ZȍEs?ݢ}=l"Gk6hH4g 3^LD!05S4yGv"X?zoEDI SS&!H,p3E(3?Ls6{T!!bnxfzP3//dr«{T͓$9vo̩xA+Q{s!I,+y=a5€dOߛ^މF 'Ke;a8eE&15M݃}۩zh?PMFB ݑb*Vwnւ/D0{*l @)-Hκ5@z97!]{]zIТ޴ 3ԍgC?VzBhmuʘe\%k161'ԇHR?[_7+=SiO#34j1)_AIH4%FϊtIm%LUBVɘM_c=6Ludvg_MdVW7d`H`(^憱 0{~-L>XE?UzWSΣB\mL|@.V=O?2u^ 4=|t% 7ySY_qR "GHxꝰ1HSdqAx|asLo{OM? ns};['5CˤWLǖwͿer˱y]L3R FO\/w8cym*P؛z37QO_s7.w43|Fj4P?5kc0?8P1T}/k Ys,p:% >dV28"-`ym UQKZYNƌ?Ot=S=T]?v.3|z̭#4Ε6ֶUP[&@v 쏰D>S;aD}뵘ֿjCJijMb}ʟ-QզM~ g5 .f)&va{=>;u&6붐 3N[LRn<5KGQ0V"w8~rJ! `Z)=x$MC2 zUF:)Q9@K%4,:Hc-4XA<0?_; pdbvC}Ң=rb+CЈٍGc ffL3Q ?quH,G/V:RS|kR*Aچ8E۵ ܣO jn9YHoSX}X ?*H}7V4Epw3O3ɵ9>ۇU5-6cDuqH'*Mq ƔRKv}z-'(D'RV"t#_s%'e|jlZˀk(Z)4#[y0_Fšk++Ј+rS+GDff,ok'gɳvd=<χ"A̭"Ik}ҋȠ wTg>g[7 OaܷGwŗz"V3j_hXH z|Aa dZuz`c(EIAPHW'e.GX"h#_;v"^><=YUsgBsdwnW_(ޯ#<_:BO=g;mSp\.':~8VK gw;%}Ad?(y@/,ę?Yb11C1KEX‹F;U6;IL3}zPB29H5^ *D("v=sZ`?Ԇqzqd493$T" 5zU mI؜ԽIaYᕈo1a?fTXC%ԬVq4ikR4J&DY/-tldm6:+M/n~tr*އ1uxEy 6~s!pa[GAC vZ_]4'T+ޞiwtY11xlvn]6ԁUΫ6ў4;lxj{Qnhtʼn-幱s/}ӹ<}2CO>XI䥲wʉ Nf~UBި25u$;ݦD? Vi pyMF)Hh:-$ƞz>  Fv]*t('m^zwo1ۓ>Ӿttt ]43sO_<>IF^7Tt"^v>.C5w5[G+}"喬sh%._mi h*c4$UՄMggbu Ro/И'=rSVβ 1`LUF-nRzKaR %?ҧ`ѐ B~r ڋPaDF+|M"1LrZ~"Kxݲ@b3/6cG?QI{)f;j js*֖Ñl^9’(/c#%hH1Jgќ[aO?ZzvHl$7/pD6BС|W(ѽ PN/XB+T}36Lcs4ŝv(+Gј~9e\"Od$j䃅F:DȚ*@RO1Rz(!ℜ[~{3Jڒaܯ)ա b`ך|y?[M(<a;Ew^\n%z tF?og~d5b7UÐn`aĚוOZ?ܲ^\7vf8%x&[/iozna*O}uuNf)\Ybe` AM5S8jݶ^ҴAhrj%dQ/KMq1E- Kl| l`6UFfUkq#"L_Fͦ7|5n^挝vvBJ̫.ls{B[M(B ^톆|t;E{"܆lV4UQn[Iy6^ ddF `6uFß p,կG =j'PnQ`jC i ,DJp,1rN ;ǐ.\x䘄PӋ2qX|sT,5M Q_2L:1qnNeb S/K˒/"MV [4}!O7=tR)HJJkxmf986ߜ yzZQqe}}C(& lx(n]oScUn2.b94g ` ~lBrU>9X-R#V%[v,;C7T^4פR#!4:Haʜ'**{'لRFJ{C(izR5 :P?ANJ&OÖr&O{z>r}RdlX[lC=Ck~}Ù-e>Z d“= p/WrrҺwl#ٽf;}S0]AqD ?FޮxQ~g.+l6$$0qm'7KXX/>GNӠ8$eIv}?H V6)Y^s,,ߺA%~G{rl/OE .ndկ79Pkϰ6nIJZ,Ar-& UgL~}0u6 5x6e43XVA5B ~Mi'BGo}Uh+.v" _3poެ5l΋hOGJ6SEgAmZCMlsy㱛#581{l.ara&`*k3I-I@Ie0aj'>r_Ohr,(. N=+9)d0V*גNLIa6%n$r"PiBBC~ޑ5\磼9{nJ~y,CȦ4M5z#jCo5hh[3h< 0,dB!Zi+݃dp!`<r& 4PeI VP!j!HYEdŢYVLDǃl,E--X-b 2 $Gl1-Q!f>XI W?U^#W; FiJpP 7>7P9͑ G@cUg$M֛Q%VqZuߊ!ܥz1"Ӵ{< G;/܇+2߰4y`Ȏ: Nb PZ)A~;n'[pY2zq}("n>Boxkf==C - 6ʪC6+cl|lGf袿+qZf$O"8K$~'?yE:]5Dr $K vc]۝_]׶0_ۙ&wڵ GɈ17Q88pn=I 8$ $ś'TJ8Vx'z ŦOS\%aیݗ9 0Au FoAy=2^t2Eq,@D雈ZX戉Ox6뱳rXm%8Z35pY ZĨ)Ct:ݭeYUmkٌ߫Đv&'(uXY6*fS5%#5Ȫ.lАo`%vyߣ{4ao7< By*aaشa> CiȢ (pP?961sm&x\ZecݝNM鯆n)dPOPu}{^:]|L~O{RhDI1E`d5y|bO>Lc*ZAuF^ -P S۠E!!{BC!␆KȡАдPxhW觜R7"<1Uh#ǸqWkǟ,Hp.QLJlK𾁋܈B+7.UnWA3#( ǖ~ϟ0f*']^Cp*O8 T:,FMz@D"R!a@f BD x:k&%pBwZӋ4#XhB]r O$"e)b5_#v <Ͱ EWIJ=NGTf' i1?Ff\K~t)PX'9+j#S-%{돾P+^kRk *Gu R^wNoM}SJq6vw#Z+$| ìxRJC5^~ ?zw[ot,"uR$J|}#1TL9BقJ"JEDF-9\w:-ǓhϹqH(p8 . ;*WAPYd(f\i(),@dzKrZ8o&2sRmv] 瞞%Rښ\Ќ~ 1,>D N<6W9(Xx*xH͙cV}("G0G-_TBo=FɑFFR5D/HwWѭ{QS*J?j{늕FsGZRɅu{ԧcמN7Qpe%=dg|SDU8O?Gc {9\jn [0 e4(A=Ґf>Meبdg Nr~6xegRŲ+ =9b苸&H\ŶyD喍?2p R|Ш)fVQl9A/EjyP^/=AⰑ}~!C#=ڕg}I- .֏SG?)/u{ellvj@"plRXcy;Ξ0CH<JCcE-a sc*"qS!@R,ؔ#3X\x2+bPb8-$n]p l&Trbp=CfaJ tbR$p!,ג:*;-xU)p OW-8YL+1L@'%BQG"˱tEVIWDEW~#Hq$D`ޛ)AnjWi bthЎ]8c3lb>(r*?yn}Aש(E[{oXcNz;Vm6-'7!tx b0 Ll)D %-CԬg8ѵ#B yFbE#`FȬçT- xx2 #k,>#_ Jf;9|KzRs\GTY#b Udڰ*fח.E;N/-۝C{3s\y.R< B+hF zkUxpP/Vl&8Th^ QZ#$X)VTMEKO@VfUb}S]P;4~ĚI@R1Q&cCL9^rEhуnj\*NN#x}{m%b FbYtFg4]iIـH )h*4iDDiȸÎjs}Dm`\jŰGwZas9.QW +/zn[9Jj%6-g\uؗu$~?AtU~U笖a :aЀ"`fEO`AZ+y 'u<*,88 Ya ,:2cFQL!p፤[KvL̬c=y[]>~;R0n>98;{};7JIU_Z&nCȾPoٍgaWBeĮlLB 9) xm-<\< XG~e<жT?XHaHVCnvs8TOzèY!_ɴlzD9 SUga"/NڝEt2ހA 7Fjl`8OԂ!Aiѓ2P}}ONrO&ߏNG`s]=@JJޔesph`Vu`B:bѿ$h>>$Ü yҼGЮƏbH 3b3ky {QK[UlU-oOf=j@Н X-n$Uu 4WxL7l8V84x#-8m L5\L_t}#qGʉ9N,]z$68x,([S-z-Y[@nk7Hd|CQFƽC5IݯyxlTFn*W62D*OIYhBMȝfA(SFnKCGh\` Bݍ?Fo() _ﶼ ,ޤAn@'lhfYT UnydؿTA_d rX~YϷ9xjwlK^7[eq'*YA]`-o̮Atdyw/Mh1]^qv9}Bi3<(~=6X"PI"\18#Q ԚJ,XxI(3`iވRLm5%zm`K{;rU#-UlhX6 D(9qdN"/uN^{N.sw繚""I"O } TB ]>ִ|NO$d'24'ZRy"w{/:, o?#22fdJda1HFBLatEw _/E@OQaQdh#A{v .6]0LVTonqmr/WX4TrהNT}GGe>˼&̧,EYNE7:&>}}GddBR?vzOڟrH@ZJ]+mH).y~6_$6 T"lfGz4!ޡWl;=u7+Sd#>w"D _w!zlW:nK" $K1#=J?x $fG Fdx&ve2#{X4+:$t:Gc*1I`5i *Cc'KGb'6V "5Eל%Mwl9G._TK xUhHj} u~oiWG@D78%>~UĎu? "WyD oo8oUmơ?&h6E.OFHLwq3[3q2CcȒu#g/9MDp 蒲]ɫfˆ%F8 'ʌy?3X^ܽWV䚐8A3M)\H`s{ݢ|;MuvYUcXv<ƪ4jϙQ ]XJe, z='|z5 K!/`:n-_Ni4!xDˆɝ?cu݄7.Z kM8}3BݙV{轷n$Z @?a|ɵ9n6{ i2gd03)V`5҇: = xş`˜Ӊ }0+18qn%y2uʆ;¤)JfB} *{K?"]&ץœ3q&pT&"iUE1fxWJh%Yޤn4yJY]U6{Fߜ&.es\ %N2 rOXDY,,MuI"ǾmgTeg򍚢VleE\a|443~ !yy%F-g[x(DR)eV_ezȫqsUŊ8\z#ZQJZT9*G {AZU>!)%*1vn3_ܴn+U->;/[%MUXyD]D iu^.ٮXKθ@=xy5^U"q~J1MNC4՝_d%( ge/?fLctUF\ŏ%X)&3:4Qx >s"Z(\>Zczo."3&"B㺞Oy$I话ޝI$7˂{5Ka9nKny@]Lr"`4 }EQa&v?uDY8>^s>Qȓb|?3wj"aiLGpj'㟢>z{lXL~pn{džǁMahK;kþg_1 q>D2jA6jб5j1%8_{IP\gH풎`9Pbi틺 $IvPňBtR;Qb\)wEM_ U]'CS4嘤.}j<(m7ȭ'^py8Td0xófpAyT.w/[S]3w>v hO1"hA2MI?j$AGm/ȢMvb4f?^&t )LOZ1Qu/7I_z?"3 o DޞLZcfهkڝnLRw C|ZX=̛z%F;ᯣqP(!%nYlQ D v5{Rx08=wWflWReD*{]vYV쾱j+r_l}nw+?{5Z澟9LdnRhBq©O>"Onw 1'F/lAת: @XRhNjźwa<;[wY>L6mՕj1>}`wB;hAZ/_F7G7ǟm|7v=IFkcxoa$h0>LYgB ZQ"u޵g*%PEa| 6S*η0DkYL$>f䒓֑/ 4`JsLP&rXPiQ$c-ychi7~̷e%șsQT-#3@2\I)7%ԓdq$u͝Ð k[pn PˠWBUCM9t͇s}2f|~[Ngqv!NV*R;-ޜ-M+S(xxxӘ~߂!HQtLLS\Q㍒=9Wؾb6g:/rÖeq*t:M|n[Ovp5vP_vOPJnl4*K ZT,Aw5[;H9$ƒq5f (osB:wۨ7Ͷ}Wօ "lVfɽYyXY3w2AkGjjIBǔ{OxjϮ16o(i+fJO]q8s42=i3ق$r8DA%a=i ND (fѓ U˨KjJ#4}T3lfHV?Fزb\*hO覦x#8"[w9>ᡈQ$jk8":`HQ9W뢛Ǻ=M{u7fn>:zr ;`e mb~A5})4its_JW𽍿t#d VWܷ?e=,:r>;( VLD0)(t>5hr3TQu h"*ĪDS[ido*޽/:ԇg !g3o.a#EU~&. 2ɣRE(~, ,cH@Cbl20B 5Γ`yC&H\t^->Bx}^e=aHi\HȺMRL#u>&"6(>̔F5𜪕m6757XV.+2Bh ($ZNF1TNTu~m4z0blB##+mB P47XlhKL^5:լ!Us<Q+%ӛ+r{, 2ꕆg', ܃ClX 밗h8}1  ?y Ř?dɬ@R$h-L`2ΨXM)']JJ  rNM@5"7ehHdq^F?8XK5BSY 76Js,*kៃXX6UVnvr +gYh1 v(|X,!Y ;Ȇ(_ rh*`"*7-̋ǻ &u8-DzR*:oeG@-&vKhXͪPQMDZ'2Rj?~TvRm`a&'d`hhj ՁMFhp23W*]U=K/9z=80= )ן48i rqk!؛0M#H&E@ ǣ#54}l@w܏6` э`jN$d`<Ž_Gr8[P~ b֢>EaĮ ËW}K)S0"44W.L^+|`tW.]:(?_>cJ Xx?/+%1w]:_7lrC[ʸk,"t, דMMkfŐӞb٠ؠ(Ǣg{\B%_-4GH2tDkҶ).Gfebu Fu͎8dtHb>ZpZUE%۶9I)ɨ+ɕ7om>N\\(Oa̕Mޙ+8EK%Rtg>WWXMP S5{ᾊ~ Wv iي(25>?P GPgpGyV Px^evUj'Z6b#SrXMĚE`n|%K ڎ9j) akizV5t^o3,c&CǤ$|b0asZ$V&wD_6 oVߙZͻhS[ L6|GFX7C 9 [K? ,rIyn4>5\u-^`Uߧ$3V*=0$W ggώMIjHKӚ;Vr$g؇_̪bPga/Ni8J@{)zdYBefXY[7("l6vOn|iuG/n}9+~YIJ.)~ҼII\nOVզ "9^P޳w:Ϩ$Q>[bt}M߹a[YYJΪ~$sd3sʼ`RlwO^L$Дօ4N'j! F <ζ Ka %Y@N3Jur`%JhaBQ(Cf<&ׂwR3a'H۪)ZsLkWIFאAX$ hwŎdnTXY8'j#WyHo8C r1\/l۷mӂxʹUvgdL*ˍ݇fSb7-jy~LUߺ|eq6/LYXG˕z>*P%YH`ku"i3 !#!pu % CcL>!^a~x|!'3?N^xx;Y$ u8goQiɰ(`^OP$f9S(mE4jeu؇6WO&q 9ΞʂG+/Zۖ5#jl>cA3t?8@Lvh;/opZԔr-wٲdUgEjf1cE%%39 lZw;/lXv.T6s0M5MtK[dG v~Gٞ-F >ձ9Ȭ`!|Ggw: aXv_PjeKCR6D[GN C},| #\'}}vx nmاfpBx1 G{$Sq_2xkR<zK)l͂P"! zufe7 [V_6h;\- V>lԅv#J$.UT9O_w7sBkh(iQjxCTT,jq$QvaC,dP}_ׂ-wjn͘)W5T%L.(a}[RwjX.$aYamR6֮Qũ+?zݾBʿ,IX݆/4l'ZNs\F+R%I8w3Q*4WCCIq=: f%VS\> P GP4Ԩō`9Cʁ+c"tuvqǹ[t2W7Ks`M9Wɢت4C2z!㯕JJ$©q ml8׃]Mna-%Ϋ͓%yqpj` VrUj`:灉kK캤=Y:z]\}?cL dM}LȋAYƘC.ͱMߖ#/JJqbT[<Ɗjeۡ u~h˙n˲P>6'}f nyWcmIѳpD41zp͈fHRaG6]?-vn<3w 꼰$,j䋵1N% (ka2vvUom}oFgL 7ð{Y2=R ;ZCTFm.}0kI`66ޝ٠rmwvON 蒭E|ipvppv.AS(B{&N:4>z.wK%\fVzc@TK5yܨ_Z ׊0-/uo<նb<;ݭّ`P2"TxWYrNW@p t˩;IwVMK]tEf66cEؔ[[]//'þE>bkJ퍰)?I.x?h 9f2Y7bJ:J/1/GUԬL{z!kf{^Oj4%˒|آ>@趂JױSxX137Ӌm n:z5[-c kIk+2>Ҭy\XlaoLC*:M 2;+-@4֚BAMw]mvVĐ{x| $;M]/0S.V`0E)v6㱽^0-qfO#54AsH/OgˢT7U) |H, E4NC Z(5 wM) 2D4k~1AnO`SyŜXdM=tGjʹh7"*P#`pM4> ]AYˤ H9);U6g=os+]Meۇ*s{|)rhsP:,G/t9W@ =uNͲ2Bc u[ei4ěxcλ*1[: qJ<=B%H+>Cpg[{M`zb8C(ޠ   TC{\SzI ԯQlPyD } [VdE7I on M \)mPTP1͜jLzIqg^319bVyf]*u|ulm0,d"7C$dOn֖CL|mtE'<<HԡzXsw!qvdV{KK \70}Iv>@x(8F'4 ; +d4>dQ51 /ƀ UD] 8r"$`Al .x )`oBx7Pd| *DAI%c d*#q„h0xjбbRKt8!sb%Q%#(~K! KTbĐU$:Z%̆Ani\[&yt3!Yl5$aڮ=4ߛu{,d"EQ$a0N8~MEsQ,nptlc(>kkwl29p:QYDFi8¸Q!U3,B⻌O-|51D0TP KMx-V9 ux.|y{zgͯ6sp:WYNEWu+0eבiq%[5ل4HD9v(ǵ.vV^#vFT#}U:۱A# w9@ՓVIdP7g^klqrPbHa(SQU1iP5s H#Cʄ pM F<[,=վx6câ0u:&e)i(H !p.L`Ә I߇lg3j=sh+)3H{< =mn諝p2^gq{IW)ɨB<b bZQ+h# #mV2,? xw>#1z^lS0CȲ# X7lLըRP߬Ȥ[PK*\*ܺܺSh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-latin.woff2nu[wOF2?a FT?HVAR9`?STAT '+8 /V `C *06$P  [0q@¼mWΥ\q;./f2rtnTФI+:܅`!gBhE]xd5Б($l]+u ݰx1RuMgF_CP=fE$ n<ˢBC+yhPthU7Z^iEVHZԑ7TOҔdAE 3QF(TA_ƫ1 7?GDj:HU o{K Ha|+g.D}^WKsta" p/ӜaBmz҉wfZbxb# *A+YKũfMY` S@AR$[0 TT@lfΘ׺pQwn}襁]~Z7;o s9”БCTsM&1`VHmۺ=QSį&T_u j/-Nf5)PQe7KWݾַuq<@ <ۣ'{nߟw:uY1>ifť3$!OP^uoiͲE6wW&TQ϶ ;U, ߯i`YF=!h6ݔ"JZTjQ#(e͗3s쏙Qb );\.!/)Pl)fHtsUKt*~S+S$%z}nɨ̢V P[I۝ʙY{$q*K=m6Xr+mEK:gɗ4Si;vT` ЪiIۿs:Eg>\Fr~JrLLXJ0SU=_kgm?np|SSRO@9 N'4?p Q P@ rE#Ԭ?IRgG9\ι|t.Jw]̽M@ t   T7c9F4(+WTАBSv &Vzlp23L4kjio=wr'S ?&m7s ӕwJs3{?WO?o3u~}+y晓ڪG.^j]zt񑫗]:];+&/,Z3jKb.1tVy醃F.+|Zzڜ>A&WGVVU\3ڧWV4v]>܆\ߜhln.[lq$zv#K<} `QP~{y<;4cxʭ"w]Iq0ϩ/;w 4!vY*4\ lu1gKAl4y>w*h)A?Do|WG+?[7|([D@]Dum"2jk%de<>ԐyҬ NJ75`FT$}H#lP.Ǚ.u7#Wp6ZR$EMtԇQ'+;2 B-$f ڋէh_͍*Ͼ6AW3\ 1׿}YOL.-$KV巤r8ob>MsZܥ'|9 CKRҞ?T^/ߖrkncFV~UQuWVV`SaX%Hy(n\QM<(VߙVqNOɼ쿪Y JH%FhՒU Q²@`.R`gBhYTGr d^8:MB=!CZ%ȢRB*zsrTZ8nw$I\L_"5,ݧ(@sѻv젗P} ZkvևIE?v秝m x_[~ɱ6uR:6v}忂s£8>Yw^uGrgԺƅ1)S˧5֖9wiΊ)[[Ug;(]p8r%K1sI&(π~%U-XA|g-sPoGw{|X>tu/i[Syho?sj+3ryT<.wcx-lOKpv$l?Hbu"0 v5Q88hN_?$W>0/2ؼjh9WNu!bJ\'wґK#w(}!W:Oh% H8}+.@0u/rM3QYz ώoB I◔s=ohp h@%bBݒ#|9=/^ kzA|*crryK4$XQZKneb7uskii soƠM@|&Y" }lۢBg6}htSy KjQwUyG7:;.i;M6 hI5>dׂ铌]]+MPQnO$㧗NS/J0%3KŕCEh" nnkUhWݲneS٭)()<6zx,S]*mJǞ*xkfTlON UITV\p,4-j _=5p %`?d+BXyR#RQ{ FѥZ p K4̣ Z$|k:)Br h누"ⳫP(ѶmIAEFHɰy=FZƗ1hVD 4h1mR_ܤe:;yVG Ku=V^ \V7ۉhuj"3!9s% 6F[L/U,,;Y^<  1$BLb&1%D"bq?r{kVl6D'"ʟuK%P_ڑYʨ+$i[jA/j~vcjI'iQO3ƠMgbaw #Oeh=^ixnUu43{2u3f]ccoxCV䦚O8dh~ P㈂]qu䧵>8ѽb%+|C³lV``{ӭ i힕 #1i|f'@#*p Z׃Cʫɡc$1)9}ɂ~WnRKom}NQQA#;$# {LxfeR*}bq8<8s+Ňr̘gT~{k@ Fug  c'_/po# InGx6Ai\LMV/)Cӑ`52xH@O\eAuc q!P}gPq`Y3 13\S .ӀaLp=c`8} rR PPCԎRov$;aɏi jD0"-Ð i[[%#feI;|dir[h&Cr^%@Gg`y7-gW707C uUn:B"+Bxb2KRBqŬXSP=94F[#w4mA]VP"8%W艄eikmg2ׯP425y8U$F~%Ot2Wi6`VF5≂rr;Z@-c:P YGSw(W`\ y:yQQ"%0;'Ňj f}Z;[YHc9D& SVGAκNʤNit GDd tFjT^=ti-ܜD5H&y=/EqpTesy$'3+V:M/FX\ri`OP8q %i5ͿBK%&/rTaА1RӶ߀ 20W=1MYư=)(pR=~ıWP'_Ϣ?_eS B5Fl7cOV8XǯURRs]H. *0M)}'|2ӽVsÀz`g@P}Lɛ!=CEn~.9x)%P15 0Ӆ Vgm癘5RGZA+[sɞ%D/Z2n3>,.-ڙإ-1+(c,R?J7(ʼ*d \sN>",ꪩ\r$6@# .\ȕJ?7dz*fc@HjchV%y0@TB9#\\LSQ :W B| 7RzPB(Ar0K e͢bq 1mF`vn96# G#M̶tru(uҤEDHdʚQB*48E^1gJerwe0MztkAt|ztr1zc[^[@8\ Tp=fcj,K>:mȝhe&3BI Wc&֪޺z볯94m]rFYx̺Xq?_R\~.,=up6 uQgW:{z4OB3fˌ0Z!Oօ[ZTqtY` Eq<% )?XL58\WZhgI҂}"zT߸V"f ޗ:rְlOPB jb8 :Vdrn1?@bF#?4jS|bBfKM7Г>E#FԨ.ab=͵xw 0&td nDgyB{~Fn{vv c)e}Fd:=9:$KgUZq }M> |2 cx)deh9VzxCg)DH2eI햖rnMZ;XS8B9 >H/Oe j~ъW$:洤VHu~:a)9e7"|'lG|{c'Wt.?&@|4u)NV0;9%lL+kSݷĂӞw_9sH2Ԕo[*\lyC!Pd]PԪ\o`6[R8uxm,Y&/٭}HQ5{D(d#hBDI|U"AЃ ?wLE>ZooY-6="%X:13X`mzw=W~^t3m8R;jjkmu>0D f³5ϝB6GW00 Kb~,PjFx-B/B^{+?.ḿtEsbXk| -ox#\Eer"]rOka=D9w=V"3U5:l}oC,#~0FVR'Py3MG(6Jv7<)ek܋ggEY[(&xdHi) Q16f9 !ђg|wK'69*y t@&ufRŨ%TY0l<>] V4SxoE'Xy #%^LkP;#oNmu's~<9SaE5딿T\VACT>Vl:x[n0.MrNEK]'w3@em[Dn6~ETGaҫqLR1]W^x~kxqar_on$P3 2=ܕ—\>F dyvxIfY5ާҷ A@oOQ8|@(Fɱre~71V[^]uu9{4@'J.HS=G {e,z\3SeH^3o ! Ԋ .y[rKزOY{tq)յm}k挿! Co8veU%#wXVBmhoj9Z Уp0(h@Z%7oſ>ÕA wz> (M9ɻ?Ass, !1C_dļ)pҋ{}f|{)/ִ;rc`L9j7XZ-|cX+#g"š$xOC]7R&3qGGͪasWW`lv­a~Su-KSv*RRl `ۥLaa^Q7S#̶3ydԋJS{4G-×:$C"Zbo nSoraJd*a&_zzث#k|ݠy=@j[Tul1fܚ'螙#Y7FtWi\z6S]O7fjOKk'!=YQ` %&K>v {/̗u%< Wa!iEM5x"SYr8JW\؉\yI'Wm?gQ/X k.)Re5 ښsi;du*ujO먽Ɲ!̭39HSj'}2CmZKQ=be[`&3+اd-(*]G*T7&ϧVMe?b7f]f0:C<^#.˺(2;zRa ltƠLsnyHKPJ;fWXG-T`x"G}=#k  ʃ_鿆i)_a;NbOb}u"CS@ ǫ+&i7VjIۢ(Q4J?:_gO˼0X}S넘y~UǑm۷;_UM1W[st)tltRNvwQ;7w~d8p6Sd}N4'9ȱ8S@+( LI~[Ln eݶo2;H'a/n\bҍO__)]zfASھe݉WJ<K ˺'NSǿ'-ݙbWeRw'FdR&?y{Sa>3y\HtaLGL7B'TsIMLG[} 8s,a:eܽ/WAY& 5Wn`2h˸R 6a̮('h|S_~'5ԼH=rkjps^a= ;sv%Wƿ~'%X$W"˹]n (t|SٖR+c:7k xtd8׏D-(+SCn޼zkQ@|o/ЊH8Vd{`P1դYH_#~jŭ_ƿׇNҡc6}轿Ei L Mߔ~ڃ(v^#79xqH0P/.\L:$軗gk'̗mc[yEN:mY6I7Z0@>@LdB5V k:Kc7j{uDev ("苡*˶F9XbɠYUAPh6 "2iX*!;E9i.XkEG1C  \ޱ rDGi'm&ç9% 6!*H }5DgF~VNFQpZdGX.&~JڲL !f)fe#1Um_`jSϚ!fhin7q^7'DzlDg  kZkߖJOh`6U/h׶/>†-<(hUn CU߲cԙS ,>=\qS\銯*l=蛪d_bj-s,M(g))njމH71 z 42R3,6xjip~d`{{WB%X@^cGM?Eq:9O4/XW\56掍lBBN#NE=iE*?r2tEI-N/"u8JZh݉t)+,JHtAfW2hK|G2>B 禇tABڦUݰ @Hr,UԞJ`i錭uָ֮BI&L`0퓅>?af%Yʂ8]Z4B.nG6m:Q'!.@wF6lm /0w8oUM@d<ӘDEgSK|3E33O޺!Z $JU0'_c;7dn"rNRPaqԼ3{7/q 9OmR[[ VEmD[CgUHjۼlHbC1q#hM77҄ގ'5U˘UJoFH*S&^oO+)nJ)TDD=a4⒆{{ժr}kO3Ig49'jf[8lzS3=p+2L~8gɯ~L^̌ I[~`HP3 F?̪8kKL W㹌s'6Z|2WH:vMȧVYEmJThxI$"Sk:DYi*"QIpw#S?@X:dq20 ܵJ|ѷnG:n%jnnN!n|Zh>b994A;6WB+m9mN -&{-ךKE#:pd\h1N#z]'JusJg3^?eT91 3/9 *U|&e?MH0Q#rJgcA8%*ޞ[߉,֊ij6Pi8fQB0nŵ"n1"VXÆA[^-i}5FiTZQW,ڰpepXkf/qVT$nJ([,kI n!D93մ|u:Hf_9+wyXRoT(}- pGX`*hEƓG>]{aW+XޛLV#~CB$W!>uN"4l\_MTK,d+éZT3}A} why {U??3keMЈёYf&I]'B9Dj{S_ Xo6H\i@a$+Jb0`Mۮ1w-nX@%p4r~uW|n}%!7j IYf+ |02VBmTF65%E?HEH8>Xl U, gcܮ3/ Xg\3b.7Z_~yKh |U-X6w رsuF'юX$r\[蠠I0dsJ\KVk͘"c6R.#ԙuaDHSa>->iqJhWSާ#+;rpگ_d{*(xbVԃgOWoAw'kh=B#2LFu[ؓ;aA7荲UU3<#2n9bӆqXGOƭ4י PE5 $;2bEl=J AeOZ)Oݍ$dL77+{,͑K,Yc-VCq[Qʡ3$mkS,k5Z\s* d2hWXJYxˡp,>?GL?B?J|h#DE`~VRvWfg H=ٓ'CgE4(sI^TIE*eUHVTPƓJxsxJ_l>|3~\Q]ge a9l~-_2l∳qYKH$Oh}YT/-1"迮q[K4`wtD1eQO"g9Ä?Lf!?yOc›UÛ8WhL Q KB!T8έ>kn纽ȨMuKtqJGFǔ:?%n |m>x,Z'"ަPw&RJ<ɝ pjqj5_jw e9ƀ9mx'bmCiOK63Ɍ,Q+N+]ZKֺݮ8t5ŭcmꉟ@;4҇ h8]M39.ꨌR4;S fHޠV>نΓWWP.]pF>TsuWRC#YTƲ"j\#lCx )NM{N7ρoRG,fLMU4l2g;ҹ\g:•+0n2p;+p 3x|f']{/^J' n^d4 A@(7G(y$> /u*!}z(;v"1joG8ci.뛟`ˆ)ku K߆?JӰ{-Q46G-q*߶oi6#qQޖ}z1jO|G8Ks FKyP`<'Dx7Hn,Udy] H1¿R<lA6Hy{'J:cG!l7Ň< *V!/y+bM-Ax2mo-H&y6za>Gn-ʽ o K-!v3e&(6r+c78BKp Ż(k9Y3&͑z }ݳR5D El Q.t{|*B.3FJ @,u n:.^DgƴV'j!f A8n{QԠ[qل™~PV}<$Ҵ(TE<!TTLj;5N $:_z"߽5GɧbKU=[,QfLkR .*yzAeU6C%2M _ g +3)Eo<+rCvDJ@ Xmʇ0- Ѕ%3@c߭e *'ucޝXQ5T{ XLNGgOO7-S:SGS`DXFr)(bLzhF'غܬVGGLA6(cS>{ "V+K|ᙻߐs{("HB6bV5Ѧ(6m5ҟ0嚦^2=2)% - lѠi}$v5d@j1L{ %NӒ4wtE D;|qo-ɛ xgӼ 9R#Sf e<UXm߂3s3!2?5r8 q=%_0jS| %PkI68 QBy.n"d_A)D0P.@LRB& 1FN> ?\7Dٔf<L:LS`zKV4g\ I脌V\2G0Pk vvg*.;  ;k݅ pi$|=̯gu-nC$nށble]y gAмCdAB*o1He .*n Ggy]bq~@ ɒ`9. | lHvS5i竕iP,ʚHG4l}pb2hS[ٹ(wө2r9gO{lؘs|AQT ˫$}ڲtHLЦdҗ籝B7ežgOQek7zI|8ڭ"5KQc!KIġͱ ;J8nsf)s&@* jǝxf[ _ۣҏQBF6+pؚ4TNebE!*҃sTTٲ91:xğ9%& IۜlH|;w+i h j5[_ϓ#A,}Nd3Kf T _CNW1j8,2\*"S*v[opB}1WPL>:,ˤ RqG61'YRo;Fz6+t\if3BǒjᅳR?AVaUTU`%w;knP;2Yǻ<StYZL1j©_6VKz(dox?X|HJRS`A//?,WrX|BNrd6EYaQؽk 0O7 _f Pˡ5ۨV ɐQ2ǵEaNMRn\oz z!TcI&NxP+Н91׳U5Kȑ!2RSU2mJ)ܬKuCݎcc:0W .GpfŠmquÒ6Z,^0͖ty ՚gvb6RC[C kcdfSz4s*ܞ{nԼof|N.YI5swI^2Pm/ĭՕkqjaoynTƏ=ni;g,M-FA:/ڗ݅4|^)kv{q h&x#8\߃BN?M%|Oz}G~%|#ŗKݝFO#fә~d4R9zF .{; u }2+*lW_fy3i$ן[n:}L3?VǾ,?0Pl*H,,X/]y?e 㴸f/0|* ?B [e5ħ@Q)j*.Xt ŐϋnEdPJ% %_%H (_RROhЋ>ae 0^feN3aY;YYX߰l?tqf9s{yR_˫gTy7w99 !*=U)B{^?o{{貱EE5{l_^v - KZ7=TGr4UU]p͙wouаO|H9Ӿ1[6W\mP)Z% 4]©"VPBNJl-^m@by*3Xc7E.@ft!N1j?iBi]QAsߺWlI59"=%x 3aJ8DDp=c4-k>?-x+͜6m@_'>N.LyZ*Jd}3Dmf|4U3ȏϧ6&{Bnԛ:~C&:1D$RӢ]&er1w°$Y-[R"8+|O3C .iK睠~Rfj)$=5(/h91n0^̝v1RdsTG}#~-K?x8C,l3%18Ylr]s%tp3n=ƩV&S=@+ʓ[ {_wTumVʜpﺉB~lx RQ3ތBڇI5KhGj+[0:=\Mmk? _yF1SfVƜgbKit'=(Z*eD'.+eFDbV^ሣ'%3H$$M`]T!ڤQ8kPiUR HƳ84F h%&=B Q77A 1$qF[K5EHQpNc ؀G%eϠh8AT9}m%6O+94܅!p9RMSSΤkت,խnABs)X[SҌbFיs.|jլqܻA<7W̏Vx\V"lD/C}7Jk;ғKJiPU3œ" (%9SxNWP&CQxCGI)Z821L3S"qOY4[k$EoNWi N:iw`$Y e,֮4)ǧT'9 P83$j-d’N8 7;+, mު)f'~1l/r4I+E1021 ܏GMZvN!y΋e<VlYJX 0xr^}Դ@歎ߞ#V|3QAɝҋ]/׷SK2y<<1uइWffCxRZ75ܺ=0b٫kR':0#!tRJϫZ ى*驅3A~42%?+˱x| Z݈m==4MPH"eys,W+S擓~Bە[._,N * 70")ldoPzBk0G0أTJ uAk8xaɱ-EOfq;_`Wc6 Ms56j{S3l0?xz13wUR(N5iZ*O=iױ$d$. Wbyiacg xۺF(^_^z٪;t[:ԸË!!u^qac]q3 CLơhZw~U/$N([ !Ň.|ss+o,hC>#?Og̾g` )Qˮ>ۭwYCIƉQ'+7~ #A2)'aLE>Hp9K@qF0Z| :7Qty$n/ :uqڑ= aIHJ0$SZH);f;0ǒa U/EV]kܠYi"L&Dv2`Jv1]Hǰc/.X,K؜]i4Qx6QR jHp g 9cH-rIZb/*8,U  봖 .z7&s:bo[X?0f3nyuJ&X.tu!%)ko2:Rى*"ϞL~ĄxMP ?TusqgsGoBInz& -L>O2'E<!G3̇kEK4U7}A`H /Vx3`g 9?'N.?zc 8y2\y_-z=i~5ۜ(I,kgK61,9=eSVAxSxS( j{* mdS@x8/l›`^`3hȤB.E gD;eiiJفTnlI7lߤ7<=}!@XMVDx_7{=(Qr(䎧Uk(v7dў>ނ}q66V(L+ E? Jx#^4":d]dٕK;~- 䩐 Cߐt܍&G"F9bX$4 иUc7G˂IZ@7*ϰ⸞X(b[qNӊQ!3>w!HaD$jhSxG8`/٥!C\JB)o tOQ1XQp~8Fo9k4g0!Ad(RfaJa@,.u 6 TRXF! yi勵\r"v"yч-V8fdd԰-ncc/[9bllf Ouula1sY?};d9 -JNᥫ4|u=7fNږDc}C5qLX`O)OE5^Q{Qztci^nFS+J*CS7뀹!2TGqv㘻:tL,u7LRZݚB8'P~ݪg*0Ïg1/ o +tSheOgetjn4N$  b{ԟƉ>aSPaZ' ;|eA9=w^;tV˯ms6vxOQ`3ϯj侕@jo[^a3 ']r&{:[|yFUH2"PT&yģɁL܆ ׆-wq5Hвh, 7ylB ֟%]ڣ2!:{f4hyD:t6܀,ntgJ.WIgC'Xi dpHKZF RCƮ1">{' ԍ[h,{6-Žj>b$H}/4 h `j2O_Aw}'߫,~:|gjL?:ϸ.<ĞzYm]U+3M@u1}L[m"dGS>Yz̿|\T]yH 4N^1_ &`S8ujq&ՈG6~Yx*:&M{nzea\v!sVd^Z< }IoWnjuULO@;,Td}H4bilX/̨y=C8bxPݔ%,:Q~No1ARHA-7d:BwAl&rbp :Xmx< FrrF,iPyՙIߏS!astξk:l"R6_proj%DdW*F?6>7Uٺ}Oz7Q^}mp=j=OQ0!~ҋV]QSN 3^Xb  [Yz=80u(Lx gEvxv&P_jj x,Pz@:,Mbja>uMk}~{ccզj0^_u`cD v7U?C'@)e#4o/:$}uưü'8fQ"H NV5Z\ 2#4"( <-?I*U_!NE r~271b!W5 K'#A>;a9ΠDRT6ϚeBSe›bRM[RR \]]v-;H)ߩa{7'' |=ywnEr6Ro`oܵ u3}rjٕ>C"[t lϿdISbH|ߠ+/uyg=+tzj $n~)R1Wŷ@w2Al-y#5[,'BPsݱWHкc1F#wOx)v+sF_k)æEUQ㑃Ab*\wӟ•ʕzqX}ju(hФ>WQxL,v=Ď0+H-)6N\Ek\[dX \; `-ƨțPXItnYtlZcp(b9< 'o3 AG`HXev&ٗ򩡵ƎoF@(K{,IN:t~ݎ{z?k<pUY ;KcA ̥NO>=R&ݏ+JW8\;^.ܮ׿(?_s*?]&E`]xsw;&3Th@-'n'ǁAﻑ{pۻ\`ǫRfd|jp m4ܬruʥAp4MwRnUp]$g3iQv!6)=]ߗTP-HRoC=~ ԁH:(OU7T _bH%b4 a1ģ-Вxv*ᠫhMu (<+'4{8Ii(pB+^#o@M )Dt! 3PN%f ȵ˚\5xvNNMi[5)< acbL׬(V#~^'^]effL. w|Ba ۯ֫XЁXiD%԰ѬSp)Z!.lۊ]"mLӕO /*=8)Ъ՝qn48k6rt(%Z~CYnMU;]W@eL&uYM=s2kBST]pq/0fƆ,1aDƱbcRIi%R9\'P`]Gh$@[ױ(mE+mUj:*d27% I%4#,Dz|J<4CF/{9 ug/]qj`x zL4jIV<>7L2_birHY#lAXP6a g%^:__a[mUnO`l&%jT GbMUD="4E"`&E&#8'l3Tfˀdi}k]ҍㅭL 1#<q, &% E@as*25thvfqGnƀ`Ey2% `I\cBl1?=&4^[ 2=!~gf9,k_ |L3,PEL ^POwo@j$D8p]ڕv*8)dM G<._Z9&wHQxpi] -2H iX](e *𐸜];D|P(nSE.ݜ]ss7Ă.eL96FvTvRڶdϸ`҇oҬұf_/Z[ ' ahg1b@.V6}6m3{tO;& ]O%)/Zo8κ]4\YLKuJ.-!Ѥn[O}0X=z\r U\wBCg߅ v-^1A?=tюqDoX*vqYyuϖ6[)G~eAh270R6zv`8ġQџV ؎u.UT}=Fkߺ"҃c2>!D$;eخ@&˧9Γjе`8T o6mMKq 7K' AWԗb+g跋0g ArP?q!$M͕_)R"xg_/τ@Ji1-i!!)4srJ$6:>ݮ]z\7U41ҥZU~٤6a챌Zm_Kܳ;AZǞ"ryF-Pe[D = ƽXN[>17reoM. S k$_OjM)-ykσG}K%GPV‚yp= |& H ƒ@H2EМѨflW8i7Vjyr^"xan#QA=b;, rgs|4qceMxLI"lS0)zI<{<ׯ贁9oS(*7t(h8.%PFgTFU TzL[p|7 u, ˹e3S= dA"hOp}m3|+`[˚o?M1t`-1<{;XUSd7 ';PYD>pnhVӘMPl|1՝'Y7|2Dv t =_gh5d>wQT DZ {SUEe#:yh|ԯLy5 kբ!٭_(#/"/bS4D 8 #5 hLx 7RJ[@9?ZЂN6u#Ȅ4S5;4Tu(lG9b:Yv]Kp7hO%d5̫`E|C.n8ײ{\PZ)%f(#^/Pp4` T@2BIS<ǃĈo?Tu83ӹ[l㹛 K-Єn*`Hѯᤏ0S&4M@>d׹JK"h}·H!q?vuY%kRaIS-˷4}U> 5_塑L5 VAZu91W9zej,$527_FRRݧ7g;;7It&_,ZY"$؋RŚޏ+XW_W,R:\(Ĕ6)NucIV2QUJUz3tenEfPBWVy*Vfy2A_ lFQUIr+/3 M[XREٷ71rCQ?{Z-7]]w0^E#{zɶm2Aшͷ)X%L<,DŽMy4eaXʀv; ]iU-RIK1V/e6A6NXHHq,Ee ot[:S[Ԇ5 YB60)M]>3sgɐ$&[NVb zqeӗ=̗$ +l5Y5>v]) >1 ʅޡ@a:}%?]=`bȵƕ@vU۔1 %ڋw渒Q}aUVm^Z  d+چӯP"SQ{Ck[n}h8D?PP~=HC/jh?ۓS*$M;GxH!w瘽`Fb%̒(TMBr v5$!A])yC(޼ܖNy{Tw Ko؞MMfIOjo)3a*a(6)"T펈jt+DVYLj+ B*WQIT*i Lӽ]nfο{ѕC<3]zShcLّGj)%jͽi[0$Mjfl& [,ws]K*3 d4G0oe@6ߵ#sݦw3 tԕ:XU@ޤ>Y?P.XA2b76w>`C ˀ4:Sq\^& X,e2TaX[(`}ؤ3'H,E#!V4BL !EF8. yl4Bxh,y4u{VsRi PD4!wg8 n$dOELBٰ6iﶻ$n?Y@ڲDnmme<7^/fӤJ1)Sn)T\Υʩ\wy^尅C՚=P.Fû0ZA,abQ~{:_ tmm:vd w]$4MBq\ 9z_oh6hc$Lh?.x̰r-ues;`LEv+).;"AA'6 cwdɤ6TCE4:欁LJb ŕ*fS+(&rN|Zeo[JVto$)4'6OAۜN"X5ʇ8F1gXnfԔ!U{ SP{ry,h&2,J`X$p­ͨD$44,J^q명<]ً?@B*sH¥e:'>M) vOL9S@%%X6Dd+wC|0-LݟVZ惣L?."Ĺi6H,"?fuP'‡/=\P &93mv.3nLHSR=3$ ø|wMƌ~ T @&ⱄ |nex9 ,Kh 0!P>h02mf5UO+'/ ,:Fՠi,\.%7>cl.?59܆$8Ғ ^BvaVvPm8J!`u0$HKKA}ݡ/娴zt^AK>-haVgbA;/LU{;>U <)FsdSG͂䘜D45ݔ9^EPcJ!QT%8,E:)zVyCKOQ 6) $yD, CJnQ ۮDrƿ&#xИ7XؖӿcŕPXH| I.#5bnz%S6P<ŀ~Nܲ(+^>'o/v׽,')q(&G!)f; J ЧIR9nxX)&68kUB&Sq-+4mphj[!g`,R|Ѓg  '<2 dwfU)|G]"Riˁ͏/^rFJ,}qt0n )>)O~,dɨinmꠢX;$"lj6.C*m뀨?!$x:VD5ExJH!wʰkkwF8>v_NvRk_-a c<'{ARxdϱ<RC4`ZSԤ׾X&.P4$\~ 5O={T_xaqm'z(]ypȹG%ش#] j; ?<Ǿq }ucx_<980/QU.óKzj3x+q릅yK]mĉtL62db8D@5h1]uꔊҚ޿w-$XăȲ-IhYQl7)4c5Kʟʯ|۲l6Fͨ{rh-&Lә*WuW4 %{/+RbO=z5V4myӰ=֮Hɯ$Cdu6R3t.2{` 袔Ua'muc:vj?@ڧ?Y{ezR^'0q>l;Vkϡ%-*+3!/%Ւ&b'[0c/T{ZǙK)-V-Udh74݈wb0I)D~[8r"S`z ]Xa+ e\uKSCzCl)C$S4"qǔFV+ =Lcs{2DlӱSd:=~$48IDŠ7S\UjT.#%Kx myq9}\<)f؝߂2҄F顓4sHZ{jmPx9 uQ:/!Ӿ{_kxL}O[i1⡈#y78둏ĝ!5gn9v-Om?:Rg %B] `^Gn'b`~9Gؘ5to]:WJcĖ q)osW@ {#QA*?g"u, -Ҭd@DHB? t], ųNP"6crNdQiLB4Ę-tx3ۏjRR#'d.AJȯtB+=\Ah=96C-C$ I< Z$k5[ߠE$@9egj'o%fښhw?zӺ:{gA_> {ƏˤEQJs, ^p;Z޼r1T潴nx09P3}[/HBݯ.iL AXD[*Ζ1}T~ 05ٗ5w8𞔆XLd2Fp6MC͓-yWZ&Z j8Y4H uy(>X5)a^;cd=NԍNuTSUݱXGfs_p@ccpHl/,M=Q^n*ٍ m%ڷoFW; jhQ(6X)h\p~."hLk'.@> }>we*4ʿph }Yn^͌&eqhTLғ]FП&~ ÚUܭS{\K!RN*?`L0683BWC(u$uwwSۊ>Fmg fvo#}+yR; zDrJ+Ƥ2Gs4~;k">ԬτQ|h-4v2FGM=52SQp#o-+n7XHamHCjk 5(8t"/ơ[t'cDLKtwC?~#qȡ1!4wjƻ\τ. DVI>}4Gq~yy,ԥry OĒ7R%ʿs酁)cEW]Ey:;];<嵫uI2(%n+x`fcmVhpTrS><]iW۫{߄ʖn dĠiwHT_uk|G82$PZy5s.đc0W Ci-y.֧V,RŽn$Hyl&,"6"V 848 >ot%< 0Z֙=`ֳ҅pD>Ju,rpHOˊ2=y4SၫLVJo#ښF*Tϼ^>sUBb836$*կR<u]ujkjT J<'TNƒUu1nDbB"*14hP|H:y*ɛ shM/ uM5/Ld7,_i)Mw:?1F# "+2LAid(QWC:e C)A4g~`&Q3)bA.)p&d"*ϱE"MCivu4RQ3kJlVzEA]$'8u1wTxŔ%d4 MK'c£Rڦ3`9'/pF6&JI"b"5#7 P3VPXHyy{EQKl&OhE,a4i Se"&[A$B8xl=KnwUA4ʉS.VNk`ez9|`qz3AȖ~d}8񑻂6ʡ3RE z%00PF8C蟐"d;(R=jf 7IU~4FwLT ͳ@"Be]ALxI eHf0:beGi8X|鯚F%Gp,,A}7"y9c0t 5nhČ 5jv^Z(0peRIY1=xDf?17"5DZ*k'CU-b*qYzmTO|~SY oPȄlS .O-DC zZcdMZ L]nc-cM؂՟];Gw}d{J[MVx7-OT_{W T;P6.HDDt|=vBl{k|xy)jD䜝Q;.m2vP>#6(03-Y! l۫ F.D؏i,qڏ>kb:rEO꬝] |o ᕐ;*= 鴩D#h6y&wy3,j5|TL\0nK͆\4M]}raDqG!^ηs?=0x&YIOUz&n=cRy'pqY OO7{ÈѢÈX0OV Vƺ(N{%Wa.AwDu(Tp;iԆG@Ps׊ I:wt"*O =OeCFv;iz&=؋ӈGLMN]gpC3c+&c(r6g ؇^X>are ~U ;UlEq9OAض_Tj>Ȯd 9^KλYU#yc[ci9F|ҜBZfR &CeEs9ϡq][#._5nmyR9}4~"F2:Eq1i~"2Giq1q)4t.bv8zHS%fDaGoۆׁDe;|5"OE6& Q82޵{ʶl\#5LtCjw&-[) e$϶X/f/tUf*JQI@x5.ہVNf5(h܅-WA-bKrXB4޹˴y[U8g?K7alsHy@ڥۙ,5 ؐaDܠ㊄C#t.jgmpd] "zxP+W]<cErjSe'y&Dƾ@7{m7^7s03]|Ƭq)/0s}P@%~k_0.6Y;u@?T\L=:ǣ|=ΣQl P4q >B]@=$N@{V75K/^bጬ08flr~k/;uj\!/!w!*s6OFrkoD6OS7\Q/aȱJn{sVvglq]R_!7 hKvs|4 Sm'G"?I̚8wKE}1|19$,Z.^Zb| omG@[AId@Uuz|=1? _ 5i]ENPEiVPj <(B"AIrb D8"-V`R *[zE=9PMfx0}-.Bnl:Vd9 }@|ƹ. oԌzV/qڢ]W(eԭ[_݅DTEl-,Uv%/gOtq4b9_hͷ}NͪVXLc ot|zV9 bU̬V|4[zM>`G7nX Z\u] S_W`"J<"w} {B0V,4aQ[A9qm){yGbF ؉\_4s*5s\r ER<3?9:ڶȟ6GWk$|E Hw1c !SV" !k##67Fl! `a"14XiN21027ih>Z)"sjGhGI}Uu.}tgӝj{Fi@22_H柲Y8SO白'6Eps= 0% KΨf)³n:|xg89뀫 [;0v@h2`y4ہxϲТ7.'.uh:,\L Q8^]CYzO;bӼ{ilq 4=Hr?Rb<]`^ק1^H,G, ϥ %>LoaN81ìY`$^1~}GS|/&$A;ͪ -mWKZoSVfͯh:s> }<~'pћm,U_k|sڂ` @= &2]dAڂ9y\%q JtK 7 \sK>[ExK-|- aO, Ob18Z~M/vTZS/3rጹ$ºlG'={é.>Nbs L l^n؉-^~_GF<ɴݯ}ě0d `>Z6#sVJ(1drM%\GO S/ZbMGŁHפu.@=`YlUVU5 up?JVUӦQ5Z9l%vdڭR}wU!ҤVK/-.kiYLZU9An%[V45,ƴҌicPQ Zth7p[ķ%R8'4UMG/i5ͧbCZ]kJ/HJ ֦.r8IXK6zLEџeҙ$ ='=:W葊# 2χƫ,GΈjP&b5POtm4/[V$B(.B~y>ks>r`?;tm^[Lit5/.Z .X*oe0H=w-k{:@k[pCK(~ GP_uҚV,xTh`͛(ӥ[>2YX>)ȱ4ꨄ*F[u\0$ȯC[׼oBk[lv)~-,mehlZK pm,/p63Z۴^#pgAXG=W˔u F_۟?T/qSoY.zKœ͎k@Q5600|9r8M!(J= PK*\ĥؾؾSh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-cyrillic-ext.woff2nu[wOF2>]wdkxύx\*hG\@m> svnw$70` r#(r-0/&ꗯU_4ll{^~E4 *F46t>Q#@I& vaC`;zK ێ-KdзWgbn&@ >!b'{~]s9ŽݝK-.:F~EFn|am*l6!Ht\U.?htݾ_cHǘH?؎Dow,(ŠI`L!H4 QBТu]ytUgNhHGn{ǘot?Zk5鈩( Q%A@@;QOGBPnBMX`ծჇZ \☼%,,@k.p:o+We1K6uIekdJRm=| $Cp=@yID+wTDAWB| \)m"Pꄚ: n88ҷT?)n @2, 9-]4G8hdhUsL8%[si!ΒQ>7*4亞g[A2sIlRi6HPO50N9c ך6<$fgl7g;L&mOTp8;6EQAHB$B\ZA{ϓ}cLʤHdٞ1b %H</x]eX.8#N ?V+9)6H<:h~Co':XDaQ<_~R bfY?}srm.ap{K nj߰n}w,gs_oc9 /uYFTD#'vP 7Qh;9N䭈&q֞@N6XaCid={ډ|k'=Ӷ M 9\UZ]+x ]Nccg01+Q7~7]q!QgW摽((^tc|11ؗ,'cӀ9Ș=Ѷyb<O߲!OӞ̟Zz>3D>sKKCKs˸W&ί"g{~я[HwD?=-?p;COzF#~b lY=sq'?]:}sA_6{kbǟJg09_tae[ ^djKťG}ߺWRn+dX\X̬.V*^e9$R[>:6nc tɴZ%^l׺VmT} J 91zXچnۆl%Z3h6Lp;<1Dv lܟ!g I:&6tiH>#Ĝj☤W';Uwz4:EIiX~JeΡl^<㾒)2Ix"G o1g:ھToVZZĶK=k%hI}q.YIL` fziKSytC y;[Q%-0d gUՅVMa?mDM7quwХڥS&>èfCFl_5itWK].zb6334WdVgUnqoɁ1"_R\y`^gO^y7ʄ"_K.\:y=g|_t*TND`5]ZЎi؃^ڦơ B!\= zH-z=A-001UmP,Ύ(ԕ.OD1Ȗh&`0YyDH@ITes&dPB[AmKZZ2L6_*116 ٲg@sȓ=/|9p8ACHdd6' fn]!sb3sΎ0mnXCUjF+H 5R?*lxkI+PQnȻ Qr4^0xuĄyC1 08&t/{|wA1dϓMՌ:nI S5 d'v|)-a}}D *+:MqH $OHr{U˴"Ԙ6?{-;GLyCkg9{RAv!&Sk2 ZUu\US:^JC׭CY _p}ti&n@ Pq*<aD~mTwdyO-eٛܠ7lK $y;98֊[׋ muG1]( 0Wxc@(Ҍ hW k}&4v#F VK~xĕ/dQٍu\cѦ.)VB=zz=ĥ^Y>NwȆ8lܵ}jmUxEX$a`1~.'ubS)TWa&pQ1clt`̿aH~a"'n Eqt|~$?AwR qE]t%EN|&}3`7&jo6{f"hF, ΋VXt!!$>Wg^ 8;NzwЉݱOs ؍wR:Nlc @_12\:Su^<*֏_!ҺoO Vy@$f/6&qۄJ$'qPŝOF|2w%K78hvoE;8 EVWrtuP'*TS/䳥2m9]^ ڔ*"VMe*Pa $o( BUxx$flGr|&+Ht!;͈dZI8נh)${o8 k9ā]{i"o{Y}.A?}w%af!CフB8\uڮW%eڠ]fe$>Yd+1^&\ P%~^aj[v7zT@ <(cHx_sU-@.) gBXȽ"xa#B)~H֍0!="[H\]_8>j ffi<^XEI0H/69Zd:sjinj,fdgefRSI q1 ztTdDx-4$8(0ÝJ! n.Nx&Zp([ /OWJawdԂ.v+\b0.wL^&VnIP"os:fsY[կ&@'`IW7",:ү=;ٗBFCYh&#=xLԅ3H M-L*J8u X۸~eJvw״G,FsIV#Sf<ɒRLW&%T8kpLĒ{;4F<+H,I&I KØ/I9 }q#jeoWZ|5E2^ͿdVǤMݭ`sE+_-Fڟ vE6}NX"iN8e.nOJrnfĺǥ%-XYSB,aQl957×g8 M>’l]QW]a:$Qz yUu5"[htTsC "oKn6:ƸJv EĈ*ݨo>uW]0(,'\1 ôcvj1Y8K RdeWl Ie^>(>:=mp+լEjb`bPr{t=eEbD."q,Əzd`XȘ"Ss/'/y\߆-wd}['ULFiy,~kA2H~ZՅ{ In_d6NlUΆ~6sY,,?OGaY21c(|;Fo4X\SSR'I4!-r4'Ł+ٲ%U UV5iY*@%jzb1LD,Ņ$0bÀ.8T`FZ11?0g^ǯ80+h T 4 q%J%o5J8,o@\S`d 9-ϛOd9(keWhwdGjSOpV6Mt/1cX}(@J\p+!,;CYـ9?l99ЮZt2tsp=!kḡ%v zTS=FSд8s+5Y {,E6n;8Ϫ;!fhëIeZI 5ҾW&H +~dpqUNzdg4hB W/Ba/fN>kB=vzF>:1h$D.r+).*z b5_9V95ڳ˕_Vj'U~HByR(H?]evT;\GESZ<6l L 88&D e Vdйq7yB0)I hXd*ŒLٯkub^pU૜|d)|rޕڌX ۭoz50(@$u\t sb!z+<d#]B[;#skeޥDܻw5>ㅗ β]'O,#nsNaxvod~ICvI]8(#[R} -C,\Y1`!o|-,ɗehXCw٪bK\ R50'W8 i҄;ҘaD<2!ne >Q3} "t $1ˬh\B75->5y|ߝvݷ\$6liCGF,ߑo,F0?L)PǜV͎]"fq~^gMyK2XZǗY|֢\f4mIsīcYI'YCz{%h5ݣk`oq.𞠪KYK/6f'r񸣔b,7/&2齩Twm3i-HpQ2ɶf-xXeDuJe-FanI$||Ij4%456ͦMC8y+z)`,' H}~~OzD J7N Vpfiw,v?}/wmdNV)JdXBGzWfrv)Q_ZkcZa[9}LTDؠkcli=^R ʡF@"Q[³ ˲$M^}0,V;`XM_[PԜmO j~$*q{m2whs "HN&#~ P(=$ORR>NpټOr,~Wh!bg5:qPg+D 9F3 4gH/8)I~WX+I]=n;?@] YJ&]Tæd\ˎǩ"R0Wjp.~Bc@-n6?,wIޕR=9wIo4ît;+}JB#إMP8T4dKbGA^]|N1)]vKwDʌ)$A~c0oeO/cwJ+w/֜Z\s`An&i⼭ϑȏ}]X;C{rݕxZnIvnqEIyP@& d?\L/17\[l<0܅:@YfghjL}h --H9ol.vJ_>b]dNlCΌOFClvsL]7$^֎%9Gpxv kc^`$h7oO&{g>9H@4i/Ⱦ[D9+1 Vٗo.9?SIEb ޲(Si1i6h|x 5<?49x76-+;@(S DA& 2dأ.<?By.*nBIC=hEɉLl> "ž~~.[ FfŒʌZP_9(!!]~s!_ աͣ,1裋?Ѥ 0#>FS13h.?Ox8Υ>kyp DY%M9%ApnV%ueoi'mWV\zS-1ibA 0Tmjv~5X1h!%҃뢻;p1*ϐCV"0m'q"}9qhHk\)83S<{$UA Sv%M $I;YbsɊHN>bPbAKaTqNXv8(;^4 shyB%XhZR Äf2(_! 9xV(SMRtDs)IP}ej.p`SQr h1|*IY,K]U2n0eǜ3FCF!$zpBH{rOr b5& ? o,< *\(_·x]zp] =#.=;\l&_:{nhn]J\-qnyPRZG~(1_3֊?9!& Jh3Īe9Ll =0'?W@nI-V8EOZI= eKtr#*FGǹNh^lT~ά |tYӟ ?*ݡ;sߑk9%:XOƅRs5FMhf:-IL UgŤD.Ҙ|[y0?ڢ 24SyޘzG[J^{S>~ՕT@:5i ͙ùZ03m~1}` .~"@G_|Ym|dhu<]]+%ƇKԏ6Ɍ) N )z0FEG_c8i1jxm7o&^y3|>|~^dHFMm+E>&&\+L赑DoϢ_ T"bPٞ[5;i8pl05qTt"RDZEjtML3W.u;fR`3ENԸi-49S`?-}~@CM 0=`n`RG:oG)_S5\$;h֪ٲWMF d6*v{35S/Vj5l8!KBq u0>u8Xm+eоl&ݕm 9Pse*z*z6e͸J05ms3 !FA%,B#"ij A'-VGVR K"mSDΥF8!}=x0V^lcg`3n0CL]%};қ* udx&EU,ZӁf ✇ؼt̘Sj{!Mf1&"n]A;}0D-6 0.px8Q([-8,IQxiWd(P{~2 Cw^Iץh`jp*Ca;dN;3w]yˆͯ F/ bj~NAlR]G\lJ%V Ϳ*-\,CeP"E0{Q@]K[@v &̵$;gR‚Ϊ&(ݥ>qAOBh(a.G@Ӎ#Q#]T/,uo#DG,!m1äNᇅDEhV7A>ًD8F//3QINC?_FTn}Ɛ*Ͽ,5tSEI:fUdkbxQSQRϑwVK1 4qDp ITg:QW5"TU1G&,QIw&egqV"bjׇq>PNv6$X8XL#0,uTaI<HVQz;0|iH\J`Dcz`E*B);#w1cٚuNew!D''GCQ/ m$=lid* ZiUSWm!eۤӸϑysĤE QiWǤ< ]?H8c F<fT*#%.s훎҈' 6-5gDtF0+~D f<4UҲ׬~ha%on\PpikCk3Ф_keӁy/FWPksߙUSäύ~W% 6ΔsBW3'MUTs-+ߋIw\JUqǓ7nG<<4Zo}kQ7;l44R7& $,w=e^w<+TN<;RwMcU5\[rU$n $=l%AO|6jci+2K11Cj&wfv.i7=I4"4UE(9KJ|ߚw?GRJdRvԔ8 k:* X=B?𼫡WCj0AY=@d~O8SؼoKigwi Y 8JTP|9=f)%gOUyW&/qPs=Z3f?׷JRcUQyy7& .boo,.0_Pq2k9FHwjAEz&8?rt}M}PpDƴv#̖i6(^hÑ$OoQB1;M5ԙ,YO߅$4K_j>uH bwٹ+"ylSP9ۤV)͓$nBwAP:UY3xrhLVβω0e8rwo>%(Fj7@ ㊇찲ꂹ>ZZabq[ Yjj\O]ptYݾ6HTv6[-EB! H,VǙ G-VU\LfA6~K==0UJwqP!%'1yqcuKXm^dF-5csQ?O^]dՐTbSV1%O{l`qTRe,v94'э K'Tzqi[܁?<+zj]LO'ߞ%UL?²[99z>MG\٤܇KPqqBʘtV8rPO:rD0n[ft"ylkPG9"|մb~4Ow">'aQ+;؇j>z^EiV5lf9Ϻ*P'2h&̾% ҂o0z(tfd* yMFElO|٨KHH `78Ά`~7 n3lT6o60h-*T8ffJ5' 'bՃJs"V\ee#*3N5.RyraV=m3=f]s v`؞[9#;f&Ff>|5}C;s /D/ Et1l[Zc r"}rl2FfvljTTmcS[mq훮WL=/턣M Տ*JvNlC uT~<Wo!RAn dYrye}ze '<뀄_*.xgQ:3rX3&Ԅ*̰&T2=2BX :6FXFayC~]@pAP@V8]qMZuIjQ!NL"p\U 0 JM覕zI:v08ZA?*YƓ Z̤&DY͇5 '*#5vtrWG=Ku2+yn| ڤbSH- Φ|Ԥle޽->sڍ6V50/Hme*ldE@ѧ/Uqb sq7ԅ4*Eb .Ԡ.0Pml\sJL&qĄ8=9:^m~QL|ubqtnJ$ĬgQx2:a_Gfo` -;q a-ʵշқC=0ELVR3*9*z b_h_Mdpq x_-ؤ>|% -[aM*TyD͊wl^u@i-Z8RgUm2#+A e$rSU0qNvMEُ<3F2zȊM|!'bMk5ă-T~9mX/6ҿ0y@y\%;;o'ו_̈zIk #<`udhʥN4 ɽ>SK8s!za[#RA?ѻAnD/[)13u D ZDue{6Rv?nNxLYf?HQ]C0|v.00L24)16gXmUS=Xtdi(>MQudu@⡒Nlh )* q𽠟oY4l,B K y"ҽ'!=U MDfC* k gZZJ\SioFZjҷAMy,8ɐB!k~ '$QK3&(emǥֵXVoP?dIUFuRב!ɥQ iMJU5_LaIؕFO#_e=B3Þ 1=AK;7 MqeaiLpAj9.QSqpCzzhV!1)-zٞ8`H_%? (#R/@ s4h{:Iua_yT{\+(4.+jQso銩H3f{ "RťԔnuC6t. 5ii<;Ҭ.Hk[8qlS7 .jܸ8tX2hs$¬AoqTdR2c hbY9aW'[_Z,BZٴ3M0_iն"X>L[;N wήsp231 Gعxq$ Ol' 캚rs $-*>K}~yJTT?9ʏͬdٮmaKdyL}+\g }e/ ̧g]e$F{?f"BUaC==YoonL#&ĺ+◈hS=F|w;==Ѻp*7zЏ 6z eRF|K.ieZ]-JC}OzE}!OgϦ9P`B b7-cIX44`ӞT5gk;u^ӄK0{FJDNӘ#d7sgS9;>[t$ݿ2<A Rkè$`TYShg)h1)LEt&Z!|vgCەQX,3OW$mǵfF1 8ѠR9nrQX8SҖ$f JxwWd>$ Xk1%1 R(ۍֵ7tLjjMp&uu&V0jC]aڂrL,)/wek0 TtVU~[| zk9\^+Vʡgo D۲zeJ~sNwr0q-XKr#:E0e09$ndQeis-H5>$%BMZFJLJ]-QGjyxzM y#1rLe3U 1@Z3FR$F(5ZI^GF#8IJ:OD K>;p>wI0gkNt]E\4q*d8kX\em-l8qv&vJr`z {O4HC+ >mF_Dŕ<-ꃏJqm,doe S .9@C&A{|ss*c>jsNU$qXU)DFCǡۇF#3UÃ7Xݧ_={K7o(9c7_<\|5"|ڎLGHRҫ22dN)*+)Q*UPQV?*eKP$tY NӐX״Ԝ2UӦjmUQ7T7S^^ފ }Vg$\q8`T8Jk{wtr3ʘf0#m ---۬ʬ?{e]s!46*(D#cw>0ryRAPhK4MG;г+Go c!`"0f)/&6bq q8>ucyg}n;t=:_u}I||{_͍F&wG_<_:6FZͲ ސ@vJ/.Ui©PPլjȓ8`δAڇ|&NǷ_شI6Mr*l& -F&1]2ǂ}#kǭ2plc.Gp Skw5^M^_ 'ΐ'X 1!M hWXIwgƼ39Yԫ;=}Iƾp-ꮐQQNkߣp `Ca5A屝ߌzY!DԢ!EF#7![BܻbjWV0z/ x`;=p_b-6­Т@&)ߖ 8 % ֣TKo 0xCa[V#um4SM r5O"z;x;NnL3 `iihEQh&`p`]Zœq (9SkۦMliԕ@ND~v 5mo4nsaǦ\ +4yGƄzG67&~mCS1k>{j}j_DѸ6K ɲc(luv'>OŒ2AMJ#9)[z6 NgɒΉܾ.kODh{JW}O/.{M<͓FzDa[0,*hx^8c[6PpH`װw4m9?#~d6<ϳ2S}'ܱa& ogwX;$<+i27 RGAKWl ӻc;xuo>fnd_N`V~;YTh;Xpp 8 )zE}Mh-4^M#EXN%ۮhi#RS>篢JE9s\K/PL )lD2 j}cVM NVc4(n2[.)pmюv3^,L)ՆZ,IGlM|X&CVU5̴Ԡ)kR6S;K# Ӣاd(.,-$2dE0ZLFT] 4R 9~+G03s Q7% G'^\8b27oh8qr)1$-vnĦt9}}ow5XkV4{a?W"C1PfTi +/MGL/+ΫwrВ~e3\O[*;㎒ 桺@h )-Kzw@oh4h $<7Udn0\<սeQlƍj-J=ď5:_-/ĬMvvP8y Mr.x4ucx&gd.zCWMnp4`@VvoŊl-e_'j ϒOU-~ɪ Mv|:LG4.di/^3!@,~iw[Ŵɉ|͢BzVqC̘h,6ǛAkO 0PcR?_ B&M sl篩ֲ1HuAn<ݣAE$᷇"Ae1I(] zhiJMSMq{ɢbVBWұet{U̅G?BVCJ-_P#WcdY7ܩ 2S[-}g:uV#rclR7E̥̝)\ 1p8BKݾK%IMkd6v5eYB<@ĭzI 'yQ,.]@Cfr4xDiRsBOW<ʇ{δ% ݳVrJטBb)bi~+aG ^_AoXQF5XԞ/iWgl6.[mm )I`FƂ* 9\9s:Fc ]Ey?t":2nR5[79Ps2d~D֋㣩qb/ /I`5 9elBARYU]$pc7 FCKvrgrUҎ3z,<2pFxxtt w׎^.sp soEŠ:Bo#3"8\?\vak]%KrlR̹ME3b| .y`\6!v~RuhR4cS n)-k]z5 "ϫ2X[q;Rj@()ƽW>) ᧷ Y}όڼ _A ?&4އimOQ8v)'n~r,> 4b.%> T/c"aBb$;i؁#&9axWpx|fp/s+4os4A3 mao;~Ԑk@CC*vM\#"ytÊiŹsO.Pފ u5M /5<;D$s!Aa h=М~i,.]([OiP Ʃ~Wo*k= j|x7|f:AR HW{\p%`` XDBXҪj\WOϒ$Osri_!Ƞ\a~3w)'v CPi: =r\K==;?T8sG ؓVrY9nVY,nIyu6 dH B$sD<f5ȏWϒvMƸp/3u/R9Gt~/}W̄/j1m1+u8 5m8=$ot&\XY'6osA&Qj:67]tqhn:F,! IˑpdX1=WLBqg~;d[ :.+&a.&F Qx"_O&R !y[|]20DX)植 gsl0;mh(!.n58iő,mڴ sīǡ+T{ZͲ:gByB,lu:$bzkʍDzEJ JQ"w @\bSFbã@ oH~&k٪L7 b.gඅ[ZG`}Tܼ,l1͝4ȹ|gfz:T% "R6^@ `ԥ̩"`JШ3^'n,U& G, gL-xxAH.79=K Q2E/N.L'zBVmt)݃yJ>sz(+2! )?4 e)X]}|Wh8DŸ;F<:6{U[IR YB|!ݫp?MQ֓QN.m m.Ѵ͎ɓ?OL~{k{!Yl-BhŠҋ_~k2Og%B;߻4u{ll^oZ&c}ͣwu`9GQni xUa4~Ywklix@Vrc4 JNd:I/'Y3 wn&SoF1|ݵty49f<,DiNq11&vWC'/2C]MYThfkq 㻴CNYsS)pu٫:?tw`kj 0$&f[z&śXyXq.d;pP4;M7ۣZoP ZP"pIv\+vꂖX)0#q mڥu .8C2 dp4FUBU;pڀ]؊>P!/:i`''gCT8bsb,+'\sŇ?{LY7Ȏ^7Ȯ@礙ޫ$iuA..RV61TR7sW2A (iw;-]vF,+cL ~+gN7x=_/v_z:T]KS"aNˏمxjGcNtlV~jSTe&~%.c0-;`aE6!QZd >r% CZ  _'(81XHE 6u Lzz"a{eClYR*m3.DX~_'tr2f8%Nf~*Lv}[ɨf~>+ZQ$\x=EmQCE4P|3>/4O r$0`sOzYO18e1nZ-Y!fD'rpZ$?ޟu@E)@C@ t=vf+vK+v)O9Pwifޗ9D_dI: X͗x4T, sDRy=2&`KIiIA l[EoҮw_][V/ewbjBq9g+iYЀa?4Gy"iҴ(%xӹC&Ont^m-h9n: O84 o_9,R&CCrItaЦ!3. „ڐ* ?`r.o]L$u y>842;qRNB> e*SĔW_dRZ9 [`U]gakEjՖcĻK~7fZ>,Rrrp&pKk-tJDto[xm7Վcn+ϳ}od&cf}nLm[GIްm* 64éRr$忪0N^7j"43wsim/z0o"3 ?Z}frkb*DF1ީ(Ȝ}rgcÇ{=<}Ң!6Ak6vO^GWN"_*W13ErV.'Fy؏:ی7Qy-scr 1;O[T0:Eb=}"ےfW"B;z:eCz7LFAtnlBrWoOO1"pHNT΂R!g8⧬3>m4oIlHULuIeDSk)>=z,x6rX+ip(az-3P A:9hC 0N]JڍLbv&䰵qOt7L?o gt|-0y{ɸ)_^r[lCT\ca5KTs.^s^wtocDvG,MZ艳n$ca6?=N`7Ѽ,Wۮ@l`|~A&  h0 _Wdlv+@|A9?]&DQPm @<ykحĵ~ɑ=XH=1f_<.|W ЯZ0hCxjEEdOn=}ՔNi󰐿\Zn3!{Nv*XEo6-}ӬTCSޚJ=DVx/;4|eoU>8j;uڨW@<7(ղyb(]NR]a||FfuPϤˏth47l,RQmj߷0OKrܺSMCAP琠cb]oSqfUd#@JCзOB947\sM 'ڮ2%~hĨn.ث?n鸁Ew]lݞnXd~.y7lyqzXfSChG T#Mfl cU mCac56s,슧3Sس*jm/.y]'{j,%7$ d.WV~8V"+&eFUhm?"yd!Ys,Bg)-{t?hed7RM-\>2OE;9){%bҪ3P:o%],,V k|6[d.RtH$UkE*aK㳩A$,fͺIF޲Ȑ;^83Q3fSQ |h<γYVOl@(&1֨ wT!*%!8~jlV=qG.QG'Dg)M< X@ӄY,!553B8Gٙfew5HXmHS}W3:%x+B|YcXd(l{=mvz.B 2C3uoVM8㔏c+1,˴{RBa{-A{1#@^+Z6]#I85DBi&igh"죈ؑ ꒘hyiU4K AχGLeUH Vg`5m74v"g+MVf6~J׌HحҦ/;6BO2uNa3DZ04q*=*IUS9|#Md2 Ek+飔ft<^8Np~4p3, l@3h^tIEC,U~n]VrT4QpܛxWVcViQ{&yJtxlhĴͣ5la1sޞu!_TZ22b)V֪kƯVe;A#Rb EǏ׃"9IUaȕYv*eV*Kp3zT,GCs,k' 2}d۵5)ATX HEQڴ#*F嗚JCC"Y~{GYt}Lf`M')=8R (`1[]H s]_ {NHܘe)<|g͖6ںy]WD.yHIo>BZ@VJb5ߦS0pv$,^ h(DKD=W6HgxVm֣ [ǿ-}Uq0쫿KWѐMV|ፗ5~q+̫Q׿Zu"d-ęQm6_RB7n?>sD:s_/R^QEΰRZ؜SὭk3x5a:~)8iuΖۣǮ eILtahzmCEڵuǿ(c% |wqճҝ_6]АDm4<1͇C vjm Zp||\Eo`}$n2O5" ѾBfdD:2iM.%jxRLr  E鸩 &~0HBݼm֍)vQastmbZn UC-pw(T٪㡀Pg*3:~PUڊcZ) W F.mWa^ l>% ŋ!!,Fx16?t|cX|Aː^W<3\54ҳPH?R*d2}y3cޔֽhֵ| nog4Ef? .pVMSDF8_lor}I|Ru,y5a<Ƒ̅]3-c(Ο"zeB0&aƞqWLS耧iQBA7iV&o&{V TI?ۑǨ%sk1(s(;؛#4/I'4ȉ먼]T7QHrP|Ӡܟ,.[5$ Ro' 17Q`q5gq<'q[c%۲83+0 WfNq9;6xdEib.5ўf$DER9cD_ږcxhwItPJ$Vh@Qg$i焭ܝ~69T{Ʃg"N*4u8x|RIag+Sz _{oܸOJ9OKE>& Eӣ! $&3A_@[:TIy+S#a)9e+,|*R ب |޺p E&EGph! sG-ru EvP>`AI%!eVj"!0 y q&Fݯ4*W̑b(ͬf[29%E.$-×?ҽ_nڴ5/!z9™XR߈kWׄX73v#Br2xc/vqUKk 68gs0` VQF_5a`͎?cJ.^K19%ΒsF[G\ۯo\[D:ae2 UW~RP3-ԃY~[B cE(Y& ƀ%=H>4nq]^wp3Th*M+O"|#8ƞ%X~^rχ%EI.%]ZUM(e2);^Cj qq RXkm*AP(nL&%!Ohlu%^irJoY6kb| ɩD"j;BrL> x2h>]:߹AyLxkB/qrb칒Sg)黹 1EqCC_)-4VZj+ևzD΃ͻPt2. gz y.r5Uͫ) ommxoLř !PjT'HHF%ItUNa.Z4A4A68_$?9(mm sBl;*[6n.oZ4^Sl&܍Y! gge]^,3K'0e/d3_flЙS{:sy?iL2,Lms<,b s!f4TӛI\+= `9a&H * i}Y(@.I^Xt{ڞM|#]I5ﱋդ7i40Ns!J:",^FcZgnR@)xI9ra'Q(2A "BZR Ik͡]û`B](LDB`]"RƂCqnkrfRi|@Y4 6E:?p='R#DLRJ"TF֍B۵n RY6ƾcZ_3MPn)[8ǦոkqV *_ 0hѷtrLxUռ^KVD..&bE]3Djj;bo]f+r|p ȵ,HHzW x\/+nb[K?;.Xl&%;oF=Uzk6f ZvLyXZTd%jQ[S 2^d۫i|eF=?}6#Q@ `;0OB;粹 )f3M⪫`{ĔoтIn(,k߼܁' ! K˩;0oZj;DUL22=f 1+ug;a_Ӌ8ikF#)pn/K7|QnOJkYo2~部r/ҨypH8)<.ѕ* yЌoQXS.ZH˥>+e>h״^`/Yu5eҹ1 ^$)_{ B`$ˏ~I_Jwvux+mUw& *4vQ4ni{09@R,h&'?`XGMrFePycbʢ>^8ˌ[\c~c٬OZgQ#giF*q2.$ ;N~AˏdaD0;S *WSh}l Ovu]a+MY+[w֤3LAߌ$&fH" tbA0]E7y6= W;磴Ӷ<|գjc[5hnҬ7ǗŪ^g~[m"6nnqȌ]^[g܇ w 2#oXV957FKwd~CWн;+4db1=̗7ܥS=o Z NӛRtbja+ ɗʫFGuHNoou.>YjλDQw =n w '4l)<A5@#G\m"|v4{X [X1}p'01 ʯw&Lm i?o6K5AoEl/ƏLwğ*_kmIb@[Җ!\ly1oBM X|BT+,p]2P6:J׈vE*TxԖwBa ,[-SW,ϑJא"wopiL-3iBNjRkD4F "jmseCJ8^TMg4깿 TvJ1=a*FHjͳi>:j81"ͪ~gJ\ >;$qa+Oc%MT1.& ZG'n06zLm6_(hD9|yԴaH[f%}9M` M ?x;2./~3.p2[jDԠ0="G6jJgCec߿ ۼRx1Kv+ 1 nu\p{/hz0!/3,p stU|918{Q  |HАm6HIRc#7du>pHV#Dw<d$8c'鐰ܘ[SUL= 6xm/tw}u;fLiY|<,t=xluR{H ‡壞 PcWsR TjxN=RKeF`~ Oxg7>j ׊A%>{2INI9݈=ba Y9] }Upcvfg5]`3w?9 "g'|,R_puҷ*x=-99eR ; nMЏՀ2Ψ,T Czᕬ̺;0A>GXAG[$/**9kH? `U<_\Ewhp4 +5D.Be;83 pKi$idݿnZm'>@yWP_ ,׊ &dۡH4'_X ?#(jw/I_R 5}Y7+*+Oo(pix_'7X=A荌oiEG&] ffqrÏr*n!l|>>r=YYMRm`ʴk/R=0<_?YKAak2 }~Z`pw[?OVpk*BF̺ 7ߔY9_!iJn rsn`2ύf_Eƿ-IXAhL+ȯLi2=-C C6SUV%evN:Bvt O߳pM'Bh/ȝv/BQbwW`?0.{ 71ە2/EW;8;OvhSw[6|OĔ`>D|7~cO{Koν߇`\A b8c7*C8t_/c="kFB9oɓ_|g4d*27|30}$zLpȲ'ٲdF%G@э9xɕQ.[] rWWU{{fUD.8kP~.ZDw,ǛfcmzT0QxAU͊+tl]\]ps'0|GK++4eJb76}f=]6b8ֹґxx^J9ޞU)ag]0>r#r!hLHCx.LԾ\Z-!RSmH:hVw ۦiL :O$W tb,Xu b`]%R54^F,W@F"$o%=ŖЊmoݢrPTWF^}l,ꙅwx@)8/RwtuA6|fI8u.m2.sX9U`O2Q GB(O+T+&+,Wdf m) uzUxEh]x1גf.1LwOӤ5f c04H7x Yi%?Ԥ ߏ/{fW$qĵ%aVak3vj0/ A.J+ 1Vc[34>*\FZm\_>>>}n}~YStiʩ2Ϸb2s=o? ҸHWʯэaF7ݤD,VU_X> YܽX(P^ u־˟jλ;e)Ue»٩}dWUp6-NrN- ze#I}r᳑d-/YdU|KɻPC6ڐdP.nAH?*qX,A{nh\Rt_-R/8 .h `,"Ugl{<ԥ|DV4ÌĸuUv4$^PUBw0Li_o4^%3&s!U-s2hд\DU(q~7~(y'޸InlAвn: M6_ָ<_๋<:xgd=( =;uFAH>WK:g \n-8 <+rhy\W{7:nV7)'ޏwA|DG"|#\> /ȥv~p^WG@,^0r.J] ;Z*Nkp#&Ҙ+'H:ȣ̭bEꎄu jyIBH>ˈd[)$SO遉V$x^"~5 Gрi^m$AďN TY-YC~Yv/ Aoie. 4.cCDum`'qr˥#WX XÞ(ɻKk{cmCsV@bFlIB1]qZ3n"Q5ˀdz~Wmi2/Pqi6 |p䡵D0~+b`xނh/ >uK=@Q@r+濻ٰU-[N≯/FSʲftGRyϵ̶v8iF7?፤),q:@ST6ɪzVbt6Oҙ C΍EcJ=ekb:TX#)&\Jfa!m񛝼q.%V뙉zR]"]}os^Y֖*Dj$cUkWf?  qSPҩAf0,^8S%*ǍVFS0Fv.IN+-,5Bѭ?hQ%eB6]4"X9aځY窣bsqhS3z NFT^l1360t:X> ) 4Ts5Rʙr8DYmH5,C'w LzI3ӱ& #eTlYjLȡLl~ 9F N?bUzyhFX8i"_֣KӲZ 0~:jZ;G-KϻgbQ8{P6}#"3!Ab3K?·3eI''1?O[\HTp8fHr| 4:dYNKy3jd^ %W+ƭz,Q{2DSY#^Q~louȓlzBNrNVbYUG9O9s)UNb2 RpUc.Zq~U"{}ZBjƐs4ߋeg9+S*A0{Q{+ Hr'ZW88HD'䛻5_ bIf%nyƃ&}ҍ>LoPwgnoYz?$DwQkR|)'1Nr n#Ѹʆ*x7ֽiɔS)v7Hx}9f+}:D3ƭoH !,0L=l󘊔jTf4OUICٓX]R(j ̣\SK]k*灕enΣ n!xeD].x\d :3^ ʥgLN-1WZ XButR/v?ʾ..IzF7wsD4K;"0/6ȷ8;gIuVgB~1"8zh1/,$!$vd!{է" Aչ#;6nWaTlN|p&3ҝYA Sk~Iѡ(+Sa)Q+W[6F"&x j2yxD}>B!NJDoT  9,oO`bM$B?h{8&G4hXvF 4D]4_r1c@+i8:w|hܓKm/KS Br;xboyEA Qn.^E~3 <.e9lfY{㷺<^'E'{E[cX{}ܐXCp` aAv]iAJBPŹ8YO%A8J/3yzuK>dGhDЭw8'+=k.3ƭ| IL 5` U#שlbR{Ib}>?T,˫s*+V.#i:~M 8!7eMM97Vv^2=4<ӧ-𘺨![rm7+icOYڨ5S.>`շ(SIҎxGG̀ۃf~ϰ8E񦈡(5FKژ3 +㩓42BZ{c;ۙL"9ҺFGu4 o(բ<g^plåRP87'L1,?ʒ8<,-qd8e Õly}Wbh?/1*֞4Jh&6fc 3)>p[RqX.ҽS 7Y-Ma+׷2/L/jqsS:7_tQeȩA\.??*HnR[Sh.d^}G~۴i~>_⚃|ƁW,v͇ϯ fpRD’;/ǪۥL:Z͵#þ[c@gƚaQ݉z* ()#eeuh'!#|ڏ?sQG,K,Jf_LD~R蝒IBDo돗CÄ^sr[ w*۸N dڍYkqR:ko~|ҩ&ܛ3h=h_^i̧"@쉂/ެw+ʂx KQAZA9Ma]?/vYY%  MpudrLSsǬb.׮Q.I^HŢĖIqڀo=tGC1'-.&|l`fh>˧>DQ5ݭVz.ܤּa`;_;-j} ʓN ˯t]Us9uh2:G`;T5qfKnWSS;^8{P17`fBװu`}FscV`qC=LW?F3i#ADp/<5?{kb;;) ;{? f f<7$K7*&um<:h(q1g5$/b=5}4/3WwVW84Ybc/oGBquPGb$ֺnXv X^4>1ҼD5G" x֙,Ur.!n"ѕ>06>_ ?RC~ XvK$vSsfwS 颤 2,hZP-|$S3b=2fS k䅬by3kJԹ4SId'j~::q*du;;>90D7 *0AYʜ# !ZWodSTly\NE `yTBa$N ٖ0SBUlهWC͛Hj܄G4B_{{z8 1p@WQ"d^5z. 8d.ہO@;HUG_X$ _n1Ѐ:|nmlx.x 06S+,W[\2N3 q%K WsM1'_S@r*}qЀ3e-`29$;;wp:dL䃃ځ ʛ[qt)m٫Qk6@W1aTN«b4.$,jX"q'?PD@ɏkai") =o?7T|`9˥-!Pmc &K@Fvh2i<>d"%9eQ2]K=KG׮MN*+#p.-N< YlMKi>YI,G'J/-3]B1]E!_&?s5h}cO W x]6>m #wlN({ڣ~ R na⸫W#:|Kt˓? yfZC?j֌ClO&,>2ͅܗBf ;DvLI<2]fc&&M3I#D},̥DUhuT"V^Ve)7M j0Zksl^[a~,|ϐ;<+n+{i&$ȚLBe\22z0۬܊x gȵ S')v >ߙy*^_  G4\ζW&R}Vkfmw~s3"%GZ&&TmB>&E5{,⸥ۈ(!녋̲<苲.`k\zNu5ɟ^-UG(ڗǎ-K!1RɿbsEw0 \ح< r+ Yr5< Y$i߾6"=|x1 $?D$Dh 98*%X-#Rźx2:ŅP{4i(pns]47&DW;nZ|D_K]1jM~{F\"䏷D/$flUw8t5Bv0qc'k6Gf2Ηmp)jf[H7eĈY,>+`4$mr~*&?2qL~pyFgA.XsgT& 0#K=oO+W<Ӯ OeT1M.hhG6((+G`4bP yxN`\eA6=* ]znW0_>&udsNkiOE~ÞTdݛTX os8N~HBG'>~s`؎)t!sۼ^TzՋ " oKpsdM޾9>p {(*~s^#ĩpZx.sS3B ѯ?pK Őa n=aA{d <Ř Na΍"Az1 {{nqy;S4C b-  v2ofǠQ>-^nfV'͜5Q uG;eB > 5i . }wv+e Cz]mLϟ>u{$Qap$Î՜2XwV%$ܗыʵ0#,sRz3rgO^͢ R<*G-9gR)$௿ (ޫ@z}ntSw-'E(f)ɪ`R%OYr}q_~LL+mJ z2f]Qeb=yKQV,8Z$OxxKF>1oR?RRt@|v}w"3i3ZC r,H0̃^+@J MIeZnNz*4cT I\ٸe7{)y1v9pA;hTĹ8/ }7_],9Y.'Ҩ"JKy=kXPigmRYl6'5U)V-^]w8̪*m8,6b&MCTtvɌ]9ٶ$tO]#CEJ[%b= 4 2[]?cu_ ,AS RF-pCszg =/Djq;qTE.`ùp{^oDfCT1I 3ꀖ,M;]ۺ7A]wbxjI{flx9kժ w)sݮT_txr}pkUapsl=M?v# 5mqlUbMUe]<kƚG=Rty~tB&a$tհ&;voP^{_Ij^W|va;~*~W 2M\վ%x5b%p ihrtdBPݽV5GQ Cl;ɯ2qe`3̧TP fR9llx:ƀSpB#T^룧.R IJVA-hZiCw`}O=/*c|-RI8TM&W(M UBe3) !V|`N~C#qI-o1!ps30V p!@ ,3lS4$4&yob>xj`af`6+9R-on.`xff-t5%ݩHG%p8+.NJL *iKY-j֊ Zb*u(6=~/f/OAp\99"K0vB"(6`l9X& u9-@Ff "sŠ,! @"@'ǂ.Lħ `iB< tB ZLF+BӚ`EoW25u9y-,Q=/;GQ%!#pkK*uGUpI^kBNA5CIR0xPYFU-M n.0rcLй0OC\a"H^HbzLLOO Mz:5o/OM&9tR6Ϩe*y[o&4 欦L2e 4iˍ(G@*˼ .$)u%5zKn^mio@ڕԪ,}XRJJi^HbT1\xTB&'3\F^de:YN)ENHT=TESҾdN,JIxV ے?>  /90=6M6 FIB)#ςS~[b`K$%-ckCTҋuIO~䯵KyNϸt!MyTF"L}HJ+&7xIz_'{;VA9HEt;orOjV 4ԈC%7xI@^y/Նg5Cmij,O\~o<^m0h\)S|BT;sv+@r==gѡj`L>: <@>D$L8םm!Ϋ1'I6ZgIWA s*s[a>tx a@|>7,;.&DŽK2QKNey'\BQ)\Ox]_y*chgtx4n2H:Rn[Z6JdZ:J)CPT=i 8B(g?OsS^x#s 2 Im#S2\ZiV&MHs,CSC[FVKB>ͤSD<P6Jg>/>~immLcSgoj$n2lj0Yp-Ssa&׉Ig#Wai)+V4pC:/E|27{w{Bi/KG&)J"N/gq85Ú&YvJ TON)J 1 $vװ+(_OVF+pF_U2bMá%F$!}y4֓'쯄<,3 ,)ٟYn©:b~Uw2T̊ŔR92;kN@x0BrKvhED_ B=j^G Q0OdikaA%Wi6H @ N1 )A64^ik{dyI'g7}r߮ZF cknŅM2X薣.s͛tB(__ fFR%=O#i:̯фkڋ2V3=:ON-\8õ ZfLc *$E+1T[K+B~ah\-?7_rgc"'ɁfHC8aYz"?.)S`k r?TYM37l^)sxu&(Q0&O0ҋV&F~=ΰu $>cFmTW?ZĽ}Nvh%uZc;RI^uݷa؅xbِ[19ǚ r᏷ ph<Ǘ5M 5`KWC6PO `<>_ 61Dז!BdEJ# WD~89irɘב7Nj}tuh<VcB||mB6kuh]ѿ=~R9m zAyDZ7u?^.X8w̾fϵz]k39G}xHru9S{NZ۷T`+f?ط̻6y>x2yGK_䶪o  ׂДxm{ WN啄; 2.gBRmg^Usmv *::U8(29 KL4UAXI0#i==pMP#mzowװxZm#aVmFۜa9sۈ^=Vqm9uHp9,EIUש|G)=_6kdɹJ+~.:dC̺,wۙ첒x{DsWqNi)9ۓ7>fAqdK/ kTCbЖU͸ؙ:z\7t}kWaoTSԚqO> . k [ج7Hjo*áP:9}ңKSi)ҧ (K QTSҋTiQm7R2e:KSk#S@g#!ߪG?)$|=l?2?#s[Nv4'mY]e=Z[KV"Ge>>n+L psgxTCn{2)KQ@6>#ss\\$`Xe>f+.}Ȭfoi'/J$-ۭ>w uO6h pdZdy/J/} muG3\ n׃&504r Ƭ%ѠI$O*s+iX [r 7 LXd}He)$ S:iꆷdц:*IMK(8ŭdM̳?v&#,Ɵ)j֢7Zj1dadWhĢIM2aѫp3ѺQSW+TL(Wsk$*nH1͚ZMHޠzw~-IڻLZHMahEBy;Ò59ڶ݁skds5nScb4 $ RZRtS4kUo:QhPqK(o#OKwʤY1|n=R4oƏgIe*e^JƥʌyX)Ne 8m,I97.6!cc~cCptGESݎ#qk\(#qPŁp@$/R}ap( cgh1m]-x*)C6M!jl :pkUFKT4X+Pzc~2]wH>B./yRXtv쓣jWlϺX1fukMP~S|MOM$yDob > bT##r0$@U1dB% $R8'g]2A'(3(P QkㄾHѧ= =R _,ПsI(w99*u"rވɆ!sGh@5 ](5582hui%EԵbgC5ngJ&6f w#7Z%637w 3 r7rk'enBx<56ƴp+a[bHpJ#I`9CB7p,4y_c]PK*\"677Xh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-vietnamese.woff2nu[wOF27r7WJ rH?$̗âcƤ7ky pG5ik! ,^i?ѭKԝ;Q1Nܠs2F3 US=@$O}JVZbϊr~rqb6Ɋ8Y !x YS:gxPmXy 7dxtw!bo􉭙֢U$[xRQLNGob[/@LrO1h:Q88>w] -ٺiKwM_úsMt{d"i$肵g~muxpi2U?/ HZ y׸hJ;Nq HB#h^P|AkWD(<A*%!u!U(])cݦEt$j.=!!P|Z;\4i.77JPhBYhWgo~IhHl u[,IfokjV7Ícj`D$0R{g"ʄH,m&[*^v>"4 |cB+!2 {q TH8bG\ȁ8?pÏt4e(խ'Kq>aR(,X_ t~\xԄ+@gW(iʯ/9e'R#Dͳ$;BAfW;߫$$'&Nwo2'u90 0~7}0hr0̅ l7p*± .lP @FPT&&Aʛ&^%p>-xoL]7YڔvD@}P;|&|L^-TVM! N}+d#)4! G4Bx`E`oiK@W2؃YhHEgDZ`X95j͛fAαsHycbgMU850B@AwlSg{T|}]e%Q-`ShGh -4UyF4q77$ܜFCxz&U)-H1TpI>qXj;k^eOlV:\"#\MN(p4fU6B̺C'J sz`&.]# 5T@3 P?[W+"a}d@tZa{=vڭf^V%ǶLCW2s`ow٨תo_$8oy;*Eym_e8'%dC9iEik١# TG$SvNx(A>c'#6|ްTʣ}#\4yC1O3)ɔS~ +}17Z H19E>0Bn2I3K&3)YJ'@%2$Yd*ӶS&nxY5#_Gԩ!,Z3ٱˀIl:Nb\Js6! :B@X^i7]vd{.͝d{Ge=GFZ.d)o@Uo=ؐ9 $W#J2;(?p9-yӢ=7JBZSzt- EUxmcK =(1Tʥ?0V4OA!C;,WTb-*ﯬTN3|?z\,8Ɂ:G0WIO3+Ɵ'>kwj~)I+R.7=n%(G},/h<eO'sHM_ㄱuVSǵN))J N, $eT4Xo , ^S5YfaxJԃRpɶv~)7<ko`uH˿O!{U|X+B7:+;l63wPAv#fA,@Nl֢Dd\^73_lH{$Uv٠Ps+ ή|Tlo 2'Asy)kJJbvS;M6Q$ h5WQ\M4)F&B!ov1%ԸOr:&b%|F"ǸwEW΍V JA${+h}"0˘{ߋt@TQ*I~g6$*Z'6X}-& DkGqѰEa+-U RSVKTSO>O4^ 7Bv 6 o-+!])hRjo(,GYk\Qd~%M=1$'酚Iu_c3FX1_=/)+ii/纍bIuS*f u(k1נO5_x,wgq$zB!~qnenqH}>̳?c7هZ0/f3unn3k(B5ܪC:ʈ~U>Fq#*t_x2mI'<]`gRntm!Ӝhըh._(|Q]yG/BD*WWi0xS9EN=|x\5<%`%4l|+Wآk7H-ҩUVUweF:z{N;jFohl-H,$<`"v<^!fKKiu*1[8uM"vGDFZ*ro]mb0PË ȳ5cHc]yaE,#&0 zk'}`K %^'GY9nǏL쀬X~!I0O(6gAH'6 #:T=oT?5|( 7Ba♟$Q#Zgpx [f |r1=Mܫ2 CaANI1x 恧vcNq2zGaQo+p q p0Ƹ5@2!GkY^y$8n - m&H /Z#7ROJ:oöd3+q$)>C*z/ ?)dCc>% jmiX М}&{Lnanh2u7F׍`'Fu Fx4XwвDtE>p ٧K!}>= 7|RIYwXQGӈЛsPk ڢxC&ں<_Su(`458`<ބc6i>U芺 vSF~JV8n 6^ql <|!$ H+@pO[Uͼ/Ys ,uXvjS߶>.p Hi G>1"JEs@. s1xߟV< o6-p8umIx1esjq]uӑhVLp(R4WZ5?kƕ +o=ܺ Bɟ$C@ng0֞UhPyإJf&&K"X} "cl-6iNľ!!>Vߘ)I PH6&GT`** 8MJ):mׅt1TVXnߐ LQc^8rT;/bFA@+2\)m[Ve&CťMpiR%= jU)Qk9اs i:̝lx8XP: ފjzue >YPePVq"CV5\in\KG#PH+Aڶ,^uuvύ(lFo%TH+ ٵ ]6i3vC[d㮉TZtҤ|Pt`d/m5>`ƌ}+Tɔ6i1k}]HiP4ahX*[hAtcSLdc#3*HD^P2=H(\z4kDbUpx0!/KX^^ Th& fSٯˆgzyiHΕg'g7(eg?e-xce\daHtu.+ (PU23]]V@{" fiW_*rko #7Oۦ .M;rnZ!6xk]Ac^:@Ga;"1Bi$–%^pwcU<:=r|:pE:pz/^B5rHl_Rǘ gb"Ϭ~KԑjA.;UWmK,*ԛLA1=S&[v#,r-kL}8!fSEBC}w;ү\oh>a؞;ƨCQ-RlAe6.eE[Yti$WHu{@_]( !%#%˥";i=můI諗D9:O.B\iԂy3K30 XUnbu 0x4jѣf[u(eD$ǐh1%9yH z3q!5G X1.)iZq}5<;uSb1mn_w7LjI~wCuc&!3;2u!CzRg@bE33Ƭ5_զI8?Cb([=Bg`ڶ񾖜_U3u v ^/-) V4^^_GZ2:T3XcZ$I+=PJ1!6 3U.q+w0O%[j$ָi'I?ܼ\͈֜+l*i*=2Z##0+Kg@1c@fֱP۬#K` ^-LL?"EMolg'L9F]&%0 $l#*!OKZXiRJsH̙)XMxh1nZuʼf?Ї"gF4>'S+ph"wKyNeFfX6UG `IV'Vىdtԩ?)պ,n1c8BmL KĻH^C}:L (I6MjzHp#F,6bvKcSKmR/:јz/ 4 Qԡ+2I fSH r(HR P*gBEN!V.XY,.^t\8yjpyXl_ѽS:9T'e _Ȟo^mQCB79O[ŐI!ao\X,ES,zS bԁY~ <:ͨg]}rA&`N[cAUYL9 1m~9J5?CڤkG3Fئ>WF.Ͷ4CSD WeM bmQe=}?W? uy$4@ۿkeSk!XtżRTsbknHIJR+V۴m.iGk%mHBmN#X;j|Y7`b1B4AFNY a2RGUESi HT\XIBhrEG7nR09cH.qZMҊIf=iA1] P#ҽcTm۰JV0biN8f){V9աDM{&{qح}A. \6q*Edw hm_Q\Z &dkLiǍ.d+ D^10_ݎ=ph?0zElyPB[5qF02yLĽ2:xA%TitNдbqZlк*|S)ν8a]pq8-3:{IvDhnb^k3FRkqfnμ(Oܧt ${?%;}\WãlBJ$NXʏCNQ&-X_9rtu7Wl B8 VNJTW5T+k?L3h¡1̋xی־ 45 0!;9"mIAIX^6¡.WMDFVs(a\kD1cR. A'|*.0`Zlk$&X"? cȘ^&Yg%b3J(޾@-BmX&\ԉ=)61.֡Fm;; k΄fH6I),$Dg [kw PKR&ݤ܎}v,YQ Ƶz',巁&ɒSxX.cbzz;twgk5+%$6KA ob\4P<8خXIy„h/>k{ASRLe$HL*(T-s9Ω}C_2Sy`N2g42>k D0H5yJj:zto(j?#i)̎˒': 5*AjeZ .1f(vKKq+ƬRTfD.eMYW9E˚VkvP62q.Hb2˪ZW- ,(8*47oyC.DZ7t*hF KuU +1{$7~#t˾h|œpz7>9PrU,4]Cͧ ڎU¥>^3KD_3Nąry?}geNm0M ӉI3kt7gpY7٠6 óEiP* g`\ae3V֏=T>OpcHo 憐e9$ Dx#f$◷Lxk˨ٸ4;K9s =uŹ"0 AqQ)&.-&)]0l4J,$t7irZMRXY3<^ߧŃszmms;AͲxМ ZTDRTߖ PR( hj:zNU!^7804捩I#&"S3h gKrK؏f2+ĘCP&Y*Z8~7z"kR>CIJ4+jvwjf 'f2~!:O[oSmEH9ZES/&+vhMOz5Q{$R7M8wCذzgI0=7J#t,5d_q̼pU&fWY9ԫf1Vѝ|4ly{k2C^-t@Lq=3 XD"Yԇv#q2ZWtj~E&P +( >6t<1ܙ1D",SՆ+D L''%:i?M49?d:kO̗c]40!bQ>ǧwEx2 T7gV!Y#>|skdcooo}}ar{H `ث^QmV з>āCx\m̓m4pH`a![O([<=96mmŒydNHz*gf'yL$ !4MyBI KM۝gۊO:s 3˦-6Q}@98qn~C}t`v u$솿rW Aw 4{^/(!N#,4G%0(+4DPIAUQB828- (JANt0$ԔV1$FaOEQ,aSbPupբLVЭ^`nv\)m6&lVv;Q۪tQ,kckSVxJИ2;5[mXgmN+kj4V[ Is=a0 +a)SIP5y6mf*Oe]?-p""c,Κ&%d-i>DjEɄCށL$swxȚd&f '/wo|O;o߰p͗k &9>)=*Dwt R*!_$BWKrdԜ|zDq{_xǨ; P=sk9S4F6pWws>vcu.f7fV7>ZjSjk{RŻ9NelX+\T|2r gfM&QH,f rt%#^"pS3>Qs"üٟF@,¹[ZTXJݓΩ7R7fI LH46D7$DѮX}OF]y!hpZ)'e6b#o5R삵^oZFJi))uPAbHEFUhdJl~`Er3´xN23Gsӹ?3'՟Dk̎<9-gawʥ jv"Hx"V0(i=F$0V6VQ"&ѻ@k*PK*\^,^,7h5plib/v127/joubel/core/fonts/open-sans/LICENSE-2.0.txtnu[ Apache License Version 2.0, January 2004 http://www.apache.org/licenses/ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 1. Definitions. "License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document. "Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License. "Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity. "You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License. "Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files. "Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types. "Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below). "Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof. "Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution." "Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work. 2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form. 3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed. 4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions: (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and (b) You must cause any modified files to carry prominent notices stating that You changed the files; and (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License. You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License. 5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions. 6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file. 7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License. 8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages. 9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability. END OF TERMS AND CONDITIONS APPENDIX: How to apply the Apache License to your work. To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!) The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives. Copyright [yyyy] [name of copyright owner] Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0 Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License. PK*\ ppLh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-latin.woff2nu[wOF2p&@b P?HVARx`?STAT$' +| /V z 06$8 ~ [Q#;X֨͜ v v "z?먌I}"s!`RF!BȢ I9r0GQ&ɵp\zBl(;<U yR!3i We,=@į7 &.txU QXziEgzaWCsVRX0 CaO 4%A;vLolwzgH}@^EN fwǁT 9g `䬭Ervs ͘+FCfA0/:X2BRP1"]dC$,/vo{N".cr e4٧M%4fMhhiBD'" (oygV@hm:wI*B O<Yw+wΩW8Zŵ>}qa1DJ @ipYk~ϕ܈5Х:Qm|yn; Q+lLLΤwb>ՔۮΤ]iO @BBDR_'~$"%H!}T#%.͝l֎Y 69c9M("RJb\9•u^o3zw~2DErazarrqݢ.[)hִS&B~r1&.IT*WH Z^aZ.7:>84וهFh5@Vg-ۤ-r5JrrHOp$erxN>\v7ϿwzHm킅E $_֪莍U|[Q#;_O5[k1B`Rv2g] 8g@ք !f3+G?R?''.=:/.h e |9~+BpՀ # $D`GO"^ }M{$@t| @MYFT[wgn{/s$e#-jnyM,f J3%M(t;1.L"5J"iܬ`/I F!\P.Pv'Akx&<k^3|M_6jK \r\}]1K` 9pr5 {"FA}٠W&ְP﯋\0x4}7)r `XFyt0w1P&^\-}-G=蒰~Ip;,cn󥵚˾˘<Ө7Q@K>p@Z8"qT3YRaBL!Cߐ߻Cc>>[ɟ Y%<1;~w=?|xiv%oG勯wto)D_Ϫ g07Ԟ]|Kw~·r_L?83OqN<)\x.CE2Sb ^ e3wOU ̯iL0C:AB#y_ "_Ad_k*96 !š% *6D[(WY(^WJvH(tFP>>H$&)fSD&VMW@O^\{vQ ]Jxn!(K _u$­q;}C_^_8K4+L`Yɔ 5GE\;ՠq} +4t,r<%jƤ5 `E@ʲ8V_e0cuŌ9,B!D\8;8:! FAE~TP= $ ?pS9=k.6G3(e5j&h?LM;t'16L\9 o5l[g]Y|Q-HdLDOJ'(G".^K`vqQZ=륵 < O2k-< >I 7Yx5ȉGˋM.k&]IY9~DCiuH>''Eu> z:}Ƭ{E$aw5mԶ|:-jGNn3/Eو1՘1{ڈm΀T|H(+$Pkt1SU7KZj`6n!Q$ q[/W슔lRN-u]k]ڲԷ`y֜V|84UK!n.rt L<-e-r&u%P[ڊn3G@L?LTE ;oA*!g {M"JC Lu_؃6OWEz[0 - ̺x %eB|:8 "4{(-9&Фl8Ѣ!&+\e/0FBy?09PjbJY:[Y@ Sѭr%G,8K}(!*RS۾兜 ~J((T@E $Z25R.`e0{w&w ={W!s$kwbmHdl1w4 +&nϳ>rKK$F}*Hf: G*ޒ)&d7jI7"@Znw^&nҶWwXj!cW^HJ~WVE_'$rŞ}Btǽyq/ ^ ?N] , ng9('nJ7ix)" 2 &Q+  RZ$s*-z0$@$=wɅr]mʼ6eIm[!.Dd }3܅_c=/bĭ-PHV lKԒI9iA7&݃R^ 9SV4l\prh@e^n*>mf>y.N#LeuPqǛ!oUpe7I4< i'Z2\֕Q!;nJt㘠wK+o mǶxF~y ɋ#QPNBȮ2~HrZ>c5fLģ ܀U*b\:guT,e6 AA։eFüN6-r]dHmbn!)|&n*-IP>fB@כ=CA\CEcJYDRoubvgAPg 2Nhx R>$IIZ%xOymA |~.5%U{4GExށOdmQ&d6jrmj Aװ8boEזC&ns۰k~ӓk"<ݲ_+ݛk;JN;hPfLP :HC-٘e/$]VeoOW'spʌr+J>[lZVod xHiuil?> mn$y[N§t^'b|m2W>sFTg +J]pCz2JzSa*),d`wӽgcBOXO>cx0BGepi'-MA q¥`gX h˺ BxR\*<#n3~ޅ 1yz'%"ӾDȺ p#ʯd쑯EO75dW!nIޜ ^=1m$R+02b,DQdw1FWS߃5Bž]Z j/Z/ftҺE:^4XDY8|\&QFNІ㊟HհPep畂ߓsX* 8Mw"Z%aXɡ辿D2܏~Kd߅GL )P]S 1YJ$/Ae+_ޔD.]{7c_Dx1OfÏiU~Tbçt !rQ!>T[@Rnx @LjggĂS< uOHX[CMd,ct/ KZ簌i,ɽQsZGE[ߘgAI}/sxΗh:W2[P?YJkA,e4wpy8RpI^ܒQܦ GLGw{_zJGaK뮂9Fld—櫝PpCGOݜl/~ MyVaeR%ډc7lG/*UiL;*I[gzjJV/:JN OtrU s ,ڔqkJյwhk|IZ n>??E2b=,R#OJ@Ń7Hr-X)! 7z6Hjgdo;[FijOGatv}/ ˩2t842%jQ6I?5m=hlE 4LBiĮ߱^Sr/C¸V Ts 4)13xAujfyܟ\ۍ_r\%҉@XtGn>c8nȪf:6mgQ']X1wyx?я*?0󴵮MOsm~[s}w ŋT_V_:) ?<^{9an:q/v\7h@P'wӻN}wK=?'B~ _z?O^̥zm>r){N ]x}}K37OwM'¥0t`xZmr9q(zf}a6~/^XyȚ.[-Wlz- LVݫfU6: j%3[ }x^O'O\;?9/9L8!.ۣ[ޛz( pw (mu)Xw1>]{ڎFJ{ttwpkfm}.`Obr{Gu!M<}mKw;+[ ڕ]-o·#%yvIHx)!mqsX\daJ,>]_)< vŝU csk+4mX{+3Ugr.dl]Qq. h`Q`Ǻ>it^:rZrz؆su9&\Ѵoydoުq-Oz8t~玽SQWcԠ:Q,ـPt~.٤|oʘÊy_X@Ͱ=}6OK8FAYZkZ #GIFn &/ٔrwii"4! %meˣ*$%] Hl G pgHԿo/Qa(΁jkZ(7̩_=@sIӗgWpd[G =.$S1 :@i-~7%7.1/`;HcP^ k sR)Mu^͵RS,%Ȅ2nV¶[22arpVVekGgj3C((a/T 8@Bh<(E a)n~TspD5ɧ߾E4wK`d{9-vq3Ǖo9T2eRWghze{}$%U3Nvv$v'xp]mں\xeO%[g߮(^}rmMޚ<u}@j;Kp'*h&d+AEpjY8@F Ur]Z!< ⡐] p!k~V}y-v6x:w_ٺOrn®<kpMŽBdi~A>?}Omm3s2%f᢮9 [âMuyB,gMnN.2u.I>8UzC9X{H)7eۣ$\vgr`HtvhjڅLqw<rF8bmawգ3z['}6nvܞtIUyYRyzc+Ԑݔnr I<*,: H\ޮT}[qwCͪm=}Vdma!M7X2즴vW)vqc-ktN`J}x_[.tAV_+zk$o*]b6׿$zf-N拲nq}"Nh}Rdk4wqӬoIHC^18r/=x -ݛgI o+a}08fC/5k|V>)4~>PwG98z^ef97P*mL"ȓ;2}dy htӒSp::_nf N隘kNHn5;OWID\8$_%CiiANPB؉]{z~4\42CQe꤭bAv|#i5gMsҝ 3e#sF5tb*cH[M`6HtD"I۔ݾ=֝lYmH% ^A*,.HPnMz^_zWuӞi6%́"PbjEW&ksFq5wyzGD߮h~j(yQk03?;Tq6鶈|uxt-|l]joP ٖXW/t)raMicl>RVV$BEģh\GMAOh;8bQA^!VEx4O(q_Py> `r4`􌩰c𚳤v%[5kAv}~E7Ֆap4V6:9wqȥ=˕GD$-YTKVc]ɏwMtG πUtM#Ű2F WO?Ր9.|b6k7CYxn`0R_!ƈC(? iF+҃qʃ%#>8VnDWdw4je]T?xgc ]%kv2?1zeq53cb#'t?U2CCn__Lz=`,shn^}zVJo҄OGO}C>e6^BAH:wސ>k91Mi#1شWXܪUN_kY?.I>@/Йy-"\b6RF^$g3{U,zfÉ97$Zw~1wؙ΢jE0:1?VaV"`[ޟ%c.ч Y̛{B7i3e|)8F)%Hy `6uB__C/Mt*fX.d۾AŴD PZUڲ7P 4QwF춝yo0GY6p[4:ە`I۵G/3v)8`f?Ga]y4gq`?2<aZhvUl+vZ1S8AlIJzDBmn`bUUa NrrTN Gz=}l )y o;;Aײl]h_{󧖯ei7GF_7@|7- kXKߌiiT*JʓY;I[EkMaGf'6MOi?h# _J "v!lI@ZйGEB' X<;h?E7*HJ&s:c65k^ab+}~Q%@ٺD*"u0^{0:4OU.G=|CUCf()wF> XC1G`wL|4v-BS-+襲C)5]NMxKUR^q01iZj>e'Ԁ^p1~sIφZaL MGG-^%6٫a'.dm)K7ϋwp ԐWc:6oCKS(]Μ]j6leoQQ{Bjl" {]V봓BM69C>`g&ke4SV9ސMs^a,*kS a6wTQQk6`vQUdʲCfEjڷLogt֓sJY 5 nqfAIA lۦ_͵|6 )D<r{zY nY!CBNw84KG*B=$g큘PG3BB(7<ƴ=ǹ#_dQ;P}LjUJT۝,,@[PB4WJxJ^x Wȋȡ~@*N:JhNC1 ߐPڄm>Sy뾕1 |afzaMv\c}<{BmC΅!ý% dv;ы'[ͩ[^a0W1ۃҘZ|g^ IkÉ REdBUҿ Jotd32s%ݒ \!*ae"յgb;qǘv4ZT0Tx5]RVs ۽1U j z'h٪[ͳ{c W 47_ZlZEwZcY-3wVB̺d = u㧙:mg? 3D)07R}o` 6&Pv:8vEM`kiȋgvLIMcĜ勥SCWM6^ƙex8+3_*|R1nA_L֑2__k1A>zA4) `swT3)Շ@M(^hh7lxRz= ='OY6^cLO*>1,,\'}; ꆢ5ϝk`z`p@cA0Fֻ}ˡd]]fPf{m4-&aݥYMI™@iAE!%f@iQT~UUoɤL)jaI9ck2m=ܦ!#/p,'ű jF k>"J˖P~o}$L}x8NJ28[s1t@殳({4"]gxfҚa,Ʒs 1/{]0T2bR#$/] `:H;-~""~:##r2 l9L~?sM>??t^LG/s`/ 7w B>BA3K_9`VMG Z pE ! Mې$@ gQ(T,* UEMΠv8f cw?GD1@ C(0sȩ3#aݱ((F2,3u pøho_!@ -qW18ABrH*RilOJ'e5: %ƨc tMOK& cD3 F%_/7 Vr,8ss^q#pU.K&r:w:vX}u*A`` /@Cί&V 4!D;;ܷv}I! m]_@Ʌj8YuE'p`ȣ!=Z}E,ǜrt3Q(\ j5إi]@$a3z4‹N+j6؂ e SQpz8AXfw}B9I D5+GDnW" F*ؘ%~~T̺P|?JӐ~ۯ h5RYҙ /4zߗr?JҚF"|槼ۿ %O 2\aH\A,#/Q#Bbߺr1Ek)(Gq>]ʤ^;7p_zĻ62QKdA$LgͼK3 JO*HP&x^V&cV`:N\ DzEu1Χ׳J4_dja5'?R;KAFsb MWS9}DL3P\uǑznBθ%vK|4qg◓(m=bd'bF66ebtrC;|ꇄY"R?}Hԛ{Ÿ%/Jd;+yQfלv3UZ͂ \Uo|<|*wt xqcU%A=E5=kUgZx2V S6V)ҵ;b`.<\7w(}^%i,i7Q.HTAȧ} 1ǯ4!C@DR,pI͗S MDUtkޯ]@DDTM4̝p8$mon(@%BblX3!A7cY:X^;A+ 䪨2B-. iX ] ]8rk:;s O}mkniſKx8-->(Nŷ-\ipc}=˃\3G+e@bzp-?Nx^i;-;4޺~aqv]vzSiGKtjyy)&iߓyaG?/vY|J[}E?Q{aGT6o;Uxq1Fsa^zI(Zf5yCq Y$=Q:z (0E;DeWŃVTز3š|Qn 4;iڊ| A)}RwNHmaFM% @fYCu_^+ZI[un AQǛ<[ppkQHYSдmV\Am1.:3.($MrZ D5Z@Ch C5 ɍ`p i>? QMdWBדGh=EOn_o |:OSK!I2*0;19 =4 qh&j>~%2c: Qe%N2 l6T*,Y/46@(zakIMCcU%,Y[՞4| ŦHV/vfVx70u .VC5|B0J& 8R}tDgF lj{C&Wf7znX|X{5vSPwi # m[i雀t%Cb|FyBctFd4= :'L'fT@44lF64{}h*Ǐ]'69/nk$A+H%^X(4O) *[#=bvA!\z r5KxtodD%F5P"{S@KT'O*-)iC)+ɃIڑr B34b"+np#⻄gzm\Z-H?L߫ ./ 7D:q!(%tj<Z^+g5!Nc֨w@'٨tf2E7G}lڥQnsh)yБ֐;W^t+Wg^>}6ŷ7KJp`y$ѭ6Ꙓm9j нCۥOOiš+RޭA[s[FQshƌan պCEȜh>Hv@eYI?xA@QKY8(lLj,4株}SfY (^l{sF_tq=r/{ 4l"Bk\Quq8dWnS~q[9` -GmCvUMflCt&M6Ӟ%=AjoA V% 4;056{ %= 53$Sݗ/:oıۀ7u"7}!@8d?C>qA]`w|V7^@pU+[<lr !"" -  A!Dc&JV|xl4'`pU#D5Z̵ҁq6@rNhE(e͢^Y3)3O}{hLy? iuy!ߠ-H;liAyBKȗ-{ *ovC.}5?0Sa\~Jw.|cďA IɽXuk*N!AQ[xERs䝷f[0,8LL؋sR7+8 ,V7E5lPr$3?LpENy!gS| d ĵ,Q7~z^K~U<^$}ۻݚ"EI9"іa:){fK60DV9LJq: + jh!gqLud'ضL"$FMLԑ~LR9T_dڝۃ1^q{v]/wpO$m'ǮZTxD1(FmXg.2Thrv 5We ħQpO>Wuj&k DE`_S Ml:0ܢ-?68'7K ~ 陽+,[_4ukh)8!!Z14Ćm]Usk8͜%uG7_z832`M/ڣn^"}?tIR tC?%`3Jh27(_66aVC:֍5DiF` ̚w}Ws- ;=keʕn@l*K 1y&fb2 %>6~D%~6~Jsae41'NJyuxyK/-O׉G7Н{ݮRX&6hL ]$G7=Y4hq',+#{[\bkV*QfcΩvN5yp -AAmӧE/G/=}A8`NXYgL֚y: _n:P7^QWĢCo5-QR?Osr.2z}R:̧_pKT}jy)Ev? v8T>]f7fMSHgAd|X(ɨRZm')-GX-OȁlUA// ]Ał{)Ȣ|aQk]6m4R%^o&O\0ՠaO&e\p-jVҔT' dVs5O<3tң3l\JyVpzʾFqX;۵F(?[7g }&Qxu5 L#?xeSπ ~\—Qﳠ߇(t6+'0M͋,6YuL{Ѓ*'(d'B.Y hTĐɢ HDh=ML)c`O31#f~]V̮v/0Q[]jqUٷ/<p/ށ r fjzWHމ[@FM v"βn6Qҏ]MZ#X< {8=No>LK#s?Yo >w0ͨ_T垏-7k3˴3  $D8: Who9ĝ&3A{w#=8 o=%BiHG\?gL᥶ .=W@ -eg-/$( I?G # _[Y>!+7M~F18 vF 8I `j+{ JZ0OR|2Q@QM_n_ph\s t[cFb8?!b5^bNM$Ocq0?N0ڭ*(g#N/5m2KܣN'J&#^L/ox’RfS`#e}dUW a>XMS#wwLlKL +H,}S Vi} Yё cvg*O0]l?$Kl^\!TIVeb"<6/:*EWC`MT\ I&Q`^D\m 3fAE,ːճ-<ۀXR3ᠩ!]'6HEu&).8^tI\x,֯ A,,%Ɗd"|UShGԭHt i'N`vdڍt2\F&bU9˱ yn!M{o|8%.MhѶTA6Cz6͓vM[ґgծ3@CqvlnCI%'\pvi c?W-Acͅ4m' $ gO 禓47ڪ9/:k뒂:"1{ռoph._AUn1Ye~!r`PU9T:4{*d?Ks/2uWQiPd_Ўh9.P&#};-׿Mx{&`(;x1 TVҙVRJ^e̕J/&x{|<|r0C52_$|;$YgS}8-<+nt?8I$sAj\lavR;"Qizoc%N(?tړʼgoMcKCZr9Jϸ/ Ws\,Ɍ,M*mj[L.h2rEHd.˯=>"E4 ۞};$$ĠRlB)TÂŌ\1? L';У1i1z?˟>rTE*"/R,WRP˦ߝc%oW&VdÖꥵ&T*dj^$\^]cwY2AoO o8GYሪrՅCAʠ?.>>L/G]Bݩ&PG؛ :Z =m@uÀOPAS϶B:5skY؋I]6au8[w-9GKAķMyG/v;ω@tiMA^MU῝Nh [['ü(n?w0|  W[7ìǷ,qme\J0:SU[O!\;Oz6q-/{ALtc^r6CWsI6.QtA"W aLtȁ1i~ݗ)>RݼM@OY[n3<&i&{r 1!YJZ0ā#& վ|tJX@X5Ȑ1 rVw4/>pfb-C#d"ȓlT K[Cfw Uiu4;IP5(>|֐IW^K3˾E9}n_ʕ3=:GRmؖCRiCOJY:/S`>oMhԦ+l^4rGK\D4㕩65֦NÊp^Nܑ@džg'{w/F߼+ihiH $my?O)%3*J9%-b.[hN霸r?N՜?Z `<%)|z F[z[^S7J"s'l3ycࠝtq=hZ]ɴ-9|HIfU>++0!rJ%ܸiN/%YӘK˒lj0bQBǠJR04M0Z<G=/mIgچZ:8NDE򖾵9:vd_g&]#d{'?.16Ao"Rt0Raz߼mY3 vޯUđ|e.AXfbHo7T%QClˤI_0D`hSLR,c{xm ^0Z$5sn/7Sa;l(몭<+"z9{nxte.!l1SՁN9şTu}UG+= x*)vMR|hp,BR=}Ev+goصᗾ]nn 0Kdf#u x MDXOg/`q!Ù'BCPnݐahjɰN(14%sU4̍ "&d:|`s+c_>.IlUR c^ZT8dCO6**7bUVQG{Jt@GD(`/FiG6e_< :oOlw)zS_d |9Ubon N5=bʜ]uug[ 7՚<EDa6}= !+~Atw^0 l/ CVz!XYf$ #*d0֪f$ !%lF|:y-C ,U,s1ZmWBn( 4^>YበiCSæYڐY;Cs3|w<V]ٰsTCtjn!Q3Wp]8ZV 0)uZMQ`|oKhɠޱ`JτbnxCnt;`.PF).UAGM {#WYb)<纆kw\QmL&וDS#ظ3B( T%_pշF$!٫ͲgŞ7M2 |ᚆ0+P S^&nD#B|{{')9m"f*$(\@jqd>G#|! 6Ίu0׸’fY717(ŕ-Ճb|GjX6GM TNW~3::~aIw^j4l{pFV-+84EL?%h#{(NaVz2_)ooh,(2 $\'9pZhJ͆\R4Q` ckj,],B$ +Z_PN:btlUflb}@.$"/8Xֲ BOX*`Asc0BzO0HyHIt #KqG޳&#GZ 5gAA;db9 ֠nT0qݯ$%A% H&IIn5^0:8m)QQMLW3PRSۇRx l<9 Đ:Gvտ]RNZYcuNhm6R3R E=En A006^S6q|wƧFe}YAih6JSrD&0j pnŘ:ύ t8qinأ\{3carQp$L.I{ =XkS5aK{摤LWՄ^FuEC8c6 EaN 1+= #.x3 vMĤbp r s<4r3g%=Ͳ0M "oJ]~i3ijB6nT -Xk;[G/ 6{l)n_V>t͔尩y>[af2aFN3R(]Aq)s>>(r:0CPF^m}d%4ԷZ~N"Y/[hL^U<,E>4ɊsU#bEf AZ줗?L')3hgnk6& 54mdCiË;PދV9B]~ haka6A#0|2 2||S$Nlp& 6Zh[a %oC](hGna|?}!NpegM~1WBF: xєUV+ZY̓e.ռ^}hG {!y-nhZNigW4n爰M eB)6?f >KuaU%WO+dc{++̇o*rY|7l9G$.jAH`yp[JrQo6j6ĝ(O~2/ecĥ*S^PV9أ0 MTKHYhVŞsSn:E:fva,QV_[jFK֝'X!!@ϝ>?C8T"qzsc-R\y51kZF45˾myH}֮h3r?coJ$% $VR$%L#ީM/Oa, A)%G3tM |Jm)ۃdGrQ9Yiv4Xv!relhqP !/kSV/fko$}bNxgiw", ]PFmq39K*ŋUЂJYǍRy رHb5V\Raij%H)Ϙ$Z#A/^YW16D% l)>726&& ePd.$;J L%21T :nK4+U"jNҟEe _TPw(>j3:kjÜ>/t|/ r$GBSC@AZSYm> MMG]% 3Xi4c'vW6gӕs=焿4 F_1*2Ց"&mWy=I P`S0xuhʮ\ؙs6gti=8K= wݔN!%8O~#~{S5뤰F|`^?)d=:2}xۇS_$?ȓ%g4|\%CA8QB90VU yHfW)ݤfÈbvz`D<@ryW/I\6QĦN=A]&19#80bd]f@ |ȯr: j*" IDhGE1a2N]ZlRh4>B?wծT1)U;p**QOY(R3k=uZr6VcL ih#8GOG<5(y*) }EJg]opNKl<=Фꘙ.Gb,J2r_b G]^"LM: e;xsԀ%e< h#FwW;1Z~M?tU9?|9.}Rx!%")(KTkŮI+mD[Vp[4 |_Nр7#'F?/眳!΀j[V.e,3]r̙(zAeg@qz2$ap4O`C }<!,>U:eYIj#1p)KĸxmFOѰL}%U^^:I8(E&2pŠ  Hh 勘kI+Phq3Ϛ5 @`FAE5t0?!ihT&R2 |LX Jcčܵ2u^<}XB R(+4Z:;m>rq,CĖ=6i~ynˌ=C'yBI_f2((CDMų0bs}/>ށJoF)荻.UnǓT'ufBU:8L~s[zHЮ\fQ\g(u֫PƬyiНf pj0#ו!Hx\j`jkY~r{:C1i>&ڂůOFSV[; MAP5u&@(5 UZbkm6mE8K &j `@$E9AxBٙbXS Gh(K%c6xA|!kH*E6[] Z.f2fY%6Î訾. ,kBV|4O-j#Vs5ˆgͳA5?{ԶHxI4'*B;/;o6j-o> It)"%W@DLV*6zB}ZahFB}F Vz m֊nna暜+.M DK uemlzaG*JDU! oVeeQq盖0σ儲~3~.BNdfY==㘡 pC7]6-]x3k!@Fe:aM0SM(|f9~b%K#Pom&6)N/,O-XStWuc5!Mr:OEC.&³xZ,3.,ޟK}Z |.< Sȫ*q*$rXje-(6ӗAda $$5rD{O\KUα7$ dNv0[ oi@*={iB#+,kk 5pD7\hљӣn[f;}kq=O"=HRYœ$bǍCaۦAETbU7o{xyfo5쐟CD k}4jy=ޒC y g+@JzEx' m=F)0$Cy# uv>wNp5wZ&Ƨfqj'}Y݆!NY" [!BbFy"ܯLݦ%#HDzZ@\h4/>fO SfW:묯ɤ޴ ܌Z;{ZO7, ~ M\XFcO%~p^^`up ȃw.'n,OgΒd"^iUĆlm /ְdžƂ.y.;ࣇ(T(Aebc;D*dAHF&m~6kĠpUŁR(QQ97֣2b3|-N}VUgXZ~*rӒ׀ҬjKU6xEeǪ ǡԸHjZ A5l,+AJe, 8]<>Ad}.**"q30 ǣPѴ0D2Ԁhjg?iYs~ . ?ǬT(m5'378Ex!ɩlK.$c;)Ud8>tE贃ϥ ~+Q-?Ř6pQUqV+ .8!ع=Z$ӱ%Op%2Hx.ȿMdY-T(Ѫ{AjH`5h~ 뼨X*_.msC 1UJO+iz2y.^DȇyâqNџ5lqȧfo81N;C7eciZ'/>;}]%S~dۘtEܝ͐ q'њKMڶ=ӇjW;[p*ħ}Ltjvgl8i(5TQ{=DzymL Oyl kg HXʟJ[QeW*CeTm4Ejh3+QZZ~P8YqU=w0=ʋ~ YͷX:GM.KਠO)v4Zւ~1&M:?!0u yƭ+nC%4ϯ\]kCa:3E&C7뵳@ 1#޲F=tg ˻.TIf]\ǴF}&Ŗ>\L?ʁ2x;iPSlg )"{$/K0ehT0J ``d~އ]c/+=5&|f]=p+0pVFjTD%Y>7Z`&~HwTP'A0WٮWA|AYwZ@hUhғ2M{TU6teʒҔ\2QI3%Q~kk %jڞ;)( VP~ѐʞoor ~l[;^ymMt h^m-]{]n1T=6io 1.j~t_ibrt$ C1ΠY3[~:$q b` &_"ƩNJ;\t(҉bK ضjV3ké-:&љz1)Հ4S◩l(yT\/3[;#X_YBͣxЙ.VbB1U vaA2t>HĨ;;4R7e7o~ر&Z4BHZ-Hl66R9 #ںp:a(CjTT[ j뼲}cCo߲k_v% b) wQd[(:5I YIKH <6 R)[-g 58Ic;f(YVUH㍹ЂWa"u[7Ne v@{'+E'z&Ċ-p|Bҙ`"sͳA-*X$yT7ӱ#۸v7t}v,4Tޙ5ovRJإs: |vg8Auڮ@Vy--r%\$m$rZ4x^i9(>Ey-ms<`=jaf}>{_(d@mv6\']!v^PST56JREyRղzY•HHۤ?l,f2)(-W3A&`E}z(~䣗;MȰGV,]J^}o9j@9(>32f;ObA]C#w҈X; s2b/keS{JjVbb+prEe[9N n, 4IbᕊȧMlَSS'=i*k8rYө=UFr{F8&a0Yv9폅T4D=eWPvwqr ,=X3I{Szf\{?=OO.x>Al_/Bb%_aȨ`ɚ(6_,$XDj4="<5  N?L~FU8>^3B\M /ˠFIoW+m/P)q%nEi4#^(EwUE_@2AtEdn>RĈ\󤚌.P+ n Jf=?6l٢ɺK>5 E:yɂP%8|m})SklfkpPSOcATɻ)~qߊ@ƻA=w(NhkMfYͮ/[/)lfght8Fl>?XQzGjbG@3[t-4 '%U,D@ڲm9}";#Ǟl4 ]nVJViiA0שV\u)&fVBr.|+M4ӺHݝK&sA DKpAl@̲8Uu&QYzO M]X KD(Q'" =27=:xEP+/|4eb2ƹk_cq}F#[chQc", -'<$-庥MeT(EC5ɌA#jU m (U2m$Lۓ8n&vL̑esak<+ Q8ۑ$ Ǔ8RXn j ` . {|E0o/F.E4XŎ~C<7}5+fkrNFC)8@*h6עXU AFްn{ٻs^}_zéT,SL-1bTJԕ"|&~gsصjL Vxxsd4ѻ(:+9pM}ZJ\nxUYF-fճbݢ s+Q7_xP±K)hE^: 68T&9ӨV7 ujp)QhY98׳ 4B+A{k3,k.(гD˂ïXez2X+m*DVy^]Co+e+N+ڱa^slJҥqO.}weiSC};*|)cT }BncAE"ǶH ;{T|g\O_m=~ 3!߿H^VCA$N[]wsڮFK1 YUWcj"2C̹ ݉ ZqPeVɢ/r&~{G5!9U$XĐxtcuƃڽ5J4;,pxY5ԝD.6sw, hF7{$anfg(CtY9%a IuqPXVݾVR3`Th\p;L?%?(Xd^מd F᧞5Mx U-޶/Xo ú:L|{yr'I{p0 D0e*Yfy%1Iq^\?9$9J%%Qy;fDE͘䳒+Max-_5s]7h8{:!tk{E.r˰i6zR rW"V׆{ [v&w9{́ }MQf^ULOXQ^Aւ+SS 1a~*El7OWg7F]W$ߢGf%Jw/wd|ɩr:{TU'f,`D]"Jc{Zd(ln`ov:LAJ/Ӝ9$1,?i HOj]$#0`;or8S,|&1QJ[үڞaym2o/N!$QxI, QA!5ݾ.Os+$0ҀtBX̀ZsF_Lϸ~ W⨰!"C\'=m/1:aRE4IH(XS$tZ.KB21 MÕ|f1%`>4BoQM] *R*[PiIyq*0K&(%lmG*y-e4M ס֛-ebЗy\Z¿P}KSwS@JMqkH9J,JD(eV% Q !=!RtEzJ_@DttVlYCSV0 uh}jP)/RHSŕ)P 8~,xy(}6$iIDADV ノ-ۈ$~H5'U;B1U/ >aYi7yiЫ@ͼ%&L\t܆tl4#jDF5I4:Fx# )_thx2ɕLj(l9QϨ̐*c*Jbf/I iXJ]WdȰ4TT&.4/;(;X<voCӃ8Ob SV+DK%Y0`@uRpG*ˈAƍTff[zVd uY &xi^3"[aun`5ua{ Rs)v>AY)5{)8bLB+Q\ji?i6Oh$dU!1 .tAǿU:߈LBtƥ7٦Z>Pt{--.?pJ dq=4H>BMO–G6; AӹQJ? ?wmq QhL{9IÝ]k@Pa*T*V+0/Mp Uy ¬rVxOyPj%op \|JK]?Px#l|VĀMC8|pAY~adB,.lu* I|~uY 57GZ|tUf5[n5/=ן*Ove: 1f߾ xzEF:?JubGYnHVo.[-/:CCc1Exlh `\+VȴɦC 2܋B3NKzfgʘ3DiH-BX[aZ)U*E$hq40 nC#dgKށLGЏ 9?OD̔iyZ0VFvNGŦ ?Op=n'\6(|ޝ` ,7d9htsuk?<Ж?ut6OZW˝ZdUHt*?*Ϯg˷=dv= l>7[}gRQ7;wõ>\V]MIzrG_\i!t'5:V {Ko84*xԫ FN$\UU:^H4zǞM $x X(<{'-ryL\ IT0 ƸV?3fT-*ό9GݹZKy8LoL\oMos73#.}~CT8dcU$ֻhmSy}~KbB]q˺)43 8~u"6 %#UYMOK\z*7{ zN+n8844VfEc8 (hdRn"W'qAqE 9sbJmhrS[y5l7͝J[7>kuV` n o;QMzs9Oyی]V;JŪ;Crv-wPN_zɭD$Ne%ٷXHrogm[sFvf+K}f'IX,&dz3QN$dY0;U=el‰紃Jf~p'CBbzUF ,>`JP,QF0bcfFjUu/ !314ymd`@Ū+dV;?~6hwt?`H~ xSeZUۈ'$$B5%6w'ud/Y>=0*&#az:+mWprMY_YXߒN~8 f2<IfVxݿ"j_;?_gcRvB ҽ +HzB6tqT ')+.i%UU "5ǎtg&ON͢D G'mg p?,tJSr @D0t k]9`-S ; cgDsc$1ǫy.c {>.3}dzTeAщ6,WQh@. R:B'69bb^T `-n[EM wzp|SI2ٹ&,q#y^U;6|fA.daAJ>0 }?K/BJ<_ -7jXjJ}->0/#T1e e}څƃյ kA \FU`ӎX|+>u^Ol/4+YNY{ `kvc2^vw5hSacL7xa={5?>n?ޚ%[);:cE<||0}3TIr$!_?p;2tt/HN`㨜j>C~%MϹ;,!K$}W _~XQ>en*K-ɏo}T߫L/VvPK*\);WWSh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-greek.woff2nu[wOF2W(V/.?HVARc`?STAT ' +8 /V Dg H06$   'nU% $?2F9GnUYp{C$!b.!93=4Ya蒣K A[ѲͷƆJp#=Ӧp_$@ \^ /lCOCF6N;<'\tXA]tL,b}n#4FMCX՚,e֖%xY*N""e=M@@, AxCUN۵X{7?3 R|J}wkҦH"?UTΠN]G}Sڮ{O?]>;QY "JH,PB-fFH HϟOUjz=Y)h ]4)V ʪ./ݼߏBDN#c'TӒDi5DǡLL(ے 2C6{TJ~?$ *)NEOGP۳ܗr)aQBm9,D 洁 -DA+fcKuӹϹ6Qb"Z#Y}V[(Lp^PG0$^7e^, V&VuX|H@8, 40IJH_| ,sn1%;^5sLW5H!B4qQS֏ts*6i]F릕yEr]JrեRZYPiҥN 'B?𽿷陓Fp6Daal^7Qp-WiYBFJrHὬ*DMn+.]:EYƪ9 m{MP`=9e  -s~Mxc6ڇ`o]VסM'f4I՘R~@ xKzP.^Ad ̿y+y$)XP~' ҄@ h,/8)z)b@ - ۵[3zg6kl=_do#-Sު~k3s[w-ץ&''&)NP>L((t빏;;⓻ɃEK}7&gJܰ꫐%CJLzQa5^_N.lz.MPC{Sg c' {<-ǘ< |Ghl}P? ߯o/+k?A>2Y PH3Uj0 䣚Zgz@ky$)cZIWY(GuX7\ =z93JWʛ/ky':{^>4?XQr]Tb(cPpbv1 ~vh- Mh6Gs.3筛[;c9]!#4| !:>Mݾ~%X`Zp~aփi9At/x'o[l=@f]2#%v1|Bx}Rr޳ڧ~ܚ-dRLoˆ;6e'zzK&?E3l7^)~lwm.g۔8`o*9d|ky 2|8ez =ygnR!V>ndϲ bǿ8J 6^iMXD4`i u(%e]n:;D+kwg7øN׳]y)VC3a5'1韁YٺȔԖX4u`]Bj73 _*-"gd2C|=6(bb)1qxw,JU#3 n |!9ldZ~L[jʺ z!h)r*VQU+R7rLZT2cH8 }^KvJjbCe;ە4-w&$bv)!,>,5guo)ֽ|9dWd,?Ȼur>c(esL>j: |CZYG/U;e=aXb Is\ZYHu?w9Tve.i;F[ڽV+Gwz|t-E F[ݧkj5Ԯ[r%9LjB`Ǐ(JsJ4)Y?ZZI''(o'L?{1xaz.XyL.l]YmŖ,|f-c}i&f9nge``?'-N+O!%XoS'"GiP8LMHb'|i4\IzJv 970 8b.[ wuɻKzlVuZv-t kwdb 5js-*C-6PT,t*Q_Nj}aqp#zAP3e(_]tiN>J^8IX==YSFur  w mNzp͛Ty꣦V|'XJ8h툇l q-L2֊~,*bǼrgK.HJsĀkA>W"&:'u8AF^K O:DGk֢L';Zg uJsxW֚  :U6>a{_ X$ly=<cPm#ί*My20P@ÁP%yfIE@&!i#?gӱ+P2qvD$@?;jN=<Ḛ@@T<%KVah-wuq QYyf]Z7Mwl:zk6VɶHONw @^sMVZeJ#XDխ,kBqokk=CP)qK!yR aBghM*brrNU]g0. ֝f#RQ[L/km2*LV㖕Фb`-ʡ"dG*`5oBi:k([qJHɗU4S@. &VCO&*/oi[_n(m$6Yھ[ZfF|Q(L -9@}`1/Jj Z\<=J}@"΀f5p׎3$H/>Yj}W :YyUZ&v͆ѫQM'j~d&G3-z`#\'.~yXJeF9>>u]/%(m~}uu7](o9l];AYu7?|99ǎC,0?fMC,@FGS> ,Wo鐶X;TeR /iKZdޛt'>R51>!>9ا MX4֙B8Aߞl&a;:u V ^!O/jSL3h}intkCGdl^,ye\wT8 { g-q /Zx";2'=L.~H=TlƝ6ƞT(\ngތ:ġ]r מBl`TY&=qz:g΀(ʘF@cՏ̗eeĄ4B!,浳 ﬦw hHAfc/AV\g:(UGekpZosQ h;'[Ok%[{ _!hF呣ESmE+jۘFALس6*Ik7$B賳dX>1~d~~qVv`n @|ѷAGbhȂ 9GG8Xg*ـl`?;b qn5ϘϪN6#s*ӈrk4[Z3"2yM\^Vú4 ~^{f뺙i5 y1-}̣ 198lxr5B?[o|\솶|B &'55{r1*1bƯBpkJvEso>e\iUE=-i;8Qmq5CLkҶ&{7C0ى|t{>_}>IW]to70ԝ7_ 1~8 yM!NG$=MzUI)| oDaP%&CuOa5E"[-{rèN.=V+^9iن{eü*`0t?^0RٲN!n͜*.>,KooJN0TZq nFU[𡖀|c8i_&=8`~bs>D$^'EƻV;}TYˡ Kq@\ z9~O59.d1˚ޏL_uYQEULo68|\ :RىkNV(?@tCAI:;@ {mŚZ{*sYJSEHpHkCT*,GBkeMi^CD_*}@cgEU)ԶB\+$j|N|RoBod-OJ|>Cs:FyJeWOsBcn b8JXdDq|,l4![~j֙|<'z8[AĖ\LE#&d/J &sqZs<0lnA 5df#[lĚ SeBH޼f@,__Tma"&PTJ1^.2 H4Uɨ@¸`6{~HY @3DXν^)'-`Q7N/ 7zNmƱJ^hے1 hzӜZ]ދ@۽˪jPLSǝ\(ɕtc=эϞƸ5>aTIUCEE"eթOpL E_Qzys9Mį]yW$(HXVNhe9>F=ox;n=Jc՗9c>m>gs R5u aDKha`(]RعwYǒ% ;ZxA:f>/TֽckGX6W(Ǩhܝ OL ۜ_w]HO߃jYP7EDx䗮hj?_a4 s{nVذV}_>c+Bƪo)ڄWYN${zJK9Km1wE;zXeA`6bƬ,/ttmW0ޗ-kZSfS􅚖4U7$)WhʗM~B=_6̵x 1ٴ-hW+]}Uq`9@]+s7.Z)p UFPGAhR6_*^;e:zi_0ZSqԈm7`q:[QK3n6D*:6(E~_>0#M+9f}lmW=UVjvs-w%ZfD:sU'n(G|&$}kbP LJX+ 5۔4r8e } T _})_(rgxJ[cP?H_}x=##[LPi_T]?\2);![t}*f'V'H] ?3~$D>k/P*TNlEI*$׹Sî.'62=dT? ]v2iE| L xBN#Vyez[>;}og2;Nh=W^y^:?x_I9{I}wn}i?ۯ_f]y ~9 ,$!K BF%FmmeEjԦSeKT3K%؈-Q[n+l1[q [ Oͧ P5YL MWS筬eh1$z2C'R ?w]U1V@p2H͓C~sdޅ>!aSvJvS#rGVgq59q8T1'ړѝޥy '_K0\pzCznWqR֒9W]S8g0+?!Q8烿֮ܪt\'E<0> C{poҦ6ػ8#~2ØSR )j|rA m!Kb4HqЋC>|-wB%Z JHuQAP"-WeT`DMM0{;ݝzhq tPx˚oU.~ `WƠm@yh#;\/o|J&WxlTɉ +:KkFDs}R`q\%L A!`1)봆Ŏ_mI]4;\U90(Q[.MxƄΥM_D- R  }H=;?dӟ(72aSBt ;ȰS%jo:i f]gPFcႻ_D?AK\u̻) ;'#,Pxj'a8;'@QTa]kЛ ECCT׫ѐu^?[y 5bJw*aֆkQ UF(ȽK5Ф=p/֢u(W1#~ښ1iݦ8wwiRj5Z&WYFFi3da!EѠ93K^@}HO E: &%dxROhsޞ/(x%~&v)#wueK8FfA0)w8 zObOt^bьUU8L}`@tt72O]ҧ^Jx" (:D'>Ǯ"OJqryR6+v-)3hI~̫Pgc.NҰ0YZ iNpuJH !LUCgZ.CkyR9w \ؔ%`ׅϲ~ : 6g Ӯ!cqI| ~ކ-͋ ^ع7DaW佁@'osՏBVի9/HeCz%%h8х)4FB$ (6Eg/xW焔4/sa!U2~eݼ|[ڴgYmk0^чB%9`QLa fp-~%UtKT4o.pNs;Pn>=)=/sy0 Dv5@h$4@Ǯܬ^/M VoqE3$?) x&s1s,=WXb7{ F'>n`4+Zf鴅JdMX+]4 ^#+'3Cp3{k8#XܕO%c6^> 3N">c@!a@DȿȢ^ʎ#%} vtbx_ubRҼV^:TXRV+"KDtsi/Xrq{) X H ^W?G$ ҁǼ0 써a:Ĭ&~urכlY,o?j5@J>Nj +TENQhֶ`1nyp{&+KtOxZr梮:}R.ԣؑK<Ϸ_tF) i˚xub`6״W`[/TX &_yߢ.Uʪ`@N'_wo͐V#N\F-8HdOLE<fn5-`lZm7 O$:ole#K K"8TUR*W<.\䯹*4HW< j˷9@"4ʹd[J"^H%wW#?0B8vU$/RݮFe=\_8+fvojE-R*'eFd+Ֆ $ke7lV VJj*,A%x+|#$.4V N#66@3e2h"04S1qOG|#Ivl3g &lo@(3D͋Z})> @87H%D-ZODT F.-q".J&8,|fjCxT&;͞jyvAqI*Pfi32*rBɤ?æq8]4>6Gy5" Og_c߼=| Ÿ@s x> $`*[29L|­-."BfTFNtrZ4xV<6^-8`q)?qcs%9~`ZsfQi@8tGk1BrXE'l38v}˶'pҒ#STHVوBCS5Hq?$kwxoPmbc;SuG-ӕ{i,_U+ mȄ*2FhI44xg~F-9 `1S054G1smiƝ8TgÞp<#Ϻ }wWbw/^Ǝp DJa>B{hoPBɝ4HU=<b^_ @hKyĚ|Є*W(͓9(V@E'CevS'1܄2҆TxnTlf| t hZ-V;~ j|?dx1<ʦD֬4 ő3MJc_NzYjskP-AЍp>5/18-Pq$mBx.L@v&m7d Şfthz,ku ( g׹zRRv$̰1D.uGu^m&2/R~cGe^ -۰xʢ`(#*|@6tr^t@CLS.6p{$& u\־#Qrn``[PS^!jÑp"U: ݻM/Agk(#țI"Q:D:52̜l$j^WLĂ.*g`Pۺ(*xٶ֧?-0־ (CRCcȬ}˃.Y5h*a{@9=WR};xic R ;g=kKvaYJKO&W]8ђhVq]EJIwbݓv</dJ3,ή-6Ef„ TȆi$|zh4Hf6Ρ 8(+η&nDNx]py\ <,[==kn&,,,+|aܤD"T:jUȈG|抟xb'NstDIJ8Z3R eA#]7j׿"R%@_{Mߒ uZd24:Z^L'r4nX°:9+!&mnS#[ʦVuBؒ A L`Wv$V}k+.Ho1k;ە|m݇손'\ lH+RU Ox;$&$\+@$ .v.Tڈ*vGQ|/m40q!̣ܳ]>ԟ=l}y EP*Z/T@Z4*uR"bN)g}NnJlg&eb6vt_'0Oxm__ta94I|BG.;kMj!~)Q{Pv3 InR%).pvx'{K/n@[NL2\(BVo"dN$RobsbQXYw͔Tx@ #8$ijh}Ab]>m2(ÔtDSъ}ʦƐ*,EjCj^yKabJxq,UQBCgFr:]^3o6WpeNfO1.OU/DBL˾Y7mZG26(a+t5EגhJt0pV@'vE* |oS7v?O74;n؉0qM!V4/`PWބL qJ?Q姍ւGbeT=,!bJ"LD'z&*ՎA\6 ǑkuAMnU$+|%cqr3j&}6-ҨJqhBl>jl.uJF(ᎮUV*e5ߊCo"V~¡MߪD g %AĐqA#*dC6ەėhO@j*3 3H/Y:ѱb'MO|<ʁ7d5%8Tӟ؞j{UTwD D䨧M]؏ Zm8{教z+R/ _uy؂;{DrZu<:mVd*rÅhX,@sS*(4n C#*4eoi6.8n@>lG%|Nv?]VduIq$;r@h2 Pj5If%J3DZj q2Zg?n/hdaYT|A?\ʏKcBKMj4L̿|ȝ'Ao^?SxJ!]z_^g$ 3DZZujNW´:)=$apK6aXm'.#X5]pݏ/p\)]$F+"m:#"t%~.vY| [;!^kqH3]FdV8[sccިQipVJBr"<߻TA+~pǨ= ؁{[^=I ANiv S1"Un? )E ]߭XR9gV3_X{K  ą!H.6w1zd/ D|V+\hbDB1*XXR^qlǵ _G#YP[.\iG~u5 ?M\7+VijiOmW) ?i H!e3Sʄt!!hs*X k$s=fi:^2sjjT̩ U<!C[ڃٚ=Wb:,8IR 0ZWx2 #\|yWn6nbq\C$u2BOe/PGVd>n8sOJ 4|> :-B]%QYUԠŵ_狶Ⱦm]_M3Z$B$7[c< c&Sf@,'٦9:'ܪa=>޻Owk扻v8ekz#]'_X7|sBY3[ QӄJ@3d EhO0BqX/˪Ybؠq`´nxaB`s$d(J3 /73F>͇mdhPWӇ=Z,Ax9nTHW>:]XQ9ru40,&;vmRSñ ._X]]U @Qܲװy}o#Zr. NPrfH'VFcSR*z~FUrZEiYP4d>/q")/bwrJ&7Vwk߼2Xg vxO;|ad#ņ5M+-z{z fI@P~JƕH+nW( Хs Qe[kDA?R{Ej}ds?ב+hO) k1܈7E ~1Ip|+58D|aFx,8C p@ F~qgP.ZpԬչ/S`zIo#On0L*U{^  hR:yᰈр M 6ohQK!;L5UIvYhYU2}}ط^EtNhwD?|iu#`B):ui%='7Tpgp}8|rR,0~-KwNBO:,wShVd&tIy1pxVeӛ֪ }vk̀C0jTsF^Ɵd[8X YmDD1Wk)T/s4+ :ݢ YnTߞ$wчDSM ̆U.c*•7"/GM)hA{<" SbV%-e~(k:֬l5GP l"VʷgSec/$;k(=bU?{EP]qz\j >q8"^ss(޻HHcuciSlM_Aw|+!x 4/=ЄTVd7-d.>_D|sDdFs\Xʸ(]n'QPtXk`\Nd@vj A$l1c3c2؛L)~-ɼZ/%;H$# y.یz@ r|Qο%[rf=[I0acdc,w|V-{ˀ\729PHcP~q+GpkaR@*WYr_k\Т!gG=m:׆QvxȽ ~kp$|+B?OR4U@t%;<#$6WKrvlRB;/aW#p5`cN9mBc,$Gwe| Ž$Pٴ{et7~^e}So)Rp$܄JeV`OXCQ3cD8,Y|kҐl힓Ĩ2 \^ H ,po[o 'e~DZ 32V٠um-x;c "7%8>DZ1:58b3hYy_7KF 0zDN,qߝ@?wsی w1qd(ǹ Z!ίKgdO6۸PBP*`| bo'hǏø%[gJUTm7\]m¡+WVmBz[-idg5<$)j{\e~^٘ X}69Ub~a+\&ϵK`yUOϢz3#]{ZRA&g8‘h,U#mkd<PU=+$B}sR*s14=o ?QV^@ñ>W;t'uDVL`#YnHErhʁI%yL &R^>.‚ݒl:tٻ̫/ؚ='5j_'v.;-nGO+N'pe7aa{ӀDDZ@aWaY !gU%FR jY.\mGaR·b`YVLY!XcC*Z5\̨֛[b#R#I"I:>ʢ +!o"4jk)3S-ǒ#YFFzjB60?ϲx"óhZjkw9d[K׺MoSμ^K ьoST"yr Ώr6:e1/_T3a~VdDսl(%mq&XX! l>6/J^a}Qn\KyAʰ62HI7a^Z,gRR8}N<,ϠM^3 ob'=zM&~~&Q> Uns!IU`]&&A{O{3"(ʥ$,&4}T(R*].dHnM:e^FeQxğ W: h/-rBWZ}Ek0!hEMt'6vDj2B\~15BP a@E̪zhN`IM$9l7߯@1YbUlr Ȉ 7 rZZ6'-CcPJY56EZX|H[Y,J8l =-,I?t%-rICF.{mTe: *@O4-%|^rBO߾-41bcX>ޗ/9^\jLK< ZsuT%[M F-lf=nY3I)wng2ƇEncL"'=k1p l0Z)Q܏0^cdf;R݀_N |6*pӸ5z^DJDY(K>,?Po,Z߯lD0q3:RJǢF׺].l%q8mv|nɌA.|,-d!ˊ,'.JHftV]Ƙ:ը1̟GM9X~lۇVMяb_̟'n%.Z,aшa}_A:E>Z JD^ZB"6EU7οf3/ tF˒Vph͞)طܮV=Wͣ@ ba<^MВMV2ۣlW&G"H1} fg Nd(.Fw2|i b+13}ۦl՝l&hx흢-bATה"xy JJvIf5/G_\rl XYd ͺw%N$f&Y?9d=7?U],U[$VUělA!&(=BՄ<;dN@)\Ά o_bnT⹇f3ICyށL6k8gJ\-z(Hh8oCW.oʟ|hI)R,525F)KA:IV$%9O2>"o[d h::un]'H'ǀ&r9Y>y8fTg+,]݆ ^k)h8]ZSG^s{Ja=sFW9i;EF9lD1"_k3잠,<%xH]ӵ3׾hydJỠo4$|ԵquVai?ΜPѫܕԪeeB}3o" z-#̤_ KϷwc<9#ɔ+Hrɬ,99ΌYiĔL2`>GGȩ7ݝA)4rE( )rF܍Nq~ wUyė2~| 1޽ ﵑ+mE KVɏhV KTSӭ]9hq СN Bv$ п!2>VAVN:`FF'b?87o5C')hҘΘ3Q_l0\`[y2Ǐ3-%LSbeĴ";5ULUVTfѩ(OÙ]!Fxǔ11S2:4԰O];ڤ$Muʨ0HO(e !9M,nq#qQp4^YA+Nb :~LKvf F 954@ujFvȏ 4q Lfa!n%%#c('OX$_"2 L2&*gcLM(R ]:A6nZ̿zvdѣl~lO5aIJzL$b[Rl@#u ]KGFMb%Fb/I6ϯC}Ufa֮4(Zz+ #YF [}+ȸÍ7T$ĠC~R1G]o2zLwà=PLM|ՋPK*\ZZh5plib/v127/joubel/core/fonts/open-sans/opensans-italic-400-600-700-v28-cyrillic-ext.woff2nu[wOF2\RST|CIpag1w(7~8=!CF%9IoG0TrqP|iF$e/WcSU= z2dcLjZ+J))6F֌e_(mtqC<x/O9rSH4M8Vs˽9{wUA@@P$Uu6뿤h4Df&2Tļ/7g6kUvUϿk夘j$'d=5GlZ !ۦ~=H(=kEӄ0Ob@$!!hR]cv$K{tVvosl+͵E"ԟ<{}GXwC$ nIXsm"FRebD b?@5"H*)@j6uJmb !7W4WT4x{LcNiu3r20 pgIX`[Z=^ iG)?'PZX/w֦=Xg$%#AEyl "cL: Dw!|my?C@Az0Ebxј] 2%tL NC(*zSlJR7@\_.}3Upe\x[jC+z /~Hy#QRΣ,hܷw?Ƨ=I=I?e?M>4<[U,;)ɻ7-}s뾹t[Zq}PׄK;_;vG;GGÏ۷}H><"~?F>a1ۧ3~`o0K.k\LkAOн#Ww7ʋ/is10 ?rO9>+ =ϩz9/ M g8i@z+b O|O~륟 ͳ_{ \w^xa*, |8 I,4FfLmw<3=2m1,)G v'5i3U1 d\BWAFo!]ZHYXc}@J"3 pqR^gL#cN8;Q>{{IT|+^:DWPU̲Vi *&\9f܄hn Nמ׷?9NԌ2e{;Fg#ZiNY,#YؑeJrN#eg8`rF'~GN Na&0xq(Cb%B˽DRUq2yKw0Y;eU,uY#Gk[ՌJt MYaqVۊNm7rG7D=cP`n >'@iF|Ug:8&9KaBX;j<>A !m9`1$.˺}HOlt 2q8TJM슣PUchjktQ':)+Vq VtY)]7Kij˅Y4_Q:,$(+,Ѹ Or)o.}liGz<'z>..Ew p$Yںs3Po_0sf#ߕ:~<{}Ls&-0J!Z5Mx-/>ʇ]CmH@&!?vQ Il]OLaO{. 苕&Nė^7|D K Qo߂9/E793 9DY)@kXtt8 8y Sin MX+'ZWkE;F\>߭ d[BEnH`1~teCra5"-2_%&8sAKvη7LOg}1&JZݕ. qM,aLuANfJRV\rt箢v`ӹV'qq( *S[j$H_q'QɈєFH5Uě2P&fyd![-lL`tT0DՓ·4܎ @id-4k7|x SAX~S$*{}Pi yjB } %SU$6[d+"@fpCz\X C/<-=).8'^FlJ+p zcE`݋@$2 F̩#jS3~>9ؽ@frLo蹾cN>5mrLT 7S!6]&qQa2&H=,@ L>?.ųrE>{~jwawƲ$IZ,H덙oz_^ (N ~e ͅiw7Ln9X7 7tj8 uGuViTLFD UJE\&EBa :J!)Wj*5{x S(9?t?r͆6k676m^K'i5sX:jJ/mk̛,ʷܒFf4{GG>N P'`fۻN8HzFenemHj'E#ڠj~Xtw̻,f+ͮ* ^AZ{Y/ieCWUeAU;U&!dЛ$o*g4{:ZO@GW =ܙA[{y}Z;E@Xfс{~Q I)4  Nъm+JSᕖ]7A-!ӯfV6Uϐᯜ՚^XkA%X^=a2mF-WSrޫ2[V3%vԷMs~/fnubFӔQ8qa҄لfԃqIFe IszDܤgω^x8' cY ^Ƽ?Lu;8wIq\\ْl$껓Fg0-}2:YNHKa^Yf NJ' o.GG%[H|qVzbމCI6nyO&:+4~<2ft -xP7Lt>^ 0K|Xv}H>u> #73ט6I$_0&mK @tNRhJrsm<+ΈѠEAĴ%.u!69 w+5DQ~ qGiЀ4TSWl~L$=v9gmkZFuoXVZ+ġ83lPM6#W'ZH ]BK{^v[.+W*w1Zj7AvZX̎8LԵk_>(5!œ#|:pʗt—+@ u{Fg~j:H͝Ei"M)uycGn[al  Tv!# H|yԈ@3&O<+ <'aK8#/(D(hAt; ab G3^[ V%`6g=_w*| hJB;wѕzgEIArQg:LE7]Jٹm˺`fE~`{ M񊚠0-qC^1/ZѻSPQ\T hD:-DK{,>F6~XFG,)X.5kNY0Ʒa]r,[b!eԠt~ə1I!ڱY#.s?C{ҹ \:hZ9CbѠ]ejn QMwRmf5.Mh:Sc%@VyC{ìZqϿĉj% DQcb@=@<I" I# LBLFLC8Gֽ82БԎ<}( @1)rDsq.a"=W9R*Eo%5lc_ 0gIةpAyv1t洖y I|4?/GD f()xForX4>A>gqwC֔- Ku[3[K&ooÅsJbeV==mݰQ UbMv'AF#]wd#n,Y5ۀE,K*Ÿt~H>.W[dRn=U!e8uwqpJӣxr%MmG@bړVu E,1_?P>s~tjaBsX } oz!9_y#XݔƟy(ΙG߷9<*׫Dž.VrCw :HW^"">dI@x;PV ɆEۙ?uξYiJH &=(ܪ*i UElkVroԕU)SV=5Zذ?ڟD\ (F.*r("eTVF'Z ii@M,P^TKj5 vo>>D9;!ߩ{gJ?ru.QI^d;r̉r57 а${B݅:RoG3WK˜SYMk7nމljavґhyZ#A7:Lڌt3Vme$-uzo#>SXɲ2Q# r3X8ѫ- n!Ez^G4T)]#8yYt]_Iv|}[Pt{o(<}Ы8*,ي/yͮUmJy9 pjvc;E=!8TV (irUe T^0/'<<>(׸y̽(7wulu`PBBS db~5"嗳nwpr{xn]D+~!vq'\'N-C:e-%u$^Bt=)_mO+6qHueurzΏZ6 l\7 q^8^Hj\  F37+JG} _9/&\XZG&`|$Z׋J[Jߙ]J͖.lyL dvo梒3[y=at~FɎ}x*ٶRKP6fRo/հ!F<_[ %EtQkіC7z?9 xBzn[HjNڲ㬺1#LtspG3d6nKMlD-}rY';`BmJvG[2ϵBO<= PN,Sit(k: nJRYm?KCj.6ب^dAӛIpi gXOe-(э"zRL\6J[8 Y؝~SP#Pk腠iA9kyGynjxgiܪ ŽΊ% )%%D6W|kPxm0вA)hG/\[k9^@åq T' mGEW2 5xܙ5Q}H^RWzWY9KpOBn3`}2]}^Ի$1؂[!?= UV5pow|A}1}uOT?ipyc`7آ-W8f҃w[R`c=.bNofek0w5om^nroT4nOU`]t*Jzơa!$ڣdG'~p:! ZsDJ\Y+llǪ '^hgyR% ,w-?Iߥ9v/6WYz$o릙=.U O]T\;߆3t#Y r0 !G_ O?5૳bo.^ \ߘ 5hks{v0K9۟$|td=*|b;?A5;Kpg>FRA0E#=vILKu4nLo4]aVlA9 JJl2\\>a-R9_51"c7FɫzLtNJ=ƒl)iI6V]5^r 4)&xqrtrCl+#MfVz dӭQʩLK's^8C@k hj֥!@E.V@'DP j1ĭ&ȖJ6jt_8Di Z#w1t_Q|ll6kƥܵn8(^ ,GEA]'41~􇠙a6wVRGgz$],g1^Q[)>+@UPʾjQH=T"p3z FcQ_ 4=d ,g#߻7!~V( {&FvhSف:onb#vD4fՐa{%sogbS>To8/P{ɱ#C|, a$`\6E4[ ; KO6td*&d6 4WGmS T4Ma\%{~\YkI͹V^ՠV .5X%Nmae\G?vo~)A_<%;=4N%ץ_/E$y gXp&8[2&Wm\O!SxK9?I[::*)32Ϯ+"~C.[~;c k=$/a {2!kj^Ve$|Fvۙ4饥Qu2R!ݚ&XbI$yV9|*K0eK0e FB)Fz̅m!.F dǯŷwØ/޹}yC?O0o}u઀o$|.DV`ՊhKteqs~}N졗\7ւxB"|4s1sJ9GÜ_uR>&#Z!~!y:\n3w9 |`sf6L^9~N-_C3u 㠽cT>@_ q路!i*kBN)NqMX7:5{ kWX9k :?!fZdk0>Ws zN⡽(V ] `x-˩c/Hr@(owx}j $ls',5kNk7R=[IN:95Onn_${.GWH\_fU4 ԌK>Y{= 9pҼEGQ_Gb?&c}sd8Ii ^Aennk`]ym%*or?`Cg/.pSFͷ1;\G 0˓};n`S*P|:bׯǧi|tǟa&n:mg[[sx>\?BDi$oU7݌Yg.Tt'K@O5m|QLJz̜ t-Io/g@?OPyYGGalii.׌gk7~fqNV6.UoM&!{Xu >^=^Ue5,›Ln6L'W*ǁU[qs8=ْj5uYņѲ͊RE ]oN#EΥz{-?tO=3ppt8uCi&u;M?4CܼϧD.]P9XOx瀹>8-c -X# >Ь-PK(wlB,܃V &UlfLj,jMl]AAFAĥ]oР2*L8S 2VgAvM(4D>,ױM4vmOjYG᎔m$.4L5o.!Ҙnd@*f*cZ~3Uz{K:nFQ6ZdpA[n͌ @ W9r(ZVJhL>hLnXMQ*B.%@NXBB57]hC;+ǒZ&mҙ@|-FG=vM6 x}t 6vR!1H'vDV) [|an]/x:Wmw'JH.ryKqw&qD{}4:wll6)5偉ܑm[ݙӐeŠ62b+s\ɂfSenn[?M%mMUm\-7/P8,h` 5M:x.n*YV^BIHu9^[Ak>_Ǻcsʼn8Y$Y[Sj f ^KTŴ ׍1WQofGG ^}Uaû-eîiG}ީӿa?R\ ,y55)T~HR@Zyk}YΥc=B[+ǺcA*zwFy °;V2st\ׯF j׻Aiiˆp{n{p?ÁV_gOӂ=+A_\q)51*eh0'.fmP\ al9p</]jXͮj_gᑽ1CW22w q|wj D|jVT>;$`Ch_ " 罥˸pRy҃^f'FrKAg`~?h(57Tn>ViZ~о5b+.C8sÕa0]E?{T+'= ?l8UJB^<Ф{uT"R==.;($$5q>'VLtxBs W2$xw9IH0S!,fH+>{@ Rqeϴ-[mĆtĪ|% _`(+v` J{#Ja +ZМPc]ei85 [$Mং,Q>?M/C_Ǎe0Q|g ²& 3GZg'#RQJ`ǓKO-QS2mRգϮhNn-!d#[l`a _6'?2V1l.=@9j;Cm=AΧ~Х_(܋#}O=U峅BҤ9uF]_̄A{Sl@Fh[5E+T{} 3:{sf-EQsiA?R$["UlUNi0#[]cTvZT_~&F@xڣv"` !X;"﷠pMag]"^MSXn W :ކ}{ 2 j[x+H\M1༜GswrXD*ZX,L aɁ*572ZRAsė&i%vzgOT)<@OSҤ)d2Q*pJ(E2Fےt{Ak:"{^i㰙H?x ݰcGf+ a7 G9ǿ%~=vK'pϭ_|F t֒s3w\0`e*Ё'}޼{r^@W M`jJP. yzDE `%]̈&g`Ec*^9Fّ0j@)W ~7 t. Aِ30<{/]tIYҀKN,ޟYfAsSl@XQ 21E{TH=LfH7z}DGM/C?'`Oa|.'&΁yn.Qa;BFw3D_RI>{W*ˉ## J/W?ٷndiB 3t<.zy7,MNdq't8ʘx2zb>/Hzi&^." u6_L]uq,|9 =kyөڮՆΖLZ?dI{D7b@_F;&[.oy+8c>\wp9kane %Dc/fb!ibƒƃmJPR#z+hT Mku4(rb MNB,J Rj1y)k+XА 8`2ωRn=4VbpqsXk;7(s"#a?WYG$)qS@e%+*IZGۤ*G沋cȚM'09) 3\]:h,8 -n4XyўsW",ֱ@ƸQ.4Ch P):GwrT}(EPփ6Pd&N}Y 'ZoOұ>rx Q!%}!$ B@Mr5i(%3{ۜ_Σp']<:E'9 gcrI u3-kzO4T%5`1c0R]w-'[D6m9 3]\rfݔTY>~Y+-zB shkWxM>tReY4hg{=/bzTfht-}(1>&O}eCg,rNDPk'f޺R I8"sƂ[0\M(АR0>.ڲa\9[ɢS c$>^32P#-< sx^"JvDZֲlU-g)&_:r1sow-8 '-c'_J*c =ç3N)E+ul jp+u읪|ׁɊ +n,>iWџ?[?ٿ0ߧ__>y罜+]NGv?Y\s5}I6B0oAW!A`R$>EfkaZyMyod>7y%DJk*fPYTBC{ӳBz`3.32^G`X&`V2;euֆH.+Ebձgb³7qМvn>2_*z D1YI#2좜/XQz*˔sڂ-ڰh_M`APx'*m)]矎7?$GS7b8.@b o-\Qց귒teUkgՋMvumB(xav>n^/,>GZP;|҄ T5ь0a]n!H rƈ{2cMt)ٕYo0^K [͞Qr5~}Bl7BM%"dVBփ7fV Pk h4;o$1 T|.3 ~w) lV[N1g'[k#f8=Infn:yyۍ!'`|el¥) g!K @T=,Y(@M24ޱchdHi Hbk`}vF tp2ހ "E̠$'2?քT6ދL6@~EM&"I>O(IdfšثEwpL" j% %R*_ xdWNI IkJm=rMCp=xTq E5W bP#G("@"= ̀ qgqU JaOl3S+֖ZgMK6 H(@eVHvIǻv\hkx/w굾^SԻm$QA2TJW?AЍ^"O돒@MJ'&TDVnZ]]X~=i)f 8Ə:83q13A玴ãN w%Ye O#~~ "w]=ʳNލ*Atv͔!vZ^> i\IJš ys`|͍ѩR\ܕxUC%440.9Ai;In_?fRv΢VuS@LQCyNemdRxe5GLfttf,,O̓׬][E,~=QFadt߀ڂᆮaq1)[r(@࠻n2cdٯ$X˅p01$FUyAUw3@-[d)'ji!'{v䠺+Tv8iw3Xe@5 |>Ùb_!ܸ._TIKCx}ٗ) )f~؁/sk"A:m 9Փ00sY uw7g(j@A1HLht@Ru>  gv14vyL⪖ڱŴp']y G>0pgMS]p ]pHE)Z6-;7+@>8Ё뎿Hl_uҧ)S9 ͂dڍOŎbPJpfXYZy^(nq1_tHUfT]AD{1h IrݏdfQ*@>j_F^;B~4)@UE' oFDdAma lnfJo *]t\P; fhZ|ku *k,H!kJqn#t_h,M5$ԁ+cՂ,L= 'nV݄ +8S R5V +,V'7=o-qy- C-gs:7UMG|84tҌnFΐj[C۾` q 9ɜxEWeف%%X<\ÖS9ӂЩ-|d%9;ȝ޽!Q'Kw*0$NYzzMv@)IH^ &zd 0kvX9A9%̊HyBW.רo 󚉤aN|PnFV>d=Chw칷4 ?:]胻]Yc{^\us#zCuޖ= {Lo?4R7sE(]`K"/zPQ =p /K; He6I"}JӁd ZmA7kjt$ !/OYh:oA~|VQ:#M+و@ 3Zᤥd"H }JI(Mw~@% (Nե'Vi#(}`˾HUfk2z&?s a>ХQR:sOZX YGO}I[N뎋Ou1LX5%l-B7I 2t>zהQ-4Geш*ω`Fv[CeǺM9"2K$V ұuKes*GT DE4tHzB 'IJ AwFOUtߕp$Qһhqz|ɫnVR_=ZEs%s2BZEUԠHĹ-5nQ*'S'ԦoX1$_(Q~aZ;+cxlR7`tYSZZhM맬IqYY Y&A$IIXg7Y#&6τ`Nv7+]B+VK'7u7h+1x3G7w=< -Kp$X8j6LT&)LC2@#cCoVS/;LCR11PɆ,۟oZ+nG!rHjI3 (`E`Ur9lǮr{Jx1lE%dM ÐoZk)h5 5}& } (,n*l=wZh%Ït 0e !ZAztכfE14XxcT.?HvfٍfmZct`r`@sRǙi!!Oa&/ƊZ>>|;6?3tUP.=Ul, _ %)z5 Tm/HV>7tGX~axf~ܧ͋/$oN\xty+NݦUՃA *ʒؒӾ @a3L5bQ!Y[YZV޺>e<'| 8?_QhG4/b Es P+PxO[=c,:ɥR){N # Sbp*SEI“@˹K\#1A'/8Ђ@8Fv'[p=s0AYRw;4č(i^%W<ޒrQL4#$"rETZxߟo賹<ħۇp+%W2f3Q^6 gڮ 3>퟾itܺikEXSh*R(>29@ +55/LECE1`JQ&$W8)-_xRFYh B2+hƺ G,&O@V1\ŨK0\] ѢVV:hh -Z5kUԒԞ6_ppiAڬ"rWioe_/ ~\8g@uӡnJ@Z\ -8mh!<߯ qaӗ?7»OmZ4`R N%@):ɣ(hk7zZdayU z(ewju7 i-:`cP-`k}iVJbv,Է"f1K|Sa5"6ׂ!KR{,7ee4MMcf08- nIeWg  d!jWF$3HʋE VO?v⇚6.jObL[JPrO9XO*6-OB.v?ZjX $H'ͤԑ.ZM먔T(崇@,hwha:E43SBbsCc͜D d9jlp|p^^[x&}(dcT=Wed.]۴/ *b ~>T o"ͅZ8VH2˖ۏf+Ph0(bÊˑ@W K0ƑmƖaQ5R8*@IuT6T`ӷޚw8*>^ӝDU;t$LI C)T4m%Sx;(^e  i"<+rDplY0Vc4`QjOpǜ`y bP AѮ@%1AǰY#BpțՍUB -l!%J4 Y``'2bk,*آtfҤ[8sհ,; 6,yTY=8'GɏTHLPq6"6 buM1(u- q///+jƙIgvw4MAhon"Ր g@>ّ#d rtw6$tuDU 4ޱ=\s;h^$VmbwPk!TYꖖ47ΉoPlLp ;8/үV"V7[w,V֚!"k} 1;5S1)bAgU\.[(ZQUߦ,xE\',$В), N2j{UX qzL%ѺE^ Mh4!M+Z? ڳ]fF*)뀲Rŧ6&P]ЙlӸK hTfT$ |_슙*ZAP481ި\߫V- E1 ez4jH$Ҧ*)v&㶓{CUTר8W "kژݒZ^;_adNYg8gcNGUg,Un8Sa\<3s+xq#5]-Up6e V?R 8j PJYBM=4& >=|<5Nz8`36%%-vn1eI3z %_Y" /LֈCO%h|{#T*#cΩF[<̮O}B[Ĕ۪A["hB\YiHYTƤ).+˵M|0~0DsFz/b~OÖדּi]6JneŸ Zg̰Xe:4榹̓|+>M%&ٟdJN:M"h~a| +<ǗK0MfbIĨX+21R>gyg'X$"˭ՂE,xJ/VF!-IF$?25l4#4091Lxh֒/G?{GKBiO)3Sĕױ6[7efZ8 ~N@P x@Kh [-ͱduIJS=*0jg\ mJKf-ً;$>Q=:fUJb3W!>{v<  FLFAa3ֹ/'zw Uxf?ƲY6+)/|tVWښpε'*:WAyq# !ѓrwBӷ3U~3Ҋ:wλd9SPQl{5&J"V%oTs yz^5TCjE nJm:q07Wzs̘Ff8>9C<Y1j9/9&ѵ>Vi$eh9YQ28F>fTƷgSd0}PB_a+݉ur0$-#Μ2U?||`ok9 XO6^XZBuU. \IRMx'δkK c 4)~ɹ%Q kǵɯlvf`=hWF@+ ZV4H!D dPGw@PP" LT,|oCcwi6Ysбbі8 xCܫ.ʫcf[Ds\IFB\.I&G;qV.iagIpU?9:<zQt d0 VTndWda+286Hj&a[a]SLJ Oe#vj3sDʥlzQTg P>kv II~6:"҃lbM IMd`LȑK 5Ѱ}]iSdJa iZŠ:uce홨 !1wP'5>n-(5Y1cڋ[>Qzg77_.๚0e M7{,JM9uhL3z}^\ F)R2"8Tr}Uz'F+nlİ~ri<$44t CWFi(d#ujZ"񼺍\TpHIe-we 'e3nxC\qE"xO[ҔF5fkD0D8sܻAdȶ3t CCCYO{\L5( n88:5v"z9惍 ǰ/jaWz~}C&AQ#iCNo & ,F4W#d7J/Dח*zK$1,ZWc=c[0KgZUFXg ;zv?L)_&|Өob#= 4'`'*cFq&ceXH ".l|,u0uvNT^Eץa5 :hYLm2rϴdILD8m'te ]CC)`TOda4@gbOb (WG8q3"hbX1MO X\- zv&T:AN0:_$Y3cRPdL|Oұ/(L'|`4hrMqxGPRu9)ap gWj A,qZ)Qv2~&GJ"?ģayXJ0wP(EZ7:BTwޚ[Z].e#XFCqz[H]܀&a ˻U[j&صFζ2(isgR>뼠z\ 3d/~>N{Ej _8^PyV2Ӊ\Sd4E ɫ? ҦX؍6K16nemGJ.Q7{t/ pk|Q$oR1 ȏlnefX9N֩gEu49%:%jx8Ai}$˶˸9oy?yl2((Vk\, lAS麇jkDMWJs"na2K#+>l4d;%ެHZ$J퉬ȼD9L'CI Q:Ť"8SHi~q=7jl pʶA j2_۞0hZ gcs+"h>m Xט0l據 W dJl3[A9;}@>@:5G\i:]/Y"ᬏ AB /a9mR-J;G![g߷t*Fhӊ|DFШ|㙰aC2#Tl٦5>( 0P}fskaY6H;c>[6\۫)!pTIth)J XNILn{-FofC!tcFm@mw&䍷<CZFekQ4ÓUz?~7JhcwwruV=з'wTsn<< oTVV>/7;e=u$ ݶlHLoQ=C{! HW4Y5{>E:'/ɫw=Q>GEEt ie2ȭO$u-QH!9wgFf ⍛ų;CހC 0j4?(Ggsq 7aSaK`6TF?:-;-FFCR4q:_AdsW,S_ '{epTLY8 ˭˨ϓdϦmO>\dzF4kʧgl&,ls8r"'_s4CmO݁M$㪎_ȍv}e^hj[͚Q\31vH' dJ-/)ZV-.Y'% Ũmk(YZbQP`ZWU[JI3E'r Jhof&o7hO>v Wʰ0\E.Tˤ}j\(.XJEYȴZsҗAh# HܾX{NVC Lf8M?S*Ҹ֤i@ŏ'O}Ǡ[^lkYaZO%3q϶>GJ %MsMJA^Mo8E׋;NBAC8~T&SM[|/OƁPmJ(yʊ03\6mJr8ZO`[|Ek}1hh!x*#vePXY4 :*jh:La:ح5W|?_\Ӧ2.#0VTfI% aǯ B2; .Kys ܮ5\Rw֦lfuKŴ9T7I($jHPw*0P?EMPV~ee7qty k^gT۴]=G`Qs܊ՍԇD^+^ :˪-w9XP:eA<>\ż1uqvQ\JcY'1 uTtg' rي92c#?g!EX^d<(R1 :2 O"p^lKL!zQz[* ג*&H }Y%T ^QԴmfݰLHG~*7ÚQ uCiF 8-eyGlTG>Tou[e@$y?CWL*kƊgRT|V:Yq A? 猛Wrݐ* ; ^~Q'^DL~ >MD]C+'`ln"xq,Lۗ>EՌ~ vs#UK{?OZJX[L) [8"QkUaX(01 ǒF%&O5B ӬSX ggW/W4fgV`N*1S..jܰǶ9òlFD\6nV)gS]j!;[s' *RY^[nDsxGeb2x[ c p6vvh-eڹ43ByX mu n{Ka[o} W<]ZMs=h`}R)'iX 3>Ӎϼj-j Y gww9Lh}:lg.]?Wɼa13pvfLpM"8iӛkL9Fh؃)TS// 4wX~Q]Ea.4v']`& ~^|7(3?[-9)FJ!Aѩz-bڴt n24hpM9tZ}7H'gz>Q@\$I*ΧKBwv[]sM9Ls@՜]O2 O.(Fsc6Z0]%uLQBލc&˅ʱP=lɯ_6MUѷs~; W6nYhSt:rNk;N#ZJFrvWVq)"]۳^D iW1rKLKܘ2EYb+tȔ)ahb4(nJ[%40xw"lh+UW[#s8zn(UxLoD ׊NAsČyWU s@Y'¥`N 6Op]l і/oohBk9B +AOx3è!Ceol;͉Zp%DKrxKRJԾrVuُ\?YnzxSS-=XI1'o/ecF!,`~ AW ͛EAa$,٦kCFLfm ixqa"4Hk&wL­"(.Ʊ&U9$"ٻ͛DR|AQ\}M];]~20A R[#(if*QQ6I|#ܧ!ij vcd*sS^2QoRbl*GQ57$0׋KWG*죙?;u WaBɭGWWЄJ9Fu$~q ؀ W vX?!^ܛy>M50Mg%>2!`UD-uz !)yѧ[g gG֨W$^q6E?~צB_^( 3뿙~a р@fœa?tXT' - +)0iN}+PEWQ'?k#cmAĈ&gϞ04zi 5o~E-=&ɎN}c8Ǎ*"zj= ۍjGmsVtlZ~U3sW_^иVcχ܏௎+e&iF租vLZГRUUe BG5+Zǚ־rZTTjg0bM#A eoupJKTɈCm6ό_,II^`y< +z,`{Yzr{SIm&6 ==gƖf\Y ;jIdr/%ls4X NJEr*/3Okϳ/3 k RV(ۤ)aCYſwuba{(VΙNlWƂf θ;w#n`F氕EX* &za5|KoO̭ w26L/u#I Srz(k6~dbaɞʿ! ~P^TgW2ugNXfԶyWM)#U'Y3E9n;tJ *iDԠ-T>N]slg'g c4$|iJhtmsATPE-)ODhܰW]:[,ܨ'/ K(3xCl*jByLõ!]"OIhbfq3R L$E$*3UA ?5R6t#}IL}0[7Q(%ڸ5l9Q9C^;c7 |iƴ/0jE02n6XO+ֶ *fP%Ihuʉ}H$eGq "x^KVǭQԣ[g2O#5  6!/&vSTYdFPh{\d%0:%&*A5">%ܙ1jK2k*4[M5Q|z{g/7#p1ӏ .quYBQw}2o۽k s<\63qʾ5EQ"Eo.8˾Kz-,tfkm9%dH+\2X RX ۯh)4Q郔u_@L8HM ӕPbkm}p2l|=V), ح.eUL*gT(.\R|] &*,sfg%2b  x bDG}{>@%Gb01, ]#7ީS?4)FfK?]̬;6lRqO-5"n*`G['QVG3%L2(70Tj\ؾWeTjU^P]hɈ%&)՚FFk(QZRJǓػ}9co(IuFX>IЎēh%N+b l?L 㲻S\L=wt_JLNZVMBXԜJPΛ\~W|įΎ)ךFQ7engI>\=-!RMҔBc!GW "ZNiR h>fʤ  3}Ah1[:Isomwwժn6̷'IG d2"ސPV %ꢖ5C UB4IJME$6Q_ {'F?ňIRDyljG/ ]~ܓ-RImVZ <$.gz{'W&#ㆸ.Gi fc D-5sp~<~Qȅ߾c͠%aqDg;"~ݍ^؁D & ~Ћ%/SbI}3I11$w@w$5+pϤfIm]o tU/TCN$sg/[ Q z=2fe3_FwIoV q(JfJK}| w˞s XŕE:zw? VJ5&_/x*W51{;x =Kܬwϥg]JHi 5=h|/L>m/r{S.mɂY9~94Rk;>mnsD;wN\+{6B_Mסfb$8J}A"z${Py_^"S$hZ>(b'T`݆`g رgrO=n#[~\M/\>}!$t#mTni(VuNfC 2כ@yv0Z\#%,L/uq?8S"kTE:%g&}e q=tppF(Nt9(:]vPzL&A:ҽ;F0W?'^j c!odvq_;o~dt3麑 $g&*>L? ξ^'-!%e`T{|T ྟ^e_W% @ٕx4'zמ7){5tߟ$[r< "ʴnOpXYYZMM.@+K6_Z,ˠSi`CoU!i[_pB׻^?WpC>5+lG T[? [*Nn6UŮX]W`s2 ,ZGMO' THv.ҕӲУBmAHf(p4xQ8S5DBթ6\c@7͂0Z%]:uyt1ҼZ.;݅xWm޸J{"h凤>H{^<(goS5j = ~Kf|!*)_ A-8A\ۘɔ{Mc켻p5GHpO6A]+vT/H}bLBO.yhsؘsFv8 -˘K 1S"42? [l⢷ aD ]3N p 6~: \yQĞE -7}lnѐtʲ;d\f-~v=Ms I;eA'kiDXDIQRiQlx bq1ɶ?(V`[÷W5Z4[ZY ;[3%lnsJnS[融IUP|4lh^0ACTs3"Ӄ7Fn<9F&fVrxpz ӭ2Lkܥ9 )~8Ƽ2M=1:8"r6 :񜛋]cQ4wAJI?~[FFSq{Ięßq4$ytAd%ۓA r<<+4(2g>ΜQ׽WDtFt f[?hIp*]#T:C v}DfȠ)=# &-jzVovl qPC,%g(_\-Еk [5Mƴ8Eۿ{[>]!uQ>~?q1R&N,~P-v$E{. $ zmn6F)e!,=;hEjă^y}cjX4cN@1]* V@h񀣩h1dgowNCS, H|~&^64YkL^=a %Et<#.)-7njut;e Oyr:c ۑr60D\2ͪ\-Ӥw,ZWNE4lnE/z <"{~'ܟ,*dd3[NHo¶'PؕAZR"Kf/QY©yԽpGg,}[so[v%Rw3p"tKۈ-j͋V0ޓc|V dڼ!K7*n%At(Hҟ[^ [BcFl$0 w ܀ (B6PXb6Ob]D9*̥׿N8ʓ@RcE[Ox T NQw'd:O9DRdv'졢TWu7ŅT@ dm˂L}ᨬ{)nݹloՁTOJw2RkH7Xu˨Dfۦge =qK4ݮmΠW6痬|~u@)g7xJ "J~ J;:{IYoe ER֎x=GAu|)s=>0qLC1B3!oBzV ok/kXI!ǔ.WcQ˨aW m=`߷Z$w( ZԊB?` x0-[(GQܛrV (- )gW4,ֽ>v= ~pYJ)8**ѹl '憊 sy̽bߎ/Zy`lbHOVQ+ Ʊpπ>|x·9T*iiwX(S#@ D.X摕ʼlst_D?,Y)pNnJَr㤜XTC>&g"lf^ʈꉮ3a]8LF\2`KV PHɦ5s4H=9fw4u}-9.6ano^Į`ɷҘtv 3BT*jYc'رWyOx)Vhiymy_mmqћXs*0r{25J);iE%v%eƬ, \wFSIVZK儒y HIv]ƣG><"V{F`>E`4E\|gZ) 0"AL{RM~8^@ɒmv4{溫\{!.݃s{r萊Q" . "/*ӕS~G0Zr8G/ը8:N#z/p!vV6D<\]KB1Lyk8=ݺfEgV`N(9Sf>vBOWB0QFdY8sⲻuqO?6'W- ˔I \ugcmNW7Jafr8F)I ܳwe^ԙsUw۱BI 'cȢ\NM }y6㬄ֈ)Hc֦Ҿu,fwhmxˠj:9৵<派Jh^z'-'s,5`"5DxA_miG$.xF@w:,AY#Zܫ*v9,?c.h8bEL&xصy2_j78_iqC|G at  j/һ;;sV[,nB,`Z-?}IBAMWHv2Na֒8_NT{ssc kMU]7oxG^Il*X+>W,nj6RK0\ܚ+Ԅo茪rJXWyIn⏔$GAT{~uisZ &3=Q *MوV|R0Tڲ#6۩x8UǦh4?]7Bͫ8eim>~ !NaG 膩Uj3fr1߯! U1r-Rj_ajM΅ {u:>H:C󢈠I"IevʐWs^Sv(D&7_,RK!{lIdDSlvNҾst[L~7)@yᴶ)>[=$i+=8jt{*J5z*Ӄa ?n8(z?>"`w70ERf27S%6.Aĉ6 rJV~FfBȃX2Hʎ |0b dkZMzPʏ*:\!Wi|1?}=8r`8!gޗ&6LzIқLm8ՑVCDEq  ZC[P(,Mvxxp^萤P-UYp4riyȉj&;uGH!~zXOFNh'_bgm?^8XwfmCRxhsViSȷud*µr"!;s7b%/_]VW*qh&ri+/]wiDInHu}Ni^KĤjS}H.f?{]cTbry mKd0@éoOwUOKpk ҝ7Q4NUTS'ϲ,P,݋m1 `J^KnK6 Ib\I .'N`,ccbr9շtk(xcod3gEXzxrO R0,R9YI,%iZJa.z>?1ChmZ;ٰcp=iL%m%ݥ%+ފ/5+yZU'}b!,c `z 噎b8/U9 Z9O QN0`T6!c?9mnyCFS2g*XJ&жZB7-Y#Мb>~Ro7-Pmٷ8V8 |I 햓<&mh5 8cٜ )@wNT2ɯ6ĽmC>Ih\i:@s!gVDӆvK1=N_Qh,R׺:k@sj'V\ŜQ/280jPvVBW opX-&,8@})d}5f$?{uuJn̸~oj,}Skv(Fv&_c ٤CRXLf]ECYr}&;0ڢ8/SxYljizzd9|j"=c+v;{ɾ+\u S#%c9VN=v,"NYKR#?83wOVPtCneɾoZw7Jj\İ:vydQҩMJvO;G REHJBu/tk|$rcJ @*F,KhrHJͰᅱ8w܎"HsP7Azapx?lޜFJERm ˡ1g3#}چɶ^:#57Ɵm8X$$ͬI3st )4bZ$QܶGiO ),J[-C+qI s5 ^ C|e)gdC2~vK8jMFDGC76p)O}'RaND6/I6񖽿:5%5b^U}jyI]]Q坽?%O̕kWZv@i"ZJ~e2sGF<;ҋQBkrEK,H|GcP/8PT:y„x]zѯ_l1| \24(6{DجHܶج 򞁨^~E[܌W^4owz/Y_pB{o9^NMX 0ȩ9?>=3;aI(o)n5{wQɭ?﯇?:\AM뮺/^oP+*s 05|~< Vո6Do2aS NnڄQڱ~4ӧU+:Ez& :Tϔ?Cf9m._ۇj:.7O$$)H!(*~4Ͽ]Cc> @M'2 =)H?mFwOF7d) xɳ3ȜRQkm԰MJ2 M>D;yr1j}ZpD%[ֳۗ>v70^8DW;n)+ھ~_13+ŸI -MwT߷Z.CS mz%&h( 7>p܂5D_Ϣq:uF>To |.O.f3:20/?fŘ᜔jzs8ɾxߘ0`o| ]lН[NoȚ]ݹe4\\GCy lC P=.`>WPDE'՟%rȁ ` 6G*H,PsCbj/J)`Ö́v=H iJ'w䡗MZΥlG&p-Rm{T݊9*q}M׉dd0y *8F'xc_li(E0Ax7(]KkpdNc&E8|_7IfʭT KnjDs:"Ȁd Kq0Z3Bd zAj7^JG-Xؕ 8>7ˡSTM46.~qƁqh<6#(r~'MZ;rN׶I՗É5qgvP<0S^(COa8XNNz7|L=pZqobG{ߩ|pHZcc{!.SrHr3y " 1#"#L[N=*>& -xOp1.G4ioIeL;̴gma?@RA OUx.&:ūFھfh!܇Ҋ>lҘ(7yOD#i=CEH/Kv~4rN7?UH S>++njx3Àe^~J|:㼃kmF~d>5Ӑwc?^/>n?Fw |_b3ȋ?yxg?7bqJ#yƅ_J] 9s#]oF, 0Q bw/'}njǎt==-/r&\K Vb%X\ @|?Ǻ<%/ZTnb[ɺAZ +v 1$]dL='qZ>D_*v+[\]_uq]5{s<>b(5D,{+-.;8H%K}yٮ卙8}O +O:(O9 뗉_gHiU_\7?&EGW#]!X /}N6w9'e vꥺ+$iUڊ{ϡ/5\>7"‘u']ul)G7;?}&R}v|_Ab&h#4ѥs$dK4?(2MM1ϕS7%‹pajc +謈Rrș٣=%{:PNJz+@EUEY%υvfW*&p`\@d=TbHv osyS ^Yċ+*Gű'bx{^Ib/lP ǩbC&G>*U3L`3/ܡLM^h̹ו,`\f=a`^DՇ![Qֶ7kSh~u*M4ǔC.M^&qbTI|a+ (ޖo'M7؂mb}Yʟ~ l[LO8T(m|=.֜.ZxXJ0c R1? eHظJ5 Hweidt6PWV =IT@V9#!&͈~JIsی).U# D9o%06M4r*eiq1.op5=XMIYQ0֔x )ŰgVϚ 9<*eOV0$!Ύ!'&^ oMcK[oABVs}ǗMsz=ç7O- D EԐfLqn?ъ2y5#С+鮷OjmE#tg_-"s2hm1M]fS9.#wiU1Sޞ| 2fQ#bړ- J(Ĵq2mZ56P"4*Q\B3 W*=0Vsfo<:bc7*P >{|@MOtrYHַGa ahM^WP/3P>쟦~M|fմA+ش6btZ^VVC.h㡦ͫh_l A76*SV=%1 Ãk]Y93-N\tY ;]u#*fs|Xe֔lcMϵ "h3Z|.34d!,cd``$hw,W3Ȍ4}XLl|#R֨>Of,_xu+)3$a/L\\E6Ո^yFeǂ1˩wضu=po +F?d1~*#;|9*EIL-# gq2LE3$VƗyɕ)]geB̧LM+Dϵ@u|n s< ( 3L2˔Vb)e3|"p1Ի0_͝#yXYXƒ}c8F]-c!|WHx˕ւ/˲dyt^*kf%y+-R.)tb9jD ^b3("4Ƒb5#5=0x+ 23KhAu%2ʮ.`'yQapcUk6frP{$qeZ?w懭 N'2k <j :{6]'b0z,6#ް1yϺJZ;rjݮR*M1u{kba6,hBE#"^ C,_Fkf|z<j6iv=(V7jL6_V 6YI\ 7VX0-돈_qMśA2;y%U5 {I\3F #,~xҽ !(õޜ͗UPs,R=0EP/v*C0Ά*5nGתbO/17 NL8LZug$\nrUxNJr2 EѢnJ{iȝ o;*#T5)KO/[(n2:/ 3Ll~(˦R7x?뗨?4j6HhI \s3zs<ڠt΂A$R+#2V%Uк$Hu&Yi`QoU{J|ۣRϳ,ɒ9H|J#8J1""̨YC2E$r]x!#+5HK|L"UE.nmG8@ O^ ؤ}a|ޣ%3ow!< h>A|=b uM }ެ;VQԠmō*Ey=T gׄ42S"AvZ`vzy <\hO(q sk~YYbx3"<;&z7nT'X>&}O'~2TϚFD|j[zͮkm'dV`\xo('2FWSgH:B <,@Wϵ"|Qm_ЁUY91PzgL}^#ށ{K7?B;Zϊ cq:7ڞ`@`igo/Wj\o c#aal`h \h[4uy%饛գխQ[9Qëݫ;ӬG5dNoDUbսՍ^wMhWdFtsҎo?,!sd| SկF+Q:|T89e {ox6p"<7ľLvN gPK*\5|(z(zPh5plib/v127/joubel/core/fonts/open-sans/opensans-400-600-700-v28-latin-ext.woff2nu[wOF2z(y &?HVARJ`?STAT$'+| /V Pc 0\6$ ~ Zt6}Ik큸޳W' l?{ʐMR1 :j01}8*^ǜ0 ;bĀQ,z+1IJiEPAc ftjdEv׫E x*AAZJ'"/7cޏFZ VxPD{$4l\a[8|ȚQP@i|3lS~2j _!dAmr%T{m~jM ޔ^̑${WI׌PK] GYҌe.Wm(~\]^ mɵ?јɩ"ԗp(&gCJ`-?ۯٞtj(MFb҈C"toe3:2l?c)ryD?~D]XФIH !"JH-Sl!B{KB$鐊..C, )@R$woAIkS$Q˩!( !sREWhvӈNNuaAр=U]OՉ.tZ/taOɸA+'μ*aܥcjS}4E-Ӳ C&:\㿔RUT}zt8&-Öi:gD@dG9$T۰yARVg-unuXɎFHeK9,Y2K@m3k< ^,ַY(WuMt!z9~L} ھBɲqt0ڗ)X_*򞀯IvP.Yˆ 7L,"gP@^P S`d<~Q@l!:ZNN3>x$a}\8bNJvC%ҶӴix`7p:HH1V(M[ HA tbm>}Z cE xQ՜( N3VXHOD(RM&xG2u1#xH. cZ ~N4<6:p6pi7>@kUAՀ~u;9T jІ[=Uw"rݞap/m3qqGI5w&|OE2^V(o$aogƃ;m~C!z_~+:Bmo{~}]o!ms1iV~kL?OOӝk>ž_Riq  kz5ܟdeUރ[?Ul[EpkeU@Af2 Đ}kA]^ځnvۡ CF, ӶOoŲEiN1f5Gćp~HBlR?{$j NBb[=ic(qCv||SִǕfKxD`^ynn4 @0fYe!:">#2N4R'ʋ3*g$Gggg_+ hY,J'F,%zZa]_lnA80!_zmi~`\6g86?g/ilKnè%_?(#@dn4a1{0@&:ek ^ֲINVhگ6Svj; etǽl;P҉#]4h4.p;΍"<=d%&h=_m$0 VkMBܼ^l ɠӨ2iaՕpWz]n5uVKB>ͤSD\ H8xr:6lոQf!'B!vJf lWF-f4JY0ɒG=Hcs إbUj`DH\idWo噱)WitT[T I Bx)+ىNY[Q I *ߺ)8\foahAjXO69/k8`4T86*<At*&5IY !.ᦧU+"<Ȫ$VvTIaJCȐ{!2R:J2)z[sxgsG lݶL˰LReGid^~ReR|l+RJ=_vx Dr(PFWEJ|$M '}vb0xՆ7hyNƃūjL懑qtb|Yc72,g0ۃG c%GăxHrbCux(Wbsw12-kZU#o'uzdVFzk4t)])[.Yyfܧ91Bh˻~|=:mlr}Ci3xIMv|H Ա{+UUC&ޫ| IE2,o;\gG:v@L'"F_sX/7٤c{_ l&y>bAVO[R_h`Qv {220nQ(n0o֭{/[@Ō:iBɢ#AR;m|%K B5Uߛ+2 ǘ(%'׮ $ #ynP}'m!6H})\}WIEfГ82~EMk&;x&4:$9&!;DE<nf5(Ju(ѐ cFjZcACgg;U |?tM7)V3ovݺכkI@| Ёi-tE{2dyUi °q^h4)Du.#Y:yfz0Jatw3mk# ~l̅V,ܨ5]goWֺL+km38w֦#0'Ҵ̨1cN*=JcɑJAiQ*MQP8jWyi!qP|ʑoخSS$BY8s̡,fHhGc~BN0 C*vFL2X :ASuO513ąbA#%iqRFX69>ےnv\)m>,sb%['a9.!9-(r[C1$Lk ^z*L Ѡ;3Ef;G6vYB/[Ι=eKEgt'&[kv$SnpdPN ئL!NpP3OfrM h/-36㒶lKlwúc)IBn(@ r\fó<5O "M[qW?Zz4Rʄ>[O3@QYW_!rȌY/V?pCE j1W=UÑua, igv1{&ী~"|':gƂKS( @L]rK1^"1\~/ޒjٷݘ?lzN6Uyp4]'kQ6i݈:vEۣ4uN}+OImZ]٘hO(E%݊Jꄰ[i)1te?mͩ'X<*ۢ?U%Ld|3y],j*!a)+ΔC_+ Vj#mQ-K݈ʬ&cVOյJݫB-O w{YBXGIs넥(CI~yye9/,̬(Pce,fLGjN6̋6SQom?Ã9˺|8QY1Z}ie ׼a-Wʬ!?;`x.?"|ϴTFʚWR$uEVnܴ֫Ѓ9>(cPOtRD8 >:.[&}p<قy|0j!MgB=9c׸Μ`}ow,I[$jaİ_c?ټ clrp7G { -:܊y^m@>C"\Bق!3x T &v#J]Y[nWA^W ҨJX@T{x+tx' m/r2?E,HB2i0SMub?rh(is'mׯ<=A`5yEWz`:ٞ $G1 }hpB>=q4!ЕT}_wIrTvܧ/HNhK(jo;,/Ϭٯq?%ilSĢ].B9K W@yt%_6s8{F֛cTې+b,d22}:B=M"TVtu.AS,+ iV"w׹MNkJfy8 qIA:VhIoV@uΐ&KXÐKH-ePB nv^3$,}\15>Xw*jL+K6 ix'錪z@|/=Ő T}vy k5jM4@7L#A;럱f^qoQ'2fS^uXS6%R,:VsqX^M*tIeJyD:%̱铯su0ePaCP4/sR Y愅tgq8+1$?P~F߭s }H\F.5-XM%HcD_ zOKJָ +5 JE)@:~fy3:W.}s| ]Ώ{cVGc{1&.zg6{ƪIgcKK>IL$Cs7ٖLՋdKU Vnᒜ/"TJ>9Q;^gRJg@xݓ["srr2srRs|UeG%h,Q1#=?xB\PUd?_f' dJv e`XIP5xkCraUaHrfQORsmn@!4xsi QCͲ^I3RHC+R8 Q97^>~eؿ_[*UlV1K{f'<+$Ur7v=,\g<_8)Hoc(gdK#@2G}fKE~!3DwiՠhPgYyr?c4HxyAߘ09s.WhXpUY /)e6]O( bUV<[3Ԍhï 1dyyWc/ !9m}:. qޙ:۫F,a8$WH-I"nXVޣ =PGw9eSkA}?SRQvšŅN%<4AxmMqm1,5:'t#>`Z#R+z~#Iva$BԁE$|6D G7.{v63L%iKv}RShwҢ0ҢZ($tXyvj 6o-T%ɎJuԯvU .]N=JvdZ4&4GGE )ߕYzF3,Y EBt_X KtNRX 4ˆFG' ZE~"elUNam9ndO Օn{2ﯬ.#R*SjAQ(f&cGޝ6V%N{ pv/Lq3&=H.h̔P"0f.(R)`aZR1_bh=WS-Z:|&8g=0@()k53qqDAmSjr]`R1jLq{S fɆoH o#z‡:QVgl|p{KG9;W^ifs=ߺ;*[Pywj D+&9Ѽ,cz8>HMdl>PsM-gRxf) TDQ?%ˈ-ψ)MӉwPfd=rY5p(4rW)ty6'/gd- H̾ñ*wnR9as|C 6=MXT~\t4`bP <( u^jȔDƇ$Lƨv]7e,'ԉ)1μv"EcSgh!loQTQ"J6wc爠E YmnnpmJv)UTx2V'1XETc$Q_a̚N{Qtj I`l$uhP\ ?!+Ju5K PU ι- w]J8uw~hPti9g1LRZq -6P^""l 1O3ܯ hš lǶA-$qx\$XqK-q8%"N7cce|M!Ų:|.X#5 lr"2&.̀62)8gc*-$.Oyl_?~&À5؝jT<ơnR‘tiejqFD 뫵1'KxM4ꗹa·2 ퟮ5q鯥ߏR,EqxfHjr!J&huL/0ݚ? b8T= Փ@&&(:GS!%lLߌA2ZXVl,{0If2mS#ř ҷEꊳUF3pȑ(v. Ƴ:Nf[e3(ߒ%hFK/l꠆_Mnc|%{l׭G,J%}fQΊ/;]zn2N˺ҁ,s[.hgDz t9 6t2bMTR$\0v G@~){"}P /1GxU DJ$*nc}KfIݠנ!@h*p %I6FpC/ɨNS6exM #q %7z|h 'j<ѶG&,^ [NK'J[5W+-eiז]7mtf^8rS}b?Kx+^@ŵ //wSü3X7iF;IDJYWpuw֙N;a#hP%(Gr{jA}ىAyOf{EQ :i^q@^~}GMV'Hmhmm| jwSXe12(]׾:i3,Im3%ZFc"#5aT'Գ" !n63͸^M#G1Pܴm 'WdNk7ʱn5yS*F6PژڣkL͛4G߼]sH+^n{ -O 'ʶ%uhzL< ݼmOveqShԅ52:@M&7 OFz(jr4 # cpDDojympzQTT\8.)J!!"#`;OL %$!p"oȮRmF2 2W&$鍕A݃ fl\IeU4F n>72Իɔ|pc@}K>%Nk&vT$ڑp)q1XԵ&7\*ƍc0N,9ϲ$YRJ担g\\bF 2)ҢH}zȑԴ40'j] L{#?cu lhWV =P&!$tr1^uFʪ+=BC8KK#`0=L9- pbʸ#k ,Iv5sBsNi xGM.Plq>,9(u+(o ثQ$5%#T^/[g#JaW4ub"}mZ0~"NWBI L㙾ļmJذ`V癮Rѭ7#K4K'Ҋv~"R.VF10$?IZߤ]͸*_b.jҁ1 z+ʞf]6Wcl1\,sJm3s Uy,-tTg 1mZ蠸έ3 :\/ zQ3 dž^֍aZ3b*,R]P/l@.қyo q=K}&皛Ӫ jb0t< ƜEd~yqQ/Ijrr0NEwQԓ"zVmYk#`b;WnmVڋDLE?+r`hʍc6PlY3Ԋ:Xyoy2ʸ% V-KPG%L qn`Ӹl{n.ˆk2k竇 $QqZ:8vwU"9z1acOqq G 7WB ᆁA C_hOSU>!5#`Ũ"0`D$$ǤiQs9d"A'>"E%%RA\<Ҷʶ敛o%K֍f:Nl']~FpZ~lcB$2r- v}Ӵހ? \rY'ki;2qJxjy;IZFA[`5Cz>m$ E/X٭)LeA\DpW a.!rb%X'X:bѣnrQ9:L5h` '?gw]Dm#Au{GG: R)QJ =<=8 6TpB^]Mq'^5ԧPb]ڃ~e2Z4q {=ELU ?85'ϱ>jzz+?U7p-/$qX@oʁF|ӃiRc؅jJ?]ϳ 6`dH[oU; 4Z1 ]o7CP,Gtq $BӪ__ bW76tt4μObN!hY }~7<#oƼX딜x5D|Dr$Fcz {c)Wj۟Z?_ _91pV%\{IV` {er'!t20+l_;\Q$Mx&}/(oj& r"quiS[ee|| TU\^|9' 67DEh]qTD@mH< h{` b઄'|~ <۱MTsMx@aL߁H8E[j$}o |gI mk]h}rL2yTv2*f i_ bRRb]Š}a\)J&vS6bHZp?4"蠪;nAAGWW}jDx ZUA)R3$h{.pAGm6C$,X*I~2{hԃʵ}n+W' 7\l‰/wCAcMY48MC{q-LiS(5()_ 6l&76 >a}ĆzQcL}ڄ[F[T|f!0RӪ٥ST&Brkƙ"Mϛ >P9d^gNg{V)Ժu1Tԓ{pNKew.zϠ~Tr=pCYP9$!EEȵd1J2J=[s񶊜$^B>iȎ2gEQX"'tj #{6!A0$Pg?M;pT^N HbBރR9`/EB/r>u$=}yM|܇2@W(ۛfΞ*l9ttXRSl9Pds#ќ83œNw!G$/<>Sdv6 J32=lX}&J!z0QQRé# C%=ہUX ,Py"`җDž"Ͱz88>_SǪ=ˤ rlwEqʒXnOiO5ŨɩK QIJ_JN+0evO|n]0TB{:$Sz~'Wiv+? W Wk,4ba8E捧4Z~c'UN{.2N{+7_#R:eH2HQ^9Y}n(|R)[qGy~p1#ƑRi+U;zELՒAf3 + v-AZ24lgXj`4ظL0Uh5A "]&RVz,!> FC4$cTWpD8құ 1{˂weB \$OgPHw%^"$Up8lEy9D 枱-q;zx) V, n[ۭSzp]ԏ$#&I/b Go)prCұ1Yk0E9VO;hD_p}\@ͤ mȭq-nu$ < 1bWՙEDK;h>IسubWqO+(Mw?{i͍:c;s^ӊv 0唦%10P1 ÖE+v'p;|s]$QtPYoBjAy&j5k#3٬P2 \U+ay v -cG;chrfOʝ϶R|yQg1q1>\faԞ'lAQ[첉WL*JUT(` X6b:1XE(xCH59gKsPe?@ijsG61AW r݀ ZԱ\ϻJdq]0vb!Oi&>Rq]JZncX0M`]*x~>vqq&=%o,@ʪ;;-Vu*w%woS_AF?E/HNa@ dҐی}H[E%-U<\>]-}5`剂%FLhV$ʗCgCUhInlVhiḁq$YS5[kBn*5 q3D#1K8Q8PxƠFqP-!1y `@pz+$mO]b51 ]eR{,(BȺD\R+9>1ɻEͭ>sON0N{-z@D\phq~( _(َJ>+zc?j۩(+C9{~S$Rbljh:qAC!W$͏I1c]).Q;lXTBd:M0vR1CA'9j!.Ph6X/d1%@+& J8QPcC1,g8M,H2.~01ǼAIjv!K:/~>^jR\t["3g)1dm]BLc&GlXgYyc`Q vcP3[ $~ t y$fƢE6Pmv֋Dtڣ?3ayZ,bRH;ʕS@ut A)= 133w¤ !HPPX:[g>J:W-n3zu*(B+Gޏ߾%ݼ:ѭs~#oRPCdcmG<] 2 K@G (YDžu8tٓlHLQGW㍫E@=ba,YyXhR 'woYPȍk` l7=-o$Qb"MKmB"f5cUPXuY@na6ٓm@x=Yh ݜ \(-CIuQW`=Ma=1["YId X1e#yƢDX=rr9c[Y=Q]ڜ(#HaWtr -pG)u=1p雠x<³\*rM_T."Ex-z)+P_h%{^Wܾ,)^ ZBY ':%؞W}M`dab܋W>\x0Mﱶ7GOt(ĊIG+6aܝ[Br7Yբܳs.ZT\#BЙs-u*s)_|y8Ҕ+=Au =!gP53.jT]mpcL˰dSWqn-cvPI\P <^;-1n>?(c2̞sU}}=Xy>9=;>8. XG_۔]Ae$SHA-vk*Ȭou2f@V;ğHN}4PN2p~ A+$@~pix_A Ѳ%hÎz  JQW=KUԧnxcIG}0;z}[u%U-%"54Ê 135p͍ 64iQP.V2$mAnXFg ˠkz>VwVl:p Akp_y2%"L^lF,)j.3OYxx9BԅښP~1`a$:ŀL gWrфH$q'l3;a*wtk<0Ens * Ml+$||a3H^O&Q˙imLJ5gMck7B'SX6s墷KcK{Ƒ9!,#4{PgC%]3Zsʭsth~t]O9}TO]Zc `|_af Xpe+5}B!8/As-ct4|5߱jݮ:}iZ퓀v ǐ(o~.mQ w8ozBCO~q'.HjL息mruMC6Ow 3 gZ<߲44TXX=?i= }<1I2`f/Ԍ!9?˓R+>Ωjd:X('ѺJe%C&R퇙hө%o͖?`FmE$$T'g9+5.oK5k>2`@R#I)59QA фag3 qͭ6HK\%}#|&Tӆ[@l]iY0[/u%Ż UHlМְ,x6U,獀!m抲-P45#6 EK>h^RJ͙VykjLb; t|8]tw! &|,u6f}3|u?I`gԪ-^bz>^I5,"d h4WNrJEQwҿWOg{i%AyQ`eTO5tJ2rѶKgK;&6$Ql3lphgsos ^i`-R' t >Թ8~!)ν)Ht iuUwXeO8+۵6z$UGǫ4H^SG1,;ꡫ8-vz;\xl>Ut5}:j(oA|U"5tg*QzjD`bo$IhͰ&z1 (mpU쨇oۏi G3]PD@Y}:ag2H',5HGA)KNA2%`^m: oUِ{i;P&Qs㢂E[i5fSӪFuvg3E7!JT 癥FiPpc9AM LK!R9ellaCi0h0O^ZtbF3[PU(t\z bMN݌emq@$? QeմG5.`nAUϢS\biȭ>bd_ER4] 0"5k4"\EU@Q'B43 mL0Kz3r/Z7,s(L9Ƕ}b,Ӝ'!U߼VSvɐfI`YQU\b$C5Jʜ"f-ڒksf(3S&vKwoIGlUX9BVlTE̿bX G}YLg1ȧ\:R-TzX44,,B&Yb)XJjn-GQbR{VQKq2 WkYsl!6b3!i,MdM4 <7& ̊Z7s)#фTa-^5HODRp~ }Rl9Iu'`<p^yg7۶p6\ gJzd(O<ّ뺯jϺfը 8U[}JOIiXdi DŽR4Y¸8Q iIzz}E 2lp,EY+ 7?pHAwFDe` NPi"88`7)OEM R%C&5dB:fNJJK.rT0n306Pgn{٥y"Wg4GchH@i  z{>:;0p)[:XfSGBc N?0%)4dP@~g( 8hi){rTp:M[ke>qvvlۊR5cj{:>,VOzxٗRV%[Nœ. % c;n'#&\A'Du .aHvXUL}UE5ђ0Ԡ$R|2 gV꘭͌&af}kUuH+!C\KP`X1Ns͐,Fb@l]צѺT`E8ȣZ Z5J3ՠ/ewuv$ [z.ډ~wt-<4wd%-&K*A% 7fVҴaM+y6x󞿍 h}} Jo`W:lyq'g 'R%ʗpwl_\?k,D᯼τh#:Vټ`jU2F,+:!(8ZĖ0I)/3Ɩ!L9VUT*p ͊R;Hz攆̼λ*4<&d;@,i?9:&F0ݑMSIM0Fo$U@sI lwR_YtJj ձlԶ?6/k` ARjoi_MY<2}8lӿ1wQxI(vC=ѳ^$ 0Ю57cC`D}/\F I%Y>%$T% j3*yta 3Խ$aoY5j#oXs&'mZdxI+ 4$0_=U޵at8JUxgYDz4Mrr8ⶳm;j̲M.Mgw1]p"%g$Io?BNK9NI' K_;pTw.{0;1|,msk>.mN n bг2 JxHG> %Vjޟ3h᫐.# Rk; RfO3%,jJI1gT*9 */+×> ~9OD8D!{(mzA,ʷ3/qIъE *{"Q_mo?% MTPjTRao=[y4עB6ĂPlư۬'z<T*}4䢵)L40PRs(Ae]]5vĥBp|.6Y٠FtUW3mҲ&p+ LVUFӧN޻[S 39 ϺTBW5M6ۮfS1{Q$2"vD-3@5Jv&rQ׮nl8T"F?LD,,5LF(pW4] AdoEчp?tdXc K-߰pН:N{YC@?YOOys ^Rlh5A "3Tcڻ!Upu5:5Us0ܴyq_NCsYč5lm+ (sU":8iP 8&t = }>;q2Y,I-gّ'}1y$rT;aCGACS Ewlq0v!zG0IΖ$ b(~zms Y6̵ Dʄ]ErPvJa'Zb(銢gJ*D2򂷢s{fGQӵ|jVФRMo. Ga]XDiozk nj"/eN5'y%Э>(b Da6s볤 )q+2Zr^w"kK^ m 0bz#C{iѿoF| Io 77f G(Y)bHа} s7/l(鰚<۔nC_R5*?S!PEi@D`Pb0]͍pG41%t#Vݱ3/.g&r" 4J25# uBXQ8@G6 ͱk|P|e2N:(3ĬtJ*FnLK=OgtہGCM"rYSkg>A j- -xd]Z&_R 3cw].X0'NS*>hu =Jl!e ׯbQ+UӼf7|.NBA0~OO?秝NU_%Nƛ(dC#u`efTi\\#:#NALW!U0fs 3FQnIsBvL*2a}enWb+SЙcD`R/Pb.] Y܎b*mk WEe,=ÛŃK9Qd](@Pkş~ ?c<\..A.$-̱`.f;L(:R``id)1a"b|y-@YS }y0ŝKCGr|=f_蔢%@B@X-ՑʂPNZsp0|zReqV١aƗG EfӲQ?o1U1Gf0 E?5Lj.&W(L(ڪ4#OȟYn'9wЂ L.bmf׎O}:a6[*a/wfej%!Cp=spoS3I~`f<#3#wƗ&@o*ͦaWEG@-fDβN:˱0LxpVW|_Kl~@BqhyTxV'}R}L?CSWu6f<ު+N>d=Lw!-k>%>.g"H&S2?WoLE Trx[נgh:X<u|*X~crHz,MfD ? ];a;rC5 b0ikU7ʝוU|OoF߭d#t|pM4-,؃ˠqEf ʈZb'$ HD"yxf^1`xI_$f30ѥ~=oAF-òƻ?TfjcsKe EN赿}om"joX;\[O~Eplj o; YU(*P؝y5Rt Tv'kçh^Z|"^.b!]VlxRQQN|3LPB'J@;]Վnl 1/9W5;"AȬKᓿ(a:"  =w0&(7߄"6O99Ѭmu5 mܗ\kOZP㶆:^ҲFAW-I!RPZJ1L&5Oe|= o=*ѠR~UviEʋp"/ U/kruD^Xs*">MEмCQGg\vn:: _TboJzUd'5s+9ȾA!jXZ`,m:`^7t&Flv$Uv["J2XQayV:}^Te(X}w㤷:'qDfVO>81>=-qZʮo]?G^S7Uk)kN)4&>&Zm,eTr/s(/ D~Z3-VD]ݠ{X'buBE)yJ.A ~ -P QfeT喾KeNI!4;m 5+9-cZFs($z$)C!Au/4QS+y<wvA*L+Hgp`&y.ဴsT}Qi e>q98h6]iiJJIWJRȁ>!II%\8$O(xZvtP"qR2GC/r/.8hdʼjU.:K~kOE(^55)'8qĕ7!*Z^d>PK*\v::/h5plib/v127/joubel/core/fonts/h5p-core-30.woff2nu[wOF2: x:?FFTM`X  L6$4 o|`%㘕ADT;MjfqET&ifutV$BB!Ȫ+ԝʬeo<{W014$^`c'vo }K[7\a?ޒ/ vk}1_g!88M7Qy -Yb՚u=! 2J%ǟL@9% B .B(bR30o#(Y2 +;Ҥː)K6<+PhJ1V2*T@5(/n*@kx.TtaKUMt<F' \C(ǺXi GXUlEpN۳ Yc5ti:pyk-&Ʉp~ ?F$1R(q&7+$? ]"$<{/w:cQҋ&5H!7E!ȳ/,G'6GMK<'4F%86"PH72E-1Fә$ظ@J;@p(M;r^م R b$arwLM//Osn1Tcq҄WrYFvTqr9>lij] Mgr$39G $Ȕ4mt$<+Hڐ ska.68hzR:L蹦`/s;Sˊ Ys6 HI$R-7\Iós"W)aOŒL{Ccf: f#q*&bQc[yG,= 6f ƃEt" d1Jk a"_z+9$stĕ[s};K]n-s;}~bJo5 G =X%SR&,GA*g b0]_bvb]_zjFa+5< ;AЩa9'.DK)g&!9Yd8[#ql$N=FKlDف?F hY$Rs9%D l`4J">@4t1|MH9ZY`n_"qf-Eo{,I'ʈtX+98U2)ݓie@B! &[ڲp26D젯O|ؕNar:!=/N #x"cBd˶8PO:%Ѡqٌ,ByDgfr8boiViAE%i10UB;57lMMOQtgHbkdzcR cV̛ܾY%wU(EHD5zlT?$GGSǫA@ZU^*#ȼȱm*J$)Bnih O{ 'ǼjP Ь%!@r1Zr+VSGȵ wB#y wD( H.vưݼ3;LJ\KX[5ҍ5zŀkw3 XD,F39y]Z!UYYdL&|Oi!h"_̛ʄ"D}:Q!fHq:xX,CIu6-_?Q[kQD֮*uj MS?RѩKF௑bkՒ^90Q~}ɑqѝL: /]dnxgOWX#r%-G>Uݕ=r %0G(ȝBR +_!gO>EC "TⰃfD*L:*\&ӘlAi3[ ;IF@jl m6WJrP/4-z\Q iS<d7q0ol@aɁj C 0 :2Ψ(W5mtG'iʼnUHHM1g$gٓ \$ P3\؎;jD{3F@zoSHӵ@@AF\iL1#@hw>qϡƺ[9ݒ"}*!Q(*<nt1=5rIVF y kB#4%eqzG#չ򪨬SJwT0~kLj;; Jh̚}7Nޓ1S?fQ2'6ۀ(ae!5Jo)*_j14FJ`Y P2#0j,"^ \` 6Uc>> |8ڥ =(kg&atHC3Gp&[Gd;#U.dxREJlbCzJ  ə:=!./s.^YS7qo m=[`G(W\Ĩ<}\2f8؟Ņ5_WYǛ+9:\kjT4l-)yǢvEw1WΨ&JZQɊ|qb9,}jfўLgy&-rͽ4c^i f>P Ҁݜ']F3ɦSC}yPyS9j}Tjk 57ח1zbT5jtQ4 Y!^?W *i,⊡*nGA,7`#2ej=i81<[1}׎R쵢AuSh݆q'/Ji[rL9mM6UsR;-eB3]H վ;Ч.VDBQ**W}p@j UTgyfښ~!J&dLา7IB`ڑpIedOT sDpfʇ}V#׸nV_,(ِ@܁RѧzEv?<};T־(ODF]vji\>pA Ggd&tge%jjSxe`VLI+PdgWvd$fh4UȍbZjxܧkLm_,A,3X&< 1Vj B?j㏾B{ӰO'ҵ,$-Bcz5V*Tt֌< ֗ "TƘ = @G P Wc̙Q9ǽĿ :<[Gy#kzg?WTxb %Q1WU$^V+D4ɓӶ9o'PՒqx|۵ bI ]9KzϘץl-;0|%7:rW'xg9gP?$_[SYJ1G>#?[n>5'fEgGG4–f1?%a_\}TbP|06zz΋^lE!XYשãԭNXLȵ@-}'HBqߌa«-[LR L9IMxӫayHq~Zȳak[F^a/# haBMlF㤆28 8Ю"C:TꝪUPG`L3v5fs_ PHYR[899̡p擱$vSkH?F$7ZtAԛv04`M@fF8g~ȧ+5``%m͸#NDA3̄39bXόfs,`:;jx-:\2)Ojy/tg IEL:3$3*)ե8S)ySő9ʕsq K_]ʵ`I;}sG>|ή1Gr8tjY (Ds#X:Ђ'hiS=6`;r✅"յ4|C7J<_k._Uw,76eWկU}xK ^NoRd)SqzFkTX`g@}r'2w:h}pgCK$lOUI$dx" bf'zyK+r`2⎜X/جzQ5rIDy*F4{t6gƽa޽XaCFO:XB8Aip[G14ܨ\ '8o6I@^/8|,2uH%YKY ViKXV5O !mXI۷7b4xa_ ` E wyVt2`8͞d0$elwJGcc }h,b uu[>o<ޔuKx:nge*R2&9q%ǔ$PΌyY*U'ZE5P-5h+6`qV'r e!\HiHbְ?!բ =n|Y#] ?) O7>6e~"1ABJh'18`|֢2Ș-'opֶ %:R4 "O0< C!@Zrb&g3 TqrCϵ \/̍A`¹R趁.ƨs5m(.}KkiZ[:ǀUuxI{4&[пg`ũ씒ZkmkOcyD!ؒt s@)vb$7@Q4`.ԪHt[~T}:Ж1Ffz@g瑃B{F  }sE`s8sƁ cs$&Yvzv{R^Eyr-h,4i9J8 Qa^\I4P Y"LV8ZU TWYGݰ0,\BK@D 2 g5"Pgg$z%-iZDeƒJ⧑OG,X"V}feZE:PoE,*[ .tUv3mD}aZ/01!v6X,-%t1. ]̜M$ϫV?jmZ<mIc9s6oI551ն* ms';eǺM x#;[8e۸)=!l=r9X$_!1nlNC4 @IJ Pv'ҶF&+aᔕl.̽2s?|a{gO4Yْ5Q$OQs5튃qVh7IYlx*jn6I&8RʽRe(qFRFȠP esW\1&:ޚ5< ε 3yV[4`!XOv{g`iwB'hDQ',Dx8$~qmJʫ)"6)U(Pmt9w4L8\CwLJ}1ni?޿*JX4`廙ʙ99iwhM$G{Y5N_VH@y#h O$^slOR$wp7󠏫f/.K>Ⱥ}A/GNE ق},RQyU4NLL'< (+91:AoeGǖ<~)9*+{+[W [['I/5y b))&!q!yY#BLH,hmA[nնLuQT(a#šx0re];;G_h'w+\wgܦԖhht Z,Q#uQ_EjGEE{pP>k+K{J~c+ib~xP C"ց*b1Q _H\?BaDQ\7P1j/!6Z.m!\Ɂ&\  ϱ?aө&D'A6@;I{i/Qr(\'7,U-i1 ;vѣii׷m(b$ yWJ"N&˒lK6EqKVlR%BJfDe~ϔ*#!3-JfQˣB RɐF BsX+_)Yj74IOfST}7*.+3AG=Tnmsm_(Gl|?{qcMa YqNXQ&m ^i,AE8Sf}S yP_~*X'gS[rN+Nʊ3NIJl3 ġ|G*ΗcEPp'3`'Y͊6o7TB#NYOzϱ[<)N$xK&z/-eQ/~dy"8hV.F!Dj)PX~0bUrJG@" sP7s 3捞w(h`Vږ</jlub^K>̝7~c _VX .go%~xs\Q#xD,xF o3:YEE]l*m?'.\/UoG?fJh;cj$ Bc4 O`n%Z aZ+USae vZRY7mڭF/ax{i˩֣h)ygAײʦe?\yB}YCWnUTbq|},r$/>Y."!.4 ɚ>ޛ9vfve@8] 6醌#' CEr6i,(=^P9HY-aqBDWwFl9T,FC%OQi )moޕt-2x!;dܾe ,+x6 <)QΎ .K6ZxS:x<"cEOmѽ})W*z3yOmMt'>STt%ieؿ*a>_1Iobx,[6@@YEyM?qDhv%Xq{vbj5o'r*~?LZ2z'H @BWW'ׄnOe3l%]^PH5vA#72T:(h<K."s3jM4$~۷+1%wr){!1-Oz5ҞaDn?cl5`ؼ^Xtw7.a(AƧeegNOdQﮖ A O4V%ys{9ɓlqd0he{z^D=w1rSG$'A#ڿkGA8طw5>o/?E?t(şc@=BjnoA+`]y~hҐEB.,g?ƙnvt> d0;Comƴ #l8ΑgW%do7sߎoptw?h`k\ ˵G-a c |@QtF@,9a JכLG(FF<=!)rrs"xB; HehM髼t  pzwWVrm]aw0;Gbv{q1p:T zVbetm<7PY0`,ڟ '1,(aPy՚A@4s?on1hCۼ J&^zA$!np ,Ea[#h/֖[-"&֡uQ 7!5B0b<%asJ'xz\# ٯZ_2_|c2<$~E@١8KR7θC:Ws9@  WLf3M,,NS8Aer}B[Ξ^OʯQ2&^$LIu]N(W]#\I[ rDՎ"kP?}TP99;2# 9f-**Ӆ*0jO,€%,). .?0O5~fttC57r[9ӔTeeT*w9 J AY^df_!ct/^"^b^~G+"E&r;bcw]<5Xi//J/wa 7\+p)+/̘yO^]9~9'EE{ͩp{D?mߵJTu#.~#,&NV LRů:ŅUw ܠzXz F=GWo@/mLҽPޤUx)^.~,,(ى[M 0'm}#*ںvʷh&A?OVz!GbFfds;`d,`r}=ɓ#3>2K c"",kEx_!Q_~r ˄IPVgٰj>+VRekM_1;FΊ| A1 ӒޕwjCZjTe(:hyӔݺߙc*`7!#-.<|Rq񝭍m/ZXm/\m8?as_L!I|a8"f=q|ߟww]pKwݙ|ۀ&/ -.NuAcDRJ]:#Q.+LDfc!i!p۟_D(!L]G$0.v4vG&8!]CG-)dQ]H*ȍʁwJHRr|F0P=G%9YA@#zM~>IZT2H,H#sn*߿0ӽؾH%h<c'F*cr%k(#~`qCU&*>/]ҮBSn0)^ty.qarB tdDX~Pi@Jih:4a AYlMe !dZOh䀬K3Eiak/9>L}ai?R%sި" v 錢L2 PHs])̐DuFDl7+f$bL޺$d0dO V5jpR7(%:&L ON o6gpeܑ,=HHL- ؓhekCj729]Y9a#\OP:*$*vJ5P >͝$g.'^4<؀gIc!Xa˙C @ ~3JO;U*i(ԱY#6vEܾ134$/b5b|XcD,9`biSTfVAҘ,xL;8# zi,>tdő _O  Q)3ABH$DȌ ;hpQŧYULcC;^fA8,ڂ g֖l8UpPd~C/H ja|qABї|͙j5^0TY_  1hapd7YJhy=4>AMyJPEI n>jWJݟ5_5ƞq8{\7z~>])ڼ :'O̥jYtxر\@g^s\>SK .ͪw@'ʁP?O`59D~TUX5y{5NݛMܖu'BL$y+z6S:gCf2cOp_O^N Тmj 'z'yRzVfLm5-@ aSi37u(mڴq኎C庋!//3I(J}#Moz%7wFV#H)wN@2YfեXa6iF.٤8m_[d ]y+ ʒ|߆ԍmF3'kzgrpeC{O1аw!\)@iY+p@J|>[=MMv]m$@FaP3]ZS@X;2m⓵ΪBĐ5M-04=ֳO~d}͒ftg k `̪[=̳ՉEo| ,YE S<vF>|H#g8:|ybkt&zeUBօ  oP3dm(R!I+<"ZD@?>3#URF8_ 錥$Zn(\i!ouyRFibS#p?Hi`e8a|)LjR/i91(YG_ O=ۻ5%5~y77()Qѵ`9/.|AxƠ=K, ۰8t;k8kz<قv9;?j'Ǘ(>8ڈV_',`ٕHÏqsjZziKqI|gZ!|ogIĒjȪQ [4 $~Ey߰J܂#+LvjhjJoifŖK7lcU/JIT{ثl}W]5QƯ_zsDƣE-ZAFSc{>*i_nJHq 7;DߊMI5xKEqZ1aĔQWBIVFYWAEn;a$O$SL6/KJVo4[N Gt6_,DPƅTXCL\~(=V-ꌹ%1@ K홴=!6isa* eR3i3aBwTL@P!=6 &qGHjϤ 8'a2WPK*\rUff5\.#"#6&=#3733267>54&'#"&'.=467>32267>7##"&5467>32.'.#"3%.#">323267>73354&'#"&5467>;%2#!"&5463%!"3!2654#53#"&=33'#535#53#53%#546;#%#532#'#53+53#53#53 2)   '      ((     !          mmtBBv$  !! !!l  s !O@@AAAABB 3 ! f  (+,! #}  q]     $ %$  HBBB6@7     ff(Ek"3267>54&'.7#";2654&#"&'##33>32%267>7#"&5467>32.'.#"%.#">323267>73354&'#"&5467>37  j// --E   0?     22 '!   ) #"     !  T  -! ;-!!- )B **267*.!  '      v   ff#`#"&/.546?>327>32#"&/#"&/.546?'.546?>327>32#"&/#"&/.546?'.546?>327>32#!"&=463!2#!"&=463!2#!"&=463!2J+b$................EEETI,b...........///..f4f$7 !7! 7267>54&'.#"'35#44a    88_6_    Rff%6\%"&'&4?62326?62#7"&'&4?62%"&'&4?>54&'.#""'&4?62#}"A33+*0.++A" .*0.++4333+ +44++0/++U*0.++4444+f5fi62"/#"&5"'&47223!:7>7>7>764=4632"#!*'.'.'.'&4=463t tn              t  >t &    &  '      ' f5f;]>7>7>7<=<5.'.'.'*+*#!4&54&'.'.'*#81#0"1*#0181:3"#":;:3>7>7>5465!:;:3>7>7>7<=<5.'.'.#"&#:%*#0"181.'81041<5&4=<7<504181>78102102362;::1021818180181810"10"#"+"&0181810"1*#"+*'*#0"181.'81041045&4=<7<104181>781021027:;:3210218181010%!4&54&'.'.#"&#:3>7>7>5465!:3"#"23021818101009818#0"#"+*'*#0"181.'810410454&=465<104181>78181201:7:;:#"&#*#0"181.'810410454&=465<504181>781021:362;::3021818980181810"10"#"                                  H  E        l                                      +  ]  +          j   f6f _%26=4&#"1#<54&'.'.'*+*##";:;267>7>7>7>53265.#%465>7263:;:323#<510#*+*#"&'.'.5<5!26=4&#"3Hz   4  |         4    r             5  n/  5 ff-"5#"&?>01+67>76'&'.'&800F7'&-\   ]6++5 C**<I118/++D  V436-&%7ff!+"327>76514'.'&3#5#535#53360/FF/0660/FF/0`XX33/:G/0660/FG//65./G1FFy33ff'5%'676&'&'&'&2727817>'81%"&54632#1o &%,,V'& %::o"C^^CC^_Bjo%,,V'& %&,,V&'**o!M_BB_^CC^ fif "-9DP[`d6&#'&172?64/6574&#"12?'3265'4&1'&"7%&37261'764/&"!!!!eg ? ?( l.? ?("n!@ @( m'? ?(.} m)@ :")m #? @( g#? >(#m #> ?( 5ff)9^.+#>3:32&353267>54&'1+532"'7##5#3533.'.'.'732654|+  0 vB"2 _ !'   ^,^vppv  ^ B9*" *) oT ' –    fof7l1"#*#0&5.'0"1&'.'&63>7>321021>7:1%66:3'.'.'.5467>76"167'.'.546723>7<1.'.54601265<1.'.5461205>'3810#"'"&1&'.'>790230"1.'*1.5761o%  1g2%* E ?2k   % &   & $ #   D D $M#4 $" 5 ) 30  #EM Y ),[0             2     $   @# D #M#6          ff?"327>7654'.'&"/"/&4?'&4?6276270/FG0/55/0GF/0V!OO !UP#JO !O:H/0550/GG0/55/0G !PP!OP "UO"J faf #-9COY]a3265'4&17'&"7%&37261'764/&"6&#'"172?64/6574&#"12?!5!5!lhE>>" m-> >If "> > m.> >J\- ff>@@(#m !@@m(? ?Km (? ?:Țf.f9%1'.=46576%64/.=461&=4657 > 3 > qdjq ? 3 > dff =J"2?6&#!54&+"3"0#"&1./.+"3!26=4&#"&54632#a  G uLL M|      ^ ^  p  ff#764/&"'&"2?2?64'g????5>>>>f;f:F6&'.'.'.'&'&673267>764'.'>732654&#",4`)+ GmG.0HqH -))A 2  5y$$]7 GmG&[GrH 2&%-'2  ' 6ffG%"#*#"#<54&5>7>7>740#4&'.'.764523:32300'46'.'.'.564'467>7>7>76&5"#*#"#2362323:3*#>7>7>74654&5.'.'.'778o787 (" 787o877 /%- . +   ,+,X,,, * # ,+,X,+,2f3  %>}?      9'B+-`4:6Z#E)5#, 7%8  00  6#5  37      D*'    ff#++"&=#"&=46;546;232FFFf2f-6Gf;26=4&+"%'.+3;!#3!2656&'5254&#"63>556?64/&"2?;065g ! Z U+   f&YY=  s t  ; k + I    +|gYZ3<  ko  = f f+62&'&'&47>64/&"27x<@ / 0055e+,$$2,   !""/ 055e,, 0<@ /p  fJf<JXf#";2654&+"&546;246;2354&+";5#&5%#"&546;2#"&546;2#"&546;21FF12FF !! !?F22FF2   E22EE2 2El""!!s ""2EE22F?!!]^ff2[7>.!&6.'".#07>1>7661'.#*#.'*#">727>3.'DB3}:'V+73FD'X,'L##L',W&A2=#Q* ==!)N&=2f!E' :;  #E %?#L&$E! E$&L#;#&$ ='&c< 3   ^ ff3D#'0"+"&'4&57.5467467'.5461%32#"&57:326?x ? lxxZZ{  pE2 " 8w{#22#j?;jfUf;X"327>7654'.'"'.'&547>7632#1"327>7654'.'&#G>>\\>>GG>>\\>>GA99TT99AA99TT99A4-.DD.-44-.DD.-4\?>GG>>]\>>GG>>]rU98AA99UU99AA89U2D.-44-.CD-.33.-Dfmf0381267>5815814&'.#81#81"8181#5814&'.#81#81"81813813#81"0181381381267>58150454&'.#0"1WW FF/.  .f8f3?W#"5.546;04714&0"#.#"*1";2656&#'2#"&546+"&54671;2651K1F2& !$ ,* 1FF11FI1z"" . - sE1*> E!!#m!!F11FF11I Y !!..!f+f3.#"347>763235"&'7#7327>765##)sC>67QK=)).3XGL3XGL)sC>67QK=))..7Q67>/))=+$GLY,$FL.6Q67=.))=`f!=B%3#"327>7654'.'&#"'.'&547>763235#ZZ-]QRy####yRQ]]QRz#$$#zQR]JABaaBAJJABaaBAwZZ@ ##zQR\]RQz$###zRR]\RRy##bAAKJAAaaBAIJBAbYY`f #/<HU#"&54632"32654&"32654&4&#"326"32654&#!"32654&"32654&#X3%%34$$4X$44$$43X$33$$4394$$43%%3%33%%34$$44$$43%33%%34$%33%%3494$$43%%3}3%%34$$4X%33%%343%%33%%33%%33%%34$$43%%3f_f&4FWf!"5.5463!23.##";2654&'#";2654&!"31!2654&##!"&5463!2#";2654&#f8P5%=  E:#=   )8PP8>8PP8Y4%%55%>%4  O9!8F  r%5 y *P88OO8s8P %44%o%55%F f_f*;G!"5.5463!23.#!"31!2654&##!"&5463!2''77'f8P5%=  E:#q8PP8>8PP8Y4%%55%>%4jnmnnmnnO9!8F  r%5{P88OO8s8P %44%o%55%mmnmnnmfcf8D_"&546;7>3232#!3!26734&/+"&=7"32654&'>7>7#"5.546;>79QQ9@ /!2 A3P824&D!11##1 9P5&u3232#!3!26734&/+"&=7"32654&'>7>7#"5.546;>7''77'9QQ9@ /!2 A3P824&D!11##1 9P5&u)noooono;7621"#"&'.5467>7>7>764'.'.'.'.5467>3237"#"&'.5467>7>'.'.'.546327#"&5467>7>7>7>764'.'.'.'.'.546721 bM  Maq  N ! '    " M'        3 b p bv    *&['  ]&   )'-,V%&    !)Z)"    +f2f%D^z'.+3;!#3!2656&'52%56?64/&"2?;0651#"&/#"&=46;7>>54&'&"3267>54&'.326g ! Z U+   fb=  s t  ; 9//9 T Ik * I    +|g<  ko  = 9?:'( 4>##? 44 f ,f,<^{.#!!676!327>767676&'&'+532"%#!!!!!&'.'&'%32654&##7>'.#"#33>733267>?3#7#'.7%2#"&/#37>7"767>'&#(wPB#077n33(+ >%#Z0/0U#$ "<*\g#E &'>uN].&%< >&6MM6Y)   XaX  L%%sY)  YEEJ)/4- 1 + C`Y ,# &" %(32n771%< P%-*12b--!  (j) }_P ='&+% (L75M3 & J,V+R#% J<"*a'N*) 0 +T.H L IPf8t67>76327>32#!"&5>?.#"+.'465463!2327>767>7>;8321#0"1"'.'&'#"&5-.RR[310Y(("V [-yE.++J  } +[-wD.*+J   ..RQ[301Y()"W VJIk $!V \,2 +$&  [+1 *$& VIIj $!VJf<#"&/#"&/.546?.546?>327>32u ! #~u"!!v   $vv " !v v $  Jf8k{"'.'&547>7632327>7654'.'&#"+"&=467>54&#"#"&/.7>32+"&=46;2j\]((((]\jj]])(()]]!"sNMXXMNt!""!tNMXXMNs"!+ j F$"b&'.'&547>7632#8"327>765<14'.'&##"&/.546?>327>32j]]((()]]jj]])(()^]jKBBbbBBKKBBccBBK  C` C((]^ij^]((((]^ji^]()ibBBLKBBbcBBJLBBc DbD Jf8#!#81"&'.5041467>32!2, 2 1  Q   1 ,! .  1     1  . ff/?#!"&=463!2#!"&=463!2%#!"&=463!2#!"&=463!2.! // ; /.! // ; /&.! // ;!..! // ;!. // !..!7 // // // !..!7 // // ff7So0#.5<15<1467301#.504=0454673101#.504150414673010!.5<15<1467!01!.504=045467!101!.50415041467!01%         $  $  $ I  v!!Q!!v  P!!w!!  v!!Q!!v  P!!w!!Jf=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5 0??/  4GF4L  4HG4  3BB2C2  ,99+  3Eb  b M22M  MP55O_  S87S  R56P 3M  I//I  M4ff1f%47>76321#"01"&'.'"#"&#"'.'&5'67>76;4654&54'.'&#"13021>7>7&K22:922L8+ )H  812J))qEDK kIHSRHHkR> )  :f*)$$66$$)3Q/ &5$#)a8..A :43MM44;Jw(A  7%Lf$n#"&'.'.5467>7>3254014�"1#854+0"1"010130213#0"1"0183061!0126540150414+0"1"018302138126540!$%!!]99GG99]!!%%!!]99GG99]! B  ?? * W } ~ M8FG:8]!"##"!]8:HG98\!"$$"!\8i \ j k  Qj j Jf8T"'.'&547>7632"327>7654'.'&##"'.'&547>7632j]])(()]]jj]])(()]]jXLMs!!!!sMLXXLMs!!!!sMLX:'&,,&'::'&,,&':)(]^ij^]((((]^ji^]()!!rMMXWMMr!!!!sMLWXLMs!!Z+'&99&'+,'&::&'5f I!"&5463!2#"3!2654&#81#"&/.546?>32>32;QQ;;QQ;& <;  ;R::RR::R < ;<Jf8"'.'&547>7632"327>7654'.'&#j]])(()]]jj]])(()]]jXLMs!!!!sMLXXLMs!!!!sMLX)(]^ij^]((((]^ji^]()!!rMMXWMMr!!!!sMLWXLMs!!Jf!"&5463!2"3!2654&#x7OO77OOO88NN8 8O ff$'.#" .#"3267>54&', "# #" ,   #"  G,  1  - "# b   #" J f #.54632 @  &&   A %% @  Jf)F81"&/#"'.'&547>7632#"327>7654'.'&# 3}EYONu""""uNOYZNOu""(% . 922JJ229932JJ239 #)""vNOYZNOu"!!"vNOYE}4 !-^K229832KK229:22JJaf/#!"&=463!2#!"&=463!2#!"&=463!2a v   v   v  eff]f:"'.'&547>767327>7654'.'&'5#gZ[''! rNMY?56OdCCLLCCcO56?YNMr !''ZZg''Z[g]SS+, ! `;76%47>7632#"'.'&,,M%%UVaaVU%%%%UVaaVU%%gEENNEEggEENNEEgX u 6 #bUV%%%%VUbbUU$%%%UVaOEEggEEOOEDggEEff:Rk#";654&%&767>7654'.'&'4&'&7>'&7>54&'/0d  ( + + (   0%&55&%02I@  0550 @I"''"]@  "#P--00--P""   *)a769976a*) M* b99a  *  B&&CffK\"/&4?627620"'81'"'81'&4?'&4?6281762812112764'1&" S L  DEDDEDDD  <  [d L  DDEDEEDE   R  `f!Ck%&320616&'4&#!"3!265#0"1"&5&67>7.54632#"&##"&'.'#"&'23267>54&'tu'%4]  F11GF2    (3 y54$A("> $$22$$3 "   ) $$ ff$9'.#"'.#"3267>54&'!3.5467#!5#"&'5 p  4 JIq'  4q5 J|   l ff!";!532654&#!!z 11 L 1-$ 1  1GG1  1`f7W47>7632>56'.'&#"3:3'&'.'&576>7>54'.'&#"'&67.'.'&#"&"&&'.'&01006767>7>'R77?>77R3 nIJTSJIn nIJS+801G7o6  =)*./)*=VCE.6     + ' ,d  ((q<=((, )w>77RR77> *SIJn nJISTIJm iP43;.7 /*)=>)).Ju8o     AJ)(e-- &/ I.?a*`f (6364/&"7'&3!26/#2?'654&#!"i^,d <.y Gf^!^ <.( k, ]=V r! ]3!467>;2!2       < <      <  <     ff%' 'rrqFf$`"'.'.'.7>7>7627>54&/7>54&/.#"'.#"326?326j2BB21sBBBBs12BB21sBBBCr1RR  RR 0sBBBBs21BB12sBBCBs01CB2R   QQ   R 5f-3X(]z"&"#"#"&'.'.'.'.'.'.54&5.'.'.#24'.'4&'.'.'.740'&"'&"'&"13"&'4&54&54&'.'2010634&'.7.'.'4&'.'.'"&'.7&'.5#<5465>3"&'<141>54&'.16&'5&45.#"&'>7:326&'>762.'&0*#>703"13:362;26'264'&47461>3>36&'0&#"&#.'.546762322>37>7>1.7>2##"&'.#"#216662?627627>104'.'&47>7>56&'.5467645<'.546762#6263263263>306363065>5>123133027:32>53""3."1>7>3>30#*#2'2#""'&'02223#13>32.'.'.#".5>77*#&4'.#"&'"&5&'1'&"#"'0321#"#"0#*"#323>7<54&'818#"&'.'.5467>7>3254&'.+54&'.+";#";267>54&'.+";267>5"&'.'.5467>7>321"3267>7>54&'1.'.##"&'.=467>;5#"&'.=46762;232'";267>=4&'.+54&'.+";#7#"&'.=467>;2#'";267>=4&'.+  @'             1wA ;L0/j99h0/ML/> O%X>1B$#C//B$$B1!m ,AA,$B/0B$$B00B$#C//B$$A10A$Mm!"m!!mAAAAA    &<   %) 0[)1KL1/i99h0/M!5c+w +B$$A01C#$B0076m7766h0C$$B10B$#D10A$#C0/B$$A1I7k67M776o66M666f:W>32&'.?5#75#73267>54&'.#">54&/.#"326?8   , xH?`I  3  w""\ \m  ,   y_@I3    #"w\  [Jf!!Ze ZJZ[Jf!"3!2654&# 7/CC//CC/PPJB//CC//BPPJf #!!3!5UUWTJf '   7ggggggggfhffhhfhff$BIio ;7>?'764'1'.+"1?3#726?64/.#'"?/1'.'.+"';26?64#'73.1#5.+'1;26?5465>'4&'#'73%./'"326?64/7/7'7'&4?/.+"1;26'#'731764/.+"81;267#'73% C'  ($ K %266  +: ($ I (!& ,55I% K !PP  K %365{  @#  "' K "66  +< ($ K (!&755 PP! K %% K  55<< v<< x 3f33f{A GF7B B///c G? B  @;?-/-/B : 7 @ ///  @ >9@ ; ////[ F @B  ?<>-..7  8 B?  Y///g g h e XXYJf24&'#4&#!"3#"!>=.+";>=4&./.sk )\\]f `f.2?/?/?''.#"326764''7>>==3ff32ee3ff32eeT  N  aa? !??! j56jj65l56jj65 )5 5feff8&'.'&'&654&'%767>767>54&-78p43%$!//j66-%34p87-.65j//!#H"-  g "ff/?N^q%4&#"3267>5&"27>56&'&"32654&'&"27>56&'&"#16?64&"27>56&'&"3267>'6&'.267>'0&5/ /.! @@  O@  / @?  QQAA  l#b#F1,?'r)P93((&,,- E>  ? - ?  [NM?  "!).C**l'&38O'm'`f$IP.'.#"3267>7>54&'#"&'.'.5467>7>32%''#_8;BB;;`####"`8;BB;;`####/W54u;;t55S  T85t;;u41X 1o%B&`;`####"`8;BB;;`####"`8;BB;1W  T85t;;u45T  W54u;;t5o*A%ff (2?6&#!"!"3!26=4&!26/&"3v<     ff)!"3!26=4&#&"3!26'!"2?6&#<  u6  fgf"'+5>CHLV%!"&5463!21"13!2654&#!#53+53#"&'7:;'>53%#53%#535#53'*+532su // 0/V    zEEFF66o 0A000000E660  00 $,   1111000 -OFFFEEF%0ff/?O_o!"3!26=4&!"3!26=4&!"3!26=4&!"3!26=4&#";26=4&#";26=4&#";26=4&g2     .   .   . X1  1  1  1  1  1  5  5  5  5  5  5  5  5  5  5  5  5  5  5 ff/;IUco!"3!26=4&!"3!26=4&!"3!26=4&%2#"&5467"326542#"&5467"32654#"&546324b   =      #(('''::')99)(('''::')99)i>++<<++>p ;  ;  :  :  :  : '('&:(';:()9(''(9()9:(':+==++<< ff0BRdt%#";26=4&%!"3!26=4&!2#!"&=463!5!"3!26=42#!"&=463%!"3!26=42+"&=4637#";26=4326=4&+"!326=4&+"326=4&+"3|        C&&C&&    && %%   %%%%/  c  P  P   <  <  =  =  =  = !%=$$=% <  < !&<&&<& <  < !&<%%<& <  <  <  < 9 <  < fG:+>_< CC5 ,ffg O ,d O ,:L`^~v d < \ * z$:lF^DL| thtRr * !!n!!""n"##z$$%8%%&&'J''(J.h./ /8/P/r01@1123>334>45j6Vdo    x  ! r        4;h5p-core-30h5p-core-30Font generated by IcoMoon.Font generated by IcoMoon.H5PH5PVersion 1.9Version 1.9h5p-core-30h5p-core-30h5p-core-30h5p-core-30RegularRegularh5p-core-30h5p-core-30PK*\^̘ 1h5plib/v127/joubel/core/fonts/h5p-hub-publish.eotnu[ LPȇh5p-hubRegularVersion 1.3h5p-hub 0OS/2`cmapVҒTgasppglyf+xheadrl6hhea$hmtx6x@loca "maxp_, name:SLpost 3 @ @@ 8  797979.#!"7607>'&"5  % 3 %  @33%4&+.#!";#"!>=.+;>=4&'...tk L]]]f 16&'&"0121!"3!02127>51 TE20  1E  1E T F2 K5&4&/&"8#'&"882781>51 Z4P4YG4:   ZOY4:   '   7ggggggggYgggggggg #!!3!5UUUU,=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5  /?>/  4FE4L  6GG5  2CB2C2  +99*  2ECb  b L32L  MO56N_  S78R  Q55Q 4M  I//H  M4{$'.#" .#"3267>54&', ## ## -   "#   +  1  - ## a   ## !%!"3!2654&/CC//CCNrC//CC//C!"3!2654& 7/CC//CCOOC//CC//CPO!!Ze ZZZP6&'&'.'&'"'.'&'&6767>75276767>767>51((a88=@p)"hEFGDi!)p@=98c(( E*).022f220.))F>y86..E C3)//e340EiiE043e//)3C E..7367o875.*)E E))./c3L͇ī_< ڿ!ڿ!, J:R8d|] c      n  4/h5p-hubh5p-hubFont generated by IcoMoon.Font generated by IcoMoon.Version 1.3Version 1.3h5p-hubh5p-hubh5p-hubh5p-hubRegularRegularh5p-hubh5p-hubPK*\x&h5plib/v127/joubel/core/images/h5p.svgnu[ PK*\S5 ff+h5plib/v127/joubel/core/images/throbber.gifnu[GIF89aVVVЮfffbbb솆ꎎ(((&&&BBBRRRnnn覦HHHⲲ>>>PPPdddࢢ$$$ZZZxxx222...~~~ JJJ```vvv|||^^^NNN"""000444jjj***XXX zzzLLL,,,ttt888\\\<<V0lUf(PNMn  sF;2Gq6! `2oVuLʵZ *^ 'T+6^=H nh h! ,`XaJ$+W23F5hO )9[ ).Y5DkN;l [_i#D4 1U #1pT0>VUE=!Q/Nff>!ת'/! ,VMT H"U IJ& ) ["$* N8]O[`)P'KX"]# SW"G^)\_ Y %8(RL!%(  ZQ'(#  1 ! , j-M V'6-U<[oN^/;^>Q;qT=8)eo>>,-J"8&cj1*_1ml>Q f:.1'c`VѳM3sQ 6r2; #bBd0l ! G,G >6 8,)0;1%#(=G>!<-'E/ A. 1G4 ?$&"G׳ * D6,79):@B5F3+ C2-! ,V( #/'Q8i(1!11p> #)1i]/PM->5h5plib/v127/joubel/core/h5p-default-storage.class.phpnu[path = $path; $this->alteditorpath = $alteditorpath; } /** * Store the library folder. * * @param array $library * Library properties */ public function saveLibrary($library) { $dest = $this->path . '/libraries/' . H5PCore::libraryToFolderName($library); // Make sure destination dir doesn't exist H5PCore::deleteFileTree($dest); // Move library folder self::copyFileTree($library['uploadDirectory'], $dest); } public function deleteLibrary($library) { // TODO } /** * Store the content folder. * * @param string $source * Path on file system to content directory. * @param array $content * Content properties */ public function saveContent($source, $content) { $dest = "{$this->path}/content/{$content['id']}"; // Remove any old content H5PCore::deleteFileTree($dest); self::copyFileTree($source, $dest); } /** * Remove content folder. * * @param array $content * Content properties */ public function deleteContent($content) { H5PCore::deleteFileTree("{$this->path}/content/{$content['id']}"); } /** * Creates a stored copy of the content folder. * * @param string $id * Identifier of content to clone. * @param int $newId * The cloned content's identifier */ public function cloneContent($id, $newId) { $path = $this->path . '/content/'; if (file_exists($path . $id)) { self::copyFileTree($path . $id, $path . $newId); } } /** * Get path to a new unique tmp folder. * * @return string * Path */ public function getTmpPath() { $temp = "{$this->path}/temp"; self::dirReady($temp); return "{$temp}/" . uniqid('h5p-'); } /** * Fetch content folder and save in target directory. * * @param int $id * Content identifier * @param string $target * Where the content folder will be saved */ public function exportContent($id, $target) { $source = "{$this->path}/content/{$id}"; if (file_exists($source)) { // Copy content folder if it exists self::copyFileTree($source, $target); } else { // No contnet folder, create emty dir for content.json self::dirReady($target); } } /** * Fetch library folder and save in target directory. * * @param array $library * Library properties * @param string $target * Where the library folder will be saved * @param string $developmentPath * Folder that library resides in */ public function exportLibrary($library, $target, $developmentPath=NULL) { $srcFolder = H5PCore::libraryToFolderName($library); $srcPath = ($developmentPath === NULL ? "/libraries/{$srcFolder}" : $developmentPath); // Library folders inside the H5P zip file shall not contain patch version in the folder name $library['patchVersionInFolderName'] = false; $destinationFolder = H5PCore::libraryToFolderName($library); self::copyFileTree("{$this->path}{$srcPath}", "{$target}/{$destinationFolder}"); } /** * Save export in file system * * @param string $source * Path on file system to temporary export file. * @param string $filename * Name of export file. * @throws Exception Unable to save the file */ public function saveExport($source, $filename) { $this->deleteExport($filename); if (!self::dirReady("{$this->path}/exports")) { throw new Exception("Unable to create directory for H5P export file."); } if (!copy($source, "{$this->path}/exports/{$filename}")) { throw new Exception("Unable to save H5P export file."); } } /** * Removes given export file * * @param string $filename */ public function deleteExport($filename) { $target = "{$this->path}/exports/{$filename}"; if (file_exists($target)) { unlink($target); } } /** * Check if the given export file exists * * @param string $filename * @return boolean */ public function hasExport($filename) { $target = "{$this->path}/exports/{$filename}"; return file_exists($target); } /** * Will concatenate all JavaScrips and Stylesheets into two files in order * to improve page performance. * * @param array $files * A set of all the assets required for content to display * @param string $key * Hashed key for cached asset */ public function cacheAssets(&$files, $key) { foreach ($files as $type => $assets) { if (empty($assets)) { continue; // Skip no assets } $content = ''; foreach ($assets as $asset) { // Get content from asset file $assetContent = file_get_contents($this->path . $asset->path); $cssRelPath = preg_replace('/[^\/]+$/', '', $asset->path); // Get file content and concatenate if ($type === 'scripts') { $content .= $assetContent . ";\n"; } else { // Rewrite relative URLs used inside stylesheets $content .= preg_replace_callback( '/url\([\'"]?([^"\')]+)[\'"]?\)/i', function ($matches) use ($cssRelPath) { if (preg_match("/^(data:|([a-z0-9]+:)?\/)/i", $matches[1]) === 1) { return $matches[0]; // Not relative, skip } return 'url("../' . $cssRelPath . $matches[1] . '")'; }, $assetContent) . "\n"; } } self::dirReady("{$this->path}/cachedassets"); $ext = ($type === 'scripts' ? 'js' : 'css'); $outputfile = "/cachedassets/{$key}.{$ext}"; file_put_contents($this->path . $outputfile, $content); $files[$type] = array((object) array( 'path' => $outputfile, 'version' => '' )); } } /** * Will check if there are cache assets available for content. * * @param string $key * Hashed key for cached asset * @return array */ public function getCachedAssets($key) { $files = array(); $js = "/cachedassets/{$key}.js"; if (file_exists($this->path . $js)) { $files['scripts'] = array((object) array( 'path' => $js, 'version' => '' )); } $css = "/cachedassets/{$key}.css"; if (file_exists($this->path . $css)) { $files['styles'] = array((object) array( 'path' => $css, 'version' => '' )); } return empty($files) ? NULL : $files; } /** * Remove the aggregated cache files. * * @param array $keys * The hash keys of removed files */ public function deleteCachedAssets($keys) { foreach ($keys as $hash) { foreach (array('js', 'css') as $ext) { $path = "{$this->path}/cachedassets/{$hash}.{$ext}"; if (file_exists($path)) { unlink($path); } } } } /** * Read file content of given file and then return it. * * @param string $file_path * @return string */ public function getContent($file_path) { return file_get_contents($file_path); } /** * Save files uploaded through the editor. * The files must be marked as temporary until the content form is saved. * * @param H5peditorFile $file * @param int $contentid */ public function saveFile($file, $contentId) { // Prepare directory if (empty($contentId)) { // Should be in editor tmp folder $path = $this->getEditorPath(); } else { // Should be in content folder $path = $this->path . '/content/' . $contentId; } $path .= '/' . $file->getType() . 's'; self::dirReady($path); // Add filename to path $path .= '/' . $file->getName(); copy($_FILES['file']['tmp_name'], $path); return $file; } /** * Copy a file from another content or editor tmp dir. * Used when copy pasting content in H5P Editor. * * @param string $file path + name * @param string|int $fromid Content ID or 'editor' string * @param int $toid Target Content ID */ public function cloneContentFile($file, $fromId, $toId) { // Determine source path if ($fromId === 'editor') { $sourcepath = $this->getEditorPath(); } else { $sourcepath = "{$this->path}/content/{$fromId}"; } $sourcepath .= '/' . $file; // Determine target path $filename = basename($file); $filedir = str_replace($filename, '', $file); $targetpath = "{$this->path}/content/{$toId}/{$filedir}"; // Make sure it's ready self::dirReady($targetpath); $targetpath .= $filename; // Check to see if source exist and if target doesn't if (!file_exists($sourcepath) || file_exists($targetpath)) { return; // Nothing to copy from or target already exists } copy($sourcepath, $targetpath); } /** * Copy a content from one directory to another. Defaults to cloning * content from the current temporary upload folder to the editor path. * * @param string $source path to source directory * @param string $contentId Id of contentarray */ public function moveContentDirectory($source, $contentId = NULL) { if ($source === NULL) { return NULL; } // TODO: Remove $contentId and never copy temporary files into content folder. JI-366 if ($contentId === NULL || $contentId == 0) { $target = $this->getEditorPath(); } else { // Use content folder $target = "{$this->path}/content/{$contentId}"; } $contentSource = $source . '/' . 'content'; $contentFiles = array_diff(scandir($contentSource), array('.','..', 'content.json')); foreach ($contentFiles as $file) { if (is_dir("{$contentSource}/{$file}")) { self::copyFileTree("{$contentSource}/{$file}", "{$target}/{$file}"); } else { copy("{$contentSource}/{$file}", "{$target}/{$file}"); } } // TODO: Return list of all files so that they can be marked as temporary. JI-366 } /** * Checks to see if content has the given file. * Used when saving content. * * @param string $file path + name * @param int $contentId * @return string File ID or NULL if not found */ public function getContentFile($file, $contentId) { $path = "{$this->path}/content/{$contentId}/{$file}"; return file_exists($path) ? $path : NULL; } /** * Checks to see if content has the given file. * Used when saving content. * * @param string $file path + name * @param int $contentid * @return string|int File ID or NULL if not found */ public function removeContentFile($file, $contentId) { $path = "{$this->path}/content/{$contentId}/{$file}"; if (file_exists($path)) { unlink($path); // Clean up any empty parent directories to avoid cluttering the file system $parts = explode('/', $path); while (array_pop($parts) !== NULL) { $dir = implode('/', $parts); if (is_dir($dir) && count(scandir($dir)) === 2) { // empty contains '.' and '..' rmdir($dir); // Remove empty parent } else { return; // Not empty } } } } /** * Check if server setup has write permission to * the required folders * * @return bool True if site can write to the H5P files folder */ public function hasWriteAccess() { return self::dirReady($this->path); } /** * Check if the file presave.js exists in the root of the library * * @param string $libraryFolder * @param string $developmentPath * @return bool */ public function hasPresave($libraryFolder, $developmentPath = null) { $path = is_null($developmentPath) ? 'libraries' . '/' . $libraryFolder : $developmentPath; $filePath = realpath($this->path . '/' . $path . '/' . 'presave.js'); return file_exists($filePath); } /** * Check if upgrades script exist for library. * * @param string $machineName * @param int $majorVersion * @param int $minorVersion * @return string Relative path */ public function getUpgradeScript($machineName, $majorVersion, $minorVersion) { $upgrades = "/libraries/{$machineName}-{$majorVersion}.{$minorVersion}/upgrades.js"; if (file_exists($this->path . $upgrades)) { return $upgrades; } else { return NULL; } } /** * Store the given stream into the given file. * * @param string $path * @param string $file * @param resource $stream * @return bool */ public function saveFileFromZip($path, $file, $stream) { $filePath = $path . '/' . $file; // Make sure the directory exists first $matches = array(); preg_match('/(.+)\/[^\/]*$/', $filePath, $matches); self::dirReady($matches[1]); // Store in local storage folder return file_put_contents($filePath, $stream); } /** * Recursive function for copying directories. * * @param string $source * From path * @param string $destination * To path * @return boolean * Indicates if the directory existed. * * @throws Exception Unable to copy the file */ private static function copyFileTree($source, $destination) { if (!self::dirReady($destination)) { throw new \Exception('unabletocopy'); } $ignoredFiles = self::getIgnoredFiles("{$source}/.h5pignore"); $dir = opendir($source); if ($dir === FALSE) { trigger_error('Unable to open directory ' . $source, E_USER_WARNING); throw new \Exception('unabletocopy'); } while (false !== ($file = readdir($dir))) { if (($file != '.') && ($file != '..') && $file != '.git' && $file != '.gitignore' && !in_array($file, $ignoredFiles)) { if (is_dir("{$source}/{$file}")) { self::copyFileTree("{$source}/{$file}", "{$destination}/{$file}"); } else { copy("{$source}/{$file}", "{$destination}/{$file}"); } } } closedir($dir); } /** * Retrieve array of file names from file. * * @param string $file * @return array Array with files that should be ignored */ private static function getIgnoredFiles($file) { if (file_exists($file) === FALSE) { return array(); } $contents = file_get_contents($file); if ($contents === FALSE) { return array(); } return preg_split('/\s+/', $contents); } /** * Recursive function that makes sure the specified directory exists and * is writable. * * @param string $path * @return bool */ private static function dirReady($path) { if (!file_exists($path)) { $parent = preg_replace("/\/[^\/]+\/?$/", '', $path); if (!self::dirReady($parent)) { return FALSE; } mkdir($path, 0777, true); } if (!is_dir($path)) { trigger_error('Path is not a directory ' . $path, E_USER_WARNING); return FALSE; } if (!is_writable($path)) { trigger_error('Unable to write to ' . $path . ' – check directory permissions –', E_USER_WARNING); return FALSE; } return TRUE; } /** * Easy helper function for retrieving the editor path * * @return string Path to editor files */ private function getEditorPath() { return ($this->alteditorpath !== NULL ? $this->alteditorpath : "{$this->path}/editor"); } } PK*\l{%%h5plib/v127/joubel/core/composer.jsonnu[{ "name": "h5p/h5p-core", "type": "library", "description": "H5P Core functionality in PHP", "keywords": ["h5p","hvp","interactive","content","quiz"], "homepage": "https://h5p.org", "license": "GPL-3.0", "authors": [ { "name": "Svein-Tore Griff With", "email": "with@joubel.com", "homepage": "http://joubel.com", "role": "CEO" }, { "name": "Frode Petterson", "email": "frode.petterson@joubel.com", "homepage": "http://joubel.com", "role": "Developer" } ], "require": { "php": ">=7.0.0" }, "autoload": { "files": [ "h5p.classes.php", "h5p-development.class.php", "h5p-file-storage.interface.php", "h5p-default-storage.class.php", "h5p-event-base.class.php", "h5p-metadata.class.php" ] } } PK*\!h5plib/v127/joubel/core/embed.phpnu[ <?php print $content['title']; ?>
PK*\+ BN4N4(h5plib/v127/joubel/core/doc/spec_en.htmlnu[

Overview

H5P is a file format for content/applications made using modern, open web technologies (HTML5). The format enables easy installation and transfer of applications/content on different CMSes, LMSes and other platforms. An H5P can be uploaded and published on a platform in mostly the same way one would publish a Flash file today. H5P files may also be updated by simply uploading a new version of the file, the same way as one would using Flash.

H5P opens for extensive reuse of code and wide flexibility regarding what may be developed as an H5P.

The system uses package files containing all necessary files and libraries for the application to function. These files are based on open formats.

Overview of package files

Package files are normal zip files, with a naming convention of <filename>.h5p to distinguish from any random zip file. This zip file then requires a specific file structure as described below.

There will be a file in JSON format named h5p.json describing the contents of the package and how the system should interpret and use it. This file contains information about title, content type, usage, copyright, licensing, version, language etc. This is described in detail below.

There shall be a folder for each included H5P library used by the package. These generic libraries may be reused by other H5P packages. As an example, a multi-choice question task may be used as a standalone block, or be included in a larger H5P package generating a game with quizzes.

Package file structure

A package contains the following elements:

  1. A mandatory file in the root folder named h5p.json
  2. An optional image file named h5p.jpg. This is an icon or an image of the application, 512 × 512 pixels. This image may be used by the platform as a preview of the application, and could be included in OG meta tags for use with social media.
  3. One content folder, named content. This will contain the preset configuration for the application, as well as any required media files.
  4. One or more library directories named the same as the library's internal name.

h5p.json

The h5p.json file is a normal JSON text file containing a JSON object with the following predefined properties.

Mandatory properties:

  • title - Name of the package. Would typically be used as header for a page displaying the package.
  • language - Standard language code. Use 'en' for english, 'nb' for norwegian "bokmål". Neutral content use "und".
  • machineName - Machine readable name of the library. This is the name that will be used for the library folder in the package too.
  • preloadedDependencies - Libraries that must be loaded on init. Specified as a list of objects with machineName, majorVersion and minorVersion. One would normally list all dependencies here to allow the platform displaying the package to merge JS and CSS files before returning the page.
  • embedTypes - List of ways to embed the package in the web page. Currently "div" and "iframe" are supported.

Optional properties:

  • contentType - Textual description of the type of content.
  • description - Textual description of the package.
  • author - Name of author.
  • license - Code for the content license. Use the following Creative Commons codes: cc-by, cc-by-sa, cc-by-nd, cc-by-nc, cc-by-nc-sa, cc-by-nc-nd. In addition for public domain: pd, and closed license: cr. More may be added later.
  • dynamicDependencies - Libraries that may be loaded dynamically during execution.
  • width - Width of the package content in cases where the package is not dynamically resizable.
  • height - Height of the package content.
  • metaKeywords - Suggestion for keywords for the application, as a string. May be used for OG meta tags for social media.
  • metaDescription - Suggestion for application metaDescription. May be used for OG meta tags for social media.

Eksempel på h5p.json:

{
"title": "Biologi-spillet",
"contentType": "Game",
"utilization": "Lær om biologi",
"language": "nb",
"author": "Amendor AS",
"license": "cc-by-sa",
"preloadedDependencies": [
{
"machineName": "H5P.Boardgame",
"majorVersion": 1,
"minorVersion": 0
}, {
"machineName": "H5P.QuestionSet",
"majorVersion": 1,
"minorVersion": 0
}, {
"machineName": "H5P.MultiChoice",
"majorVersion": 1, "minorVersion": 0
}, {
"machineName": "EmbeddedJS",
"majorVersion": 1,
"minorVersion": 0
} ],
"embedTypes": ["div", "iframe"],
"w": 635,
"h": 500
}

The content folder

Contains all the content for the package and its libraries. There shall be no content inside the library folders. The content folder shall contain a file named content.json, containing the JSON object that will be passed to the initializer for the main package library.

Content required by libraries invoked from the main package library will get their contents passed from the main library. The JSON for this will be found within the main content.json for the package, and passed during initialization.

Library folders

A library folder contains all logic, stylesheets and graphics that will be common for all instances of a library. There shall be no content or interface text directly in these folders. All text displayed to the end user shall be passed as part of the library configuration. This make the libraries language independent.

The root of a library folder shall contain a file name library.json formatted similar to the package's hp5.json, but with a few differences. The library shall also have one or more images in the root folder, named library.jpg, library1.jpg etc. Image sizes 512px × 512px, and will be used in the H5P editor tool.

Libraries are not allowed to modify the document tree in ways that will have consequences for the web site or will be noticeable by the user without the library explicitly being initialized from the main package library or another invoked library.

The library shall always include a JavaScript object function named the same as the defined library machineName (defined in library.json and used as the library folder name). This object will be instantiated with the library options as parameter. The resulting object must contain a function attach(target) that will be called after instantiation to attach the library DOM to the main DOM inside target

Example

A library called H5P.multichoice would typically be instantiated and attached to the page like this:

var multichoice = new H5P.multichoice(contentFromJson, contentId);
multichoice.attach($multichoiceContainer);

library.json

Mandatory properties:

  • title - Human readable name of the library. May be used in the H5P editor and overviews of installed libraries.
  • majorVersion - Version major number. (The x in x.y.z). Positive integer.
  • minorVersion - Version minor number. (The y in x.y.z). Positive integer.
  • patchVersion - Version patch number. (The z in x.y.z). Positive integer. The system will automatically update to the latest patchVersion installed for all packages that use the library with the same major and minor version number. A new patch version must therefore not change any behaviour of the library, only fix errors.
  • machineName - Machine readable name for the library. Same as the folder name used.
  • preloadedJs - List of path to the javascript files required for the library. At least one file need to be present (the one defining the library object). Paths are relative to the library root folder.

Optional properties:

  • author - Author name as text.
  • license - Code describing the library license. Use the following creative commons codes: cc-by, cc-by-sa, cc-by-nd, cc-by-nc, cc-by-nc-sa, cc-by-nc-nd. In addition use pd for public domain, and cr for closed source
  • description - Textual description of the library.
  • preloadedDependencies - Libraries that need to be loaded for this library to work. Specified as a list of objects with machineName, majorVersion and minorVersion for the required libraries.
  • dynamicDependencies - Libraries that may be loaded dynamically during library execution. Specified as a list of objects like preloadedDependencies above.
  • preloadedCss - List of paths to CSS files to be loaded with the library. Paths are relative to the library root folder.
  • w - Width in pixels for libraries that use a fixed width. Mandatory if the library shall be embedded in an iframe (see embedTypes below).
  • h - Height in pixels for libraries that use a fixed height. Mandatory if the library shall be embedded in an iframe (see embedTypes below).
  • embedTypes - List of possible ways to embed the package in the page. Available values are div and iframe.

Eksempel på library.json:

{
"title": "Boardgame",
"description": "The user is presented with a board with several hotspots. By clicking a hotspot he invokes a mini-game.",
"majorVersion": 1,
"minorVersion": 0,
"patchVersion": 6,
"runnable": 1,
"machineName": "H5P.Boardgame",
"author": "Amendor AS",
"license": "cc-by-sa",
"preloadedDependencies": [
{
"machineName": "EmbeddedJS",
"majorVersion": 1,
"minorVersion": 0
}, {
"machineName": "H5P.MultiChoice",
"majorVersion": 1,
"minorVersion": 0
}, {
"machineName": "H5P.QuestionSet",
"majorVersion": 1,
"minorVersion": 0
} ],
"preloadedCss": [ {"path": "css/boardgame.css"} ],
"preloadedJs": [ {"path": "js/boardgame.js"} ],
"w": 635,
"h": 500 }

Allowed file types

Files that require server side execution or that cannot be regarded an open standard shall not be used. Allowed file types: js, json, png, jpg, gif, svg, css, mp3, wav (audio: PCM), m4a (audio: AAC), mp4 (video: H.264, audio: AAC/MP3), ogg (video: Theora, audio: Vorbis) and webm (video VP8, audio: Vorbis). Administrators of web sites implementing H5P may open for accepting further formats. HTML files shall not be used. HTML for each library shall be inserted from the library scripts to ease code reuse. (By avoiding content being defined in said HTML).

API functions

The following JavaScript functions are available through h5p:

  • H5P.getUserData(namespace, variable)
  • H5P.setUserData(namespace, variable, data)
  • H5P.getUserStart(namespace)
  • H5P.setUserStop(namespace)
  • H5P.deleteUserData(namespace, variable)
  • H5P.getGlobalData(namespace, variable)
  • H5P.setGlobalData(namespace, variable, data)
  • H5P.deleteGlobalData(namespace, variable)

I tillegg er følgende api funksjoner tilgjengelig via ndla:

  • H5P.setUserScore(contentId, score, maxScore)

Best practices

H5P is a very open standard. This is positive for flexibility. Most content may be produces as H5P. But this also allows for bad code, security weaknesses, code that may be difficult to reuse. Therefore the following best practices should be followed to get the most from H5P:

  • Think reusability when creating a library. H5P support dependencies between libraries, so the same small quiz-library may be used in various larger packages or libraries.
  • H5P supports library updates. This enables all content using a common library to be updated at once. This must be accounted for when writing new libraries. A library should be as general as possible. The content format should be thought out so there are no changes to the required content data when a library is updated. Note: Multiple versions of a library may exists at the same time, only patch level updates will be automatically installed.
  • An H5P should not interact directly with the containing web site. It shall only affect elements within its own generated DOM tree. Elements shall also only be injected within the target defined on initialization. This is to avoid dependencies to a specific platform or web page.
  • Prefix objects, global functions, etc with h5p to minimize the chance of namespace conflicts with the rest of the web page. Remember that there may also be multiple H5P objects inserted on a page, so plan ahead to avoid conflicts.
  • Content should be responsive.
  • Content should be WCAG 2 AA compliant
  • All generated HTML should validate.
  • All CSS should validate (some browser specific non-standard CSS may at times be required)
  • Best practices for JavaScript, HTML, etc. should of course also be followed when writing an H5P.
PK*\^T'h5plib/v127/joubel/core/h5p.classes.phpnu[ '/^.{1,255}$/', 'language' => '/^[-a-zA-Z]{1,10}$/', 'preloadedDependencies' => array( 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), 'mainLibrary' => '/^[$a-z_][0-9a-z_\.$]{1,254}$/i', 'embedTypes' => array('iframe', 'div'), ); private $h5pOptional = array( 'contentType' => '/^.{1,255}$/', 'dynamicDependencies' => array( 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), // deprecated 'author' => '/^.{1,255}$/', 'authors' => array( 'name' => '/^.{1,255}$/', 'role' => '/^\w+$/', ), 'source' => '/^(http[s]?:\/\/.+)$/', 'license' => '/^(CC BY|CC BY-SA|CC BY-ND|CC BY-NC|CC BY-NC-SA|CC BY-NC-ND|CC0 1\.0|GNU GPL|PD|ODC PDDL|CC PDM|U|C)$/', 'licenseVersion' => '/^(1\.0|2\.0|2\.5|3\.0|4\.0)$/', 'licenseExtras' => '/^.{1,5000}$/s', 'yearsFrom' => '/^([0-9]{1,4})$/', 'yearsTo' => '/^([0-9]{1,4})$/', 'changes' => array( 'date' => '/^[0-9]{2}-[0-9]{2}-[0-9]{2} [0-9]{1,2}:[0-9]{2}:[0-9]{2}$/', 'author' => '/^.{1,255}$/', 'log' => '/^.{1,5000}$/s' ), 'authorComments' => '/^.{1,5000}$/s', 'w' => '/^[0-9]{1,4}$/', 'h' => '/^[0-9]{1,4}$/', // deprecated 'metaKeywords' => '/^.{1,}$/', // deprecated 'metaDescription' => '/^.{1,}$/', ); // Schemas used to validate the library files private $libraryRequired = array( 'title' => '/^.{1,255}$/', 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', 'patchVersion' => '/^[0-9]{1,5}$/', 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'runnable' => '/^(0|1)$/', ); private $libraryOptional = array( 'author' => '/^.{1,255}$/', 'license' => '/^(cc-by|cc-by-sa|cc-by-nd|cc-by-nc|cc-by-nc-sa|cc-by-nc-nd|pd|cr|MIT|GPL1|GPL2|GPL3|MPL|MPL2)$/', 'description' => '/^.{1,}$/', 'metadataSettings' => array( 'disable' => '/^(0|1)$/', 'disableExtraTitleField' => '/^(0|1)$/' ), 'dynamicDependencies' => array( 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), 'preloadedDependencies' => array( 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), 'editorDependencies' => array( 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), 'preloadedJs' => array( 'path' => '/^((\\\|\/)?[a-z_\-\s0-9\.]+)+\.js$/i', ), 'preloadedCss' => array( 'path' => '/^((\\\|\/)?[a-z_\-\s0-9\.]+)+\.css$/i', ), 'dropLibraryCss' => array( 'machineName' => '/^[\w0-9\-\.]{1,255}$/i', ), 'w' => '/^[0-9]{1,4}$/', 'h' => '/^[0-9]{1,4}$/', 'embedTypes' => array('iframe', 'div'), 'fullscreen' => '/^(0|1)$/', 'coreApi' => array( 'majorVersion' => '/^[0-9]{1,5}$/', 'minorVersion' => '/^[0-9]{1,5}$/', ), ); /** * Constructor for the H5PValidator * * @param H5PFrameworkInterface $H5PFramework * The frameworks implementation of the H5PFrameworkInterface * @param H5PCore $H5PCore */ public function __construct($H5PFramework, $H5PCore) { $this->h5pF = $H5PFramework; $this->h5pC = $H5PCore; $this->h5pCV = new H5PContentValidator($this->h5pF, $this->h5pC); } /** * Validates a .h5p file * * @param bool $skipContent * @param bool $upgradeOnly * @return bool TRUE if the .h5p file is valid * TRUE if the .h5p file is valid */ public function isValidPackage($skipContent = FALSE, $upgradeOnly = FALSE) { // Create a temporary dir to extract package in. $tmpDir = $this->h5pF->getUploadedH5pFolderPath(); $tmpPath = $this->h5pF->getUploadedH5pPath(); // Check dependencies, make sure Zip is present if (!class_exists('ZipArchive')) { $this->h5pF->setErrorMessage($this->h5pF->t('Your PHP version does not support ZipArchive.'), 'zip-archive-unsupported'); unlink($tmpPath); return FALSE; } if (!extension_loaded('mbstring')) { $this->h5pF->setErrorMessage($this->h5pF->t('The mbstring PHP extension is not loaded. H5P need this to function properly'), 'mbstring-unsupported'); unlink($tmpPath); return FALSE; } // Only allow files with the .h5p extension: if (strtolower(substr($tmpPath, -3)) !== 'h5p') { $this->h5pF->setErrorMessage($this->h5pF->t('The file you uploaded is not a valid HTML5 Package (It does not have the .h5p file extension)'), 'missing-h5p-extension'); unlink($tmpPath); return FALSE; } // Extract and then remove the package file. $zip = new ZipArchive; // Open the package if ($zip->open($tmpPath) !== TRUE) { $this->h5pF->setErrorMessage($this->h5pF->t('The file you uploaded is not a valid HTML5 Package (We are unable to unzip it)'), 'unable-to-unzip'); unlink($tmpPath); return FALSE; } if ($this->h5pC->disableFileCheck !== TRUE) { list($contentWhitelist, $contentRegExp) = $this->getWhitelistRegExp(FALSE); list($libraryWhitelist, $libraryRegExp) = $this->getWhitelistRegExp(TRUE); } $canInstall = $this->h5pC->mayUpdateLibraries(); $valid = TRUE; $libraries = array(); $totalSize = 0; $mainH5pExists = FALSE; $contentExists = FALSE; // Check for valid file types, JSON files + file sizes before continuing to unpack. for ($i = 0; $i < $zip->numFiles; $i++) { $fileStat = $zip->statIndex($i); if (!empty($this->h5pC->maxFileSize) && $fileStat['size'] > $this->h5pC->maxFileSize) { // Error file is too large $this->h5pF->setErrorMessage($this->h5pF->t('One of the files inside the package exceeds the maximum file size allowed. (%file %used > %max)', array('%file' => $fileStat['name'], '%used' => ($fileStat['size'] / 1048576) . ' MB', '%max' => ($this->h5pC->maxFileSize / 1048576) . ' MB')), 'file-size-too-large'); $valid = FALSE; } $totalSize += $fileStat['size']; $fileName = mb_strtolower($fileStat['name']); if (preg_match('/(^[\._]|\/[\._]|\\\[\._])/', $fileName) !== 0) { continue; // Skip any file or folder starting with a . or _ } elseif ($fileName === 'h5p.json') { $mainH5pExists = TRUE; } elseif ($fileName === 'content/content.json') { $contentExists = TRUE; } elseif (substr($fileName, 0, 8) === 'content/') { // This is a content file, check that the file type is allowed if ($skipContent === FALSE && $this->h5pC->disableFileCheck !== TRUE && !preg_match($contentRegExp, $fileName)) { $this->h5pF->setErrorMessage($this->h5pF->t('File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.', array('%filename' => $fileStat['name'], '%files-allowed' => $contentWhitelist)), 'not-in-whitelist'); $valid = FALSE; } } elseif ($canInstall && strpos($fileName, '/') !== FALSE) { // This is a library file, check that the file type is allowed if ($this->h5pC->disableFileCheck !== TRUE && !preg_match($libraryRegExp, $fileName)) { $this->h5pF->setErrorMessage($this->h5pF->t('File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.', array('%filename' => $fileStat['name'], '%files-allowed' => $libraryWhitelist)), 'not-in-whitelist'); $valid = FALSE; } // Further library validation happens after the files are extracted } } if (!empty($this->h5pC->maxTotalSize) && $totalSize > $this->h5pC->maxTotalSize) { // Error total size of the zip is too large $this->h5pF->setErrorMessage($this->h5pF->t('The total size of the unpacked files exceeds the maximum size allowed. (%used > %max)', array('%used' => ($totalSize / 1048576) . ' MB', '%max' => ($this->h5pC->maxTotalSize / 1048576) . ' MB')), 'total-size-too-large'); $valid = FALSE; } if ($skipContent === FALSE) { // Not skipping content, require two valid JSON files from the package if (!$contentExists) { $this->h5pF->setErrorMessage($this->h5pF->t('A valid content folder is missing'), 'invalid-content-folder'); $valid = FALSE; } else { $contentJsonData = $this->getJson($tmpPath, $zip, 'content/content.json'); // TODO: Is this case-senstivie? if ($contentJsonData === NULL) { return FALSE; // Breaking error when reading from the archive. } elseif ($contentJsonData === FALSE) { $valid = FALSE; // Validation error when parsing JSON } } if (!$mainH5pExists) { $this->h5pF->setErrorMessage($this->h5pF->t('A valid main h5p.json file is missing'), 'invalid-h5p-json-file'); $valid = FALSE; } else { $mainH5pData = $this->getJson($tmpPath, $zip, 'h5p.json', TRUE); if ($mainH5pData === NULL) { return FALSE; // Breaking error when reading from the archive. } elseif ($mainH5pData === FALSE) { $valid = FALSE; // Validation error when parsing JSON } elseif (!$this->isValidH5pData($mainH5pData, 'h5p.json', $this->h5pRequired, $this->h5pOptional)) { $this->h5pF->setErrorMessage($this->h5pF->t('The main h5p.json file is not valid'), 'invalid-h5p-json-file'); // Is this message a bit redundant? $valid = FALSE; } } } if (!$valid) { // If something has failed during the initial checks of the package // we will not unpack it or continue validation. $zip->close(); unlink($tmpPath); return FALSE; } // Extract the files from the package for ($i = 0; $i < $zip->numFiles; $i++) { $fileName = $zip->statIndex($i)['name']; if (preg_match('/(^[\._]|\/[\._]|\\\[\._])/', $fileName) !== 0) { continue; // Skip any file or folder starting with a . or _ } $isContentFile = (substr($fileName, 0, 8) === 'content/'); $isFolder = (strpos($fileName, '/') !== FALSE); if ($skipContent !== FALSE && $isContentFile) { continue; // Skipping any content files } if (!($isContentFile || ($canInstall && $isFolder))) { continue; // Not something we want to unpack } // Get file stream $fileStream = $zip->getStream($fileName); if (!$fileStream) { // This is a breaking error, there's no need to continue. (the rest of the files will fail as well) $this->h5pF->setErrorMessage($this->h5pF->t('Unable to read file from the package: %fileName', array('%fileName' => $fileName)), 'unable-to-read-package-file'); $zip->close(); unlink($path); H5PCore::deleteFileTree($tmpDir); return FALSE; } // Use file interface to allow overrides $this->h5pC->fs->saveFileFromZip($tmpDir, $fileName, $fileStream); // Clean up if (is_resource($fileStream)) { fclose($fileStream); } } // We're done with the zip file, clean up the stuff $zip->close(); unlink($tmpPath); if ($canInstall) { // Process and validate libraries using the unpacked library folders $files = scandir($tmpDir); foreach ($files as $file) { $filePath = $tmpDir . '/' . $file; if ($file === '.' || $file === '..' || $file === 'content' || !is_dir($filePath)) { continue; // Skip } $libraryH5PData = $this->getLibraryData($file, $filePath, $tmpDir); if ($libraryH5PData === FALSE) { $valid = FALSE; continue; // Failed, but continue validating the rest of the libraries } // Library's directory name must be: // - // - or - // - -. // where machineName, majorVersion and minorVersion is read from library.json if ($libraryH5PData['machineName'] !== $file && H5PCore::libraryToFolderName($libraryH5PData) !== $file) { $this->h5pF->setErrorMessage($this->h5pF->t('Library directory name must match machineName or machineName-majorVersion.minorVersion (from library.json). (Directory: %directoryName , machineName: %machineName, majorVersion: %majorVersion, minorVersion: %minorVersion)', array( '%directoryName' => $file, '%machineName' => $libraryH5PData['machineName'], '%majorVersion' => $libraryH5PData['majorVersion'], '%minorVersion' => $libraryH5PData['minorVersion'])), 'library-directory-name-mismatch'); $valid = FALSE; continue; // Failed, but continue validating the rest of the libraries } $libraryH5PData['uploadDirectory'] = $filePath; $libraries[H5PCore::libraryToString($libraryH5PData)] = $libraryH5PData; } } if ($valid) { if ($upgradeOnly) { // When upgrading, we only add the already installed libraries, and // the new dependent libraries $upgrades = array(); foreach ($libraries as $libString => &$library) { // Is this library already installed? if ($this->h5pF->getLibraryId($library['machineName']) !== FALSE) { $upgrades[$libString] = $library; } } while ($missingLibraries = $this->getMissingLibraries($upgrades)) { foreach ($missingLibraries as $libString => $missing) { $library = $libraries[$libString]; if ($library) { $upgrades[$libString] = $library; } } } $libraries = $upgrades; } $this->h5pC->librariesJsonData = $libraries; if ($skipContent === FALSE) { $this->h5pC->mainJsonData = $mainH5pData; $this->h5pC->contentJsonData = $contentJsonData; $libraries['mainH5pData'] = $mainH5pData; // Check for the dependencies in h5p.json as well as in the libraries } $missingLibraries = $this->getMissingLibraries($libraries); foreach ($missingLibraries as $libString => $missing) { if ($this->h5pC->getLibraryId($missing, $libString)) { unset($missingLibraries[$libString]); } } if (!empty($missingLibraries)) { // We still have missing libraries, check if our main library has an upgrade (BUT only if we has content) $mainDependency = NULL; if (!$skipContent && !empty($mainH5pData)) { foreach ($mainH5pData['preloadedDependencies'] as $dep) { if ($dep['machineName'] === $mainH5pData['mainLibrary']) { $mainDependency = $dep; } } } if ($skipContent || !$mainDependency || !$this->h5pF->libraryHasUpgrade(array( 'machineName' => $mainDependency['machineName'], 'majorVersion' => $mainDependency['majorVersion'], 'minorVersion' => $mainDependency['minorVersion'] ))) { foreach ($missingLibraries as $libString => $library) { if (!empty($mainDependency) && $library['machineName'] === $mainDependency['machineName']) { $this->h5pF->setErrorMessage($this->h5pF->t('Missing main library @library', array('@library' => $libString )), 'missing-main-library'); } else { $this->h5pF->setErrorMessage($this->h5pF->t('Missing required library @library', array('@library' => $libString)), 'missing-required-library'); } $valid = FALSE; } if (!$this->h5pC->mayUpdateLibraries()) { $this->h5pF->setInfoMessage($this->h5pF->t("Note that the libraries may exist in the file you uploaded, but you're not allowed to upload new libraries. Contact the site administrator about this.")); $valid = FALSE; } } } } if (!$valid) { H5PCore::deleteFileTree($tmpDir); } return $valid; } /** * Help read JSON from the archive * * @param string $path * @param ZipArchive $zip * @param string $file * @return mixed JSON content if valid, FALSE for invalid, NULL for breaking error. */ private function getJson($path, $zip, $file, $assoc = FALSE) { // Get stream $stream = $zip->getStream($file); if (!$stream) { // Breaking error, no need to continue validating. $this->h5pF->setErrorMessage($this->h5pF->t('Unable to read file from the package: %fileName', array('%fileName' => $file)), 'unable-to-read-package-file'); $zip->close(); unlink($path); return NULL; } // Read data $contents = ''; while (!feof($stream)) { $contents .= fread($stream, 2); } // Decode the data $json = json_decode($contents, $assoc); if ($json === NULL) { // JSON cannot be decoded or the recursion limit has been reached. $this->h5pF->setErrorMessage($this->h5pF->t('Unable to parse JSON from the package: %fileName', array('%fileName' => $file)), 'unable-to-parse-package'); return FALSE; } // All OK return $json; } /** * Help retrieve file type regexp whitelist from plugin. * * @param bool $isLibrary Separate list with more allowed file types * @return string RegExp */ private function getWhitelistRegExp($isLibrary) { $whitelist = $this->h5pF->getWhitelist($isLibrary, H5PCore::$defaultContentWhitelist, H5PCore::$defaultLibraryWhitelistExtras); return array($whitelist, '/\.(' . preg_replace('/ +/i', '|', preg_quote($whitelist)) . ')$/i'); } /** * Validates a H5P library * * @param string $file * Name of the library folder * @param string $filePath * Path to the library folder * @param string $tmpDir * Path to the temporary upload directory * @return boolean|array * H5P data from library.json and semantics if the library is valid * FALSE if the library isn't valid */ public function getLibraryData($file, $filePath, $tmpDir) { if (preg_match('/^[\w0-9\-\.]{1,255}$/i', $file) === 0) { $this->h5pF->setErrorMessage($this->h5pF->t('Invalid library name: %name', array('%name' => $file)), 'invalid-library-name'); return FALSE; } $h5pData = $this->getJsonData($filePath . '/' . 'library.json'); if ($h5pData === FALSE) { $this->h5pF->setErrorMessage($this->h5pF->t('Could not find library.json file with valid json format for library %name', array('%name' => $file)), 'invalid-library-json-file'); return FALSE; } // validate json if a semantics file is provided $semanticsPath = $filePath . '/' . 'semantics.json'; if (file_exists($semanticsPath)) { $semantics = $this->getJsonData($semanticsPath, TRUE); if ($semantics === FALSE) { $this->h5pF->setErrorMessage($this->h5pF->t('Invalid semantics.json file has been included in the library %name', array('%name' => $file)), 'invalid-semantics-json-file'); return FALSE; } else { $h5pData['semantics'] = $semantics; } } // validate language folder if it exists $languagePath = $filePath . '/' . 'language'; if (is_dir($languagePath)) { $languageFiles = scandir($languagePath); foreach ($languageFiles as $languageFile) { if (in_array($languageFile, array('.', '..'))) { continue; } if (preg_match('/^(-?[a-z]+){1,7}\.json$/i', $languageFile) === 0) { $this->h5pF->setErrorMessage($this->h5pF->t('Invalid language file %file in library %library', array('%file' => $languageFile, '%library' => $file)), 'invalid-language-file'); return FALSE; } $languageJson = $this->getJsonData($languagePath . '/' . $languageFile, TRUE); if ($languageJson === FALSE) { $this->h5pF->setErrorMessage($this->h5pF->t('Invalid language file %languageFile has been included in the library %name', array('%languageFile' => $languageFile, '%name' => $file)), 'invalid-language-file'); return FALSE; } $parts = explode('.', $languageFile); // $parts[0] is the language code $h5pData['language'][$parts[0]] = $languageJson; } } // Check for icon: $h5pData['hasIcon'] = file_exists($filePath . '/' . 'icon.svg'); $validLibrary = $this->isValidH5pData($h5pData, $file, $this->libraryRequired, $this->libraryOptional); //$validLibrary = $this->h5pCV->validateContentFiles($filePath, TRUE) && $validLibrary; if (isset($h5pData['preloadedJs'])) { $validLibrary = $this->isExistingFiles($h5pData['preloadedJs'], $tmpDir, $file) && $validLibrary; } if (isset($h5pData['preloadedCss'])) { $validLibrary = $this->isExistingFiles($h5pData['preloadedCss'], $tmpDir, $file) && $validLibrary; } if ($validLibrary) { return $h5pData; } else { return FALSE; } } /** * Use the dependency declarations to find any missing libraries * * @param array $libraries * A multidimensional array of libraries keyed with machineName first and majorVersion second * @return array * A list of libraries that are missing keyed with machineName and holds objects with * machineName, majorVersion and minorVersion properties */ private function getMissingLibraries($libraries) { $missing = array(); foreach ($libraries as $library) { if (isset($library['preloadedDependencies'])) { $missing = array_merge($missing, $this->getMissingDependencies($library['preloadedDependencies'], $libraries)); } if (isset($library['dynamicDependencies'])) { $missing = array_merge($missing, $this->getMissingDependencies($library['dynamicDependencies'], $libraries)); } if (isset($library['editorDependencies'])) { $missing = array_merge($missing, $this->getMissingDependencies($library['editorDependencies'], $libraries)); } } return $missing; } /** * Helper function for getMissingLibraries, searches for dependency required libraries in * the provided list of libraries * * @param array $dependencies * A list of objects with machineName, majorVersion and minorVersion properties * @param array $libraries * An array of libraries keyed with machineName * @return * A list of libraries that are missing keyed with machineName and holds objects with * machineName, majorVersion and minorVersion properties */ private function getMissingDependencies($dependencies, $libraries) { $missing = array(); foreach ($dependencies as $dependency) { $libString = H5PCore::libraryToString($dependency); if (!isset($libraries[$libString])) { $missing[$libString] = $dependency; } } return $missing; } /** * Figure out if the provided file paths exists * * Triggers error messages if files doesn't exist * * @param array $files * List of file paths relative to $tmpDir * @param string $tmpDir * Path to the directory where the $files are stored. * @param string $library * Name of the library we are processing * @return boolean * TRUE if all the files excists */ private function isExistingFiles($files, $tmpDir, $library) { foreach ($files as $file) { $path = str_replace(array('/', '\\'), '/', $file['path']); if (!file_exists($tmpDir . '/' . $library . '/' . $path)) { $this->h5pF->setErrorMessage($this->h5pF->t('The file "%file" is missing from library: "%name"', array('%file' => $path, '%name' => $library)), 'library-missing-file'); return FALSE; } } return TRUE; } /** * Validates h5p.json and library.json data * * Error messages are triggered if the data isn't valid * * @param array $h5pData * h5p data * @param string $library_name * Name of the library we are processing * @param array $required * Validation pattern for required properties * @param array $optional * Validation pattern for optional properties * @return boolean * TRUE if the $h5pData is valid */ private function isValidH5pData($h5pData, $library_name, $required, $optional) { $valid = $this->isValidRequiredH5pData($h5pData, $required, $library_name); $valid = $this->isValidOptionalH5pData($h5pData, $optional, $library_name) && $valid; // Check the library's required API version of Core. // If no requirement is set this implicitly means 1.0. if (isset($h5pData['coreApi']) && !empty($h5pData['coreApi'])) { if (($h5pData['coreApi']['majorVersion'] > H5PCore::$coreApi['majorVersion']) || ( ($h5pData['coreApi']['majorVersion'] == H5PCore::$coreApi['majorVersion']) && ($h5pData['coreApi']['minorVersion'] > H5PCore::$coreApi['minorVersion']) )) { $this->h5pF->setErrorMessage( $this->h5pF->t('The system was unable to install the %component component from the package, it requires a newer version of the H5P plugin. This site is currently running version %current, whereas the required version is %required or higher. You should consider upgrading and then try again.', array( '%component' => (isset($h5pData['title']) ? $h5pData['title'] : $library_name), '%current' => H5PCore::$coreApi['majorVersion'] . '.' . H5PCore::$coreApi['minorVersion'], '%required' => $h5pData['coreApi']['majorVersion'] . '.' . $h5pData['coreApi']['minorVersion'] ) ), 'api-version-unsupported' ); $valid = false; } } return $valid; } /** * Helper function for isValidH5pData * * Validates the optional part of the h5pData * * Triggers error messages * * @param array $h5pData * h5p data * @param array $requirements * Validation pattern * @param string $library_name * Name of the library we are processing * @return boolean * TRUE if the optional part of the $h5pData is valid */ private function isValidOptionalH5pData($h5pData, $requirements, $library_name) { $valid = TRUE; foreach ($h5pData as $key => $value) { if (isset($requirements[$key])) { $valid = $this->isValidRequirement($value, $requirements[$key], $library_name, $key) && $valid; } // Else: ignore, a package can have parameters that this library doesn't care about, but that library // specific implementations does care about... } return $valid; } /** * Validate a requirement given as regexp or an array of requirements * * @param mixed $h5pData * The data to be validated * @param mixed $requirement * The requirement the data is to be validated against, regexp or array of requirements * @param string $library_name * Name of the library we are validating(used in error messages) * @param string $property_name * Name of the property we are validating(used in error messages) * @return boolean * TRUE if valid, FALSE if invalid */ private function isValidRequirement($h5pData, $requirement, $library_name, $property_name) { $valid = TRUE; if (is_string($requirement)) { if ($requirement == 'boolean') { if (!is_bool($h5pData)) { $this->h5pF->setErrorMessage($this->h5pF->t("Invalid data provided for %property in %library. Boolean expected.", array('%property' => $property_name, '%library' => $library_name))); $valid = FALSE; } } else { // The requirement is a regexp, match it against the data if (is_string($h5pData) || is_int($h5pData)) { if (preg_match($requirement, $h5pData) === 0) { $this->h5pF->setErrorMessage($this->h5pF->t("Invalid data provided for %property in %library", array('%property' => $property_name, '%library' => $library_name))); $valid = FALSE; } } else { $this->h5pF->setErrorMessage($this->h5pF->t("Invalid data provided for %property in %library", array('%property' => $property_name, '%library' => $library_name))); $valid = FALSE; } } } elseif (is_array($requirement)) { // We have sub requirements if (is_array($h5pData)) { if (is_array(current($h5pData))) { foreach ($h5pData as $sub_h5pData) { $valid = $this->isValidRequiredH5pData($sub_h5pData, $requirement, $library_name) && $valid; } } else { $valid = $this->isValidRequiredH5pData($h5pData, $requirement, $library_name) && $valid; } } else { $this->h5pF->setErrorMessage($this->h5pF->t("Invalid data provided for %property in %library", array('%property' => $property_name, '%library' => $library_name))); $valid = FALSE; } } else { $this->h5pF->setErrorMessage($this->h5pF->t("Can't read the property %property in %library", array('%property' => $property_name, '%library' => $library_name))); $valid = FALSE; } return $valid; } /** * Validates the required h5p data in libraray.json and h5p.json * * @param mixed $h5pData * Data to be validated * @param array $requirements * Array with regexp to validate the data against * @param string $library_name * Name of the library we are validating (used in error messages) * @return boolean * TRUE if all the required data exists and is valid, FALSE otherwise */ private function isValidRequiredH5pData($h5pData, $requirements, $library_name) { $valid = TRUE; foreach ($requirements as $required => $requirement) { if (is_int($required)) { // We have an array of allowed options return $this->isValidH5pDataOptions($h5pData, $requirements, $library_name); } if (isset($h5pData[$required])) { $valid = $this->isValidRequirement($h5pData[$required], $requirement, $library_name, $required) && $valid; } else { $this->h5pF->setErrorMessage($this->h5pF->t('The required property %property is missing from %library', array('%property' => $required, '%library' => $library_name)), 'missing-required-property'); $valid = FALSE; } } return $valid; } /** * Validates h5p data against a set of allowed values(options) * * @param array $selected * The option(s) that has been specified * @param array $allowed * The allowed options * @param string $library_name * Name of the library we are validating (used in error messages) * @return boolean * TRUE if the specified data is valid, FALSE otherwise */ private function isValidH5pDataOptions($selected, $allowed, $library_name) { $valid = TRUE; foreach ($selected as $value) { if (!in_array($value, $allowed)) { $this->h5pF->setErrorMessage($this->h5pF->t('Illegal option %option in %library', array('%option' => $value, '%library' => $library_name)), 'illegal-option-in-library'); $valid = FALSE; } } return $valid; } /** * Fetch json data from file * * @param string $filePath * Path to the file holding the json string * @param boolean $return_as_string * If true the json data will be decoded in order to validate it, but will be * returned as string * @return mixed * FALSE if the file can't be read or the contents can't be decoded * string if the $return as string parameter is set * array otherwise */ private function getJsonData($filePath, $return_as_string = FALSE) { $json = file_get_contents($filePath); if ($json === FALSE) { return FALSE; // Cannot read from file. } $jsonData = json_decode($json, TRUE); if ($jsonData === NULL) { return FALSE; // JSON cannot be decoded or the recursion limit has been reached. } return $return_as_string ? $json : $jsonData; } /** * Helper function that copies an array * * @param array $array * The array to be copied * @return array * Copy of $array. All objects are cloned */ private function arrayCopy(array $array) { $result = array(); foreach ($array as $key => $val) { if (is_array($val)) { $result[$key] = self::arrayCopy($val); } elseif (is_object($val)) { $result[$key] = clone $val; } else { $result[$key] = $val; } } return $result; } } /** * This class is used for saving H5P files */ class H5PStorage { public $h5pF; public $h5pC; public $contentId = NULL; // Quick fix so WP can get ID of new content. /** * Constructor for the H5PStorage * * @param H5PFrameworkInterface|object $H5PFramework * The frameworks implementation of the H5PFrameworkInterface * @param H5PCore $H5PCore */ public function __construct(H5PFrameworkInterface $H5PFramework, H5PCore $H5PCore) { $this->h5pF = $H5PFramework; $this->h5pC = $H5PCore; } /** * Saves a H5P file * * @param null $content * @param int $contentMainId * The main id for the content we are saving. This is used if the framework * we're integrating with uses content id's and version id's * @param bool $skipContent * @param array $options * @return bool TRUE if one or more libraries were updated * TRUE if one or more libraries were updated * FALSE otherwise */ public function savePackage($content = NULL, $contentMainId = NULL, $skipContent = FALSE, $options = array()) { if ($this->h5pC->mayUpdateLibraries()) { // Save the libraries we processed during validation $this->saveLibraries(); } if (!$skipContent) { $basePath = $this->h5pF->getUploadedH5pFolderPath(); $current_path = $basePath . '/' . 'content'; // Save content if ($content === NULL) { $content = array(); } if (!is_array($content)) { $content = array('id' => $content); } // Find main library version foreach ($this->h5pC->mainJsonData['preloadedDependencies'] as $dep) { if ($dep['machineName'] === $this->h5pC->mainJsonData['mainLibrary']) { $dep['libraryId'] = $this->h5pC->getLibraryId($dep); $content['library'] = $dep; break; } } $content['params'] = file_get_contents($current_path . '/' . 'content.json'); if (isset($options['disable'])) { $content['disable'] = $options['disable']; } $content['id'] = $this->h5pC->saveContent($content, $contentMainId); $this->contentId = $content['id']; try { // Save content folder contents $this->h5pC->fs->saveContent($current_path, $content); } catch (Exception $e) { $this->h5pF->setErrorMessage($e->getMessage(), 'save-content-failed'); } // Remove temp content folder H5PCore::deleteFileTree($basePath); } } /** * Helps savePackage. * * @return int Number of libraries saved */ private function saveLibraries() { // Keep track of the number of libraries that have been saved $newOnes = 0; $oldOnes = 0; // Go through libraries that came with this package foreach ($this->h5pC->librariesJsonData as $libString => &$library) { // Find local library with same major + minor $existingLibrary = $this->h5pC->loadLibrary($library['machineName'], $library['majorVersion'], $library['minorVersion']); // Assume new library $new = TRUE; if (isset($existingLibrary['libraryId'])) { $new = false; // We have the library installed already (with the same major + minor) $library['libraryId'] = $existingLibrary['libraryId']; // Is this a newer patchVersion? $newerPatchVersion = $existingLibrary['patchVersion'] < $library['patchVersion']; if (!$newerPatchVersion) { $library['saveDependencies'] = FALSE; // This is an older version, no need to save. continue; } } // Indicate that the dependencies of this library should be saved. $library['saveDependencies'] = TRUE; // Convert metadataSettings values to boolean & json_encode it before saving $library['metadataSettings'] = isset($library['metadataSettings']) ? H5PMetadata::boolifyAndEncodeSettings($library['metadataSettings']) : NULL; // MOODLE PATCH: The library needs to be saved in database first before creating the files, because the libraryid is used // as itemid for the files. // Update our DB $this->h5pF->saveLibraryData($library, $new); // Save library folder $this->h5pC->fs->saveLibrary($library); // Remove cached assets that uses this library if ($this->h5pC->aggregateAssets && isset($library['libraryId'])) { $removedKeys = $this->h5pF->deleteCachedAssets($library['libraryId']); $this->h5pC->fs->deleteCachedAssets($removedKeys); } // Remove tmp folder H5PCore::deleteFileTree($library['uploadDirectory']); if ($existingLibrary) { $this->h5pC->fs->deleteLibrary($existingLibrary); } if ($new) { $newOnes++; } else { $oldOnes++; } } // Go through the libraries again to save dependencies. $library_ids = array(); foreach ($this->h5pC->librariesJsonData as &$library) { if (!$library['saveDependencies']) { continue; } // TODO: Should the table be locked for this operation? // Remove any old dependencies $this->h5pF->deleteLibraryDependencies($library['libraryId']); // Insert the different new ones if (isset($library['preloadedDependencies'])) { $this->h5pF->saveLibraryDependencies($library['libraryId'], $library['preloadedDependencies'], 'preloaded'); } if (isset($library['dynamicDependencies'])) { $this->h5pF->saveLibraryDependencies($library['libraryId'], $library['dynamicDependencies'], 'dynamic'); } if (isset($library['editorDependencies'])) { $this->h5pF->saveLibraryDependencies($library['libraryId'], $library['editorDependencies'], 'editor'); } $library_ids[] = $library['libraryId']; } // Make sure libraries dependencies, parameter filtering and export files gets regenerated for all content who uses these libraries. if (!empty($library_ids)) { $this->h5pF->clearFilteredParameters($library_ids); } // Tell the user what we've done. if ($newOnes && $oldOnes) { if ($newOnes === 1) { if ($oldOnes === 1) { // Singular Singular $message = $this->h5pF->t('Added %new new H5P library and updated %old old one.', array('%new' => $newOnes, '%old' => $oldOnes)); } else { // Singular Plural $message = $this->h5pF->t('Added %new new H5P library and updated %old old ones.', array('%new' => $newOnes, '%old' => $oldOnes)); } } else { // Plural if ($oldOnes === 1) { // Plural Singular $message = $this->h5pF->t('Added %new new H5P libraries and updated %old old one.', array('%new' => $newOnes, '%old' => $oldOnes)); } else { // Plural Plural $message = $this->h5pF->t('Added %new new H5P libraries and updated %old old ones.', array('%new' => $newOnes, '%old' => $oldOnes)); } } } elseif ($newOnes) { if ($newOnes === 1) { // Singular $message = $this->h5pF->t('Added %new new H5P library.', array('%new' => $newOnes)); } else { // Plural $message = $this->h5pF->t('Added %new new H5P libraries.', array('%new' => $newOnes)); } } elseif ($oldOnes) { if ($oldOnes === 1) { // Singular $message = $this->h5pF->t('Updated %old H5P library.', array('%old' => $oldOnes)); } else { // Plural $message = $this->h5pF->t('Updated %old H5P libraries.', array('%old' => $oldOnes)); } } if (isset($message)) { $this->h5pF->setInfoMessage($message); } } /** * Delete an H5P package * * @param $content */ public function deletePackage($content) { $this->h5pC->fs->deleteContent($content); $this->h5pC->fs->deleteExport(($content['slug'] ? $content['slug'] . '-' : '') . $content['id'] . '.h5p'); $this->h5pF->deleteContentData($content['id']); } /** * Copy/clone an H5P package * * May for instance be used if the content is being revisioned without * uploading a new H5P package * * @param int $contentId * The new content id * @param int $copyFromId * The content id of the content that should be cloned * @param int $contentMainId * The main id of the new content (used in frameworks that support revisioning) */ public function copyPackage($contentId, $copyFromId, $contentMainId = NULL) { $this->h5pC->fs->cloneContent($copyFromId, $contentId); $this->h5pF->copyLibraryUsage($contentId, $copyFromId, $contentMainId); } } /** * This class is used for exporting zips */ Class H5PExport { public $h5pF; public $h5pC; /** * Constructor for the H5PExport * * @param H5PFrameworkInterface|object $H5PFramework * The frameworks implementation of the H5PFrameworkInterface * @param H5PCore $H5PCore * Reference to an instance of H5PCore */ public function __construct(H5PFrameworkInterface $H5PFramework, H5PCore $H5PCore) { $this->h5pF = $H5PFramework; $this->h5pC = $H5PCore; } /** * Reverts the replace pattern used by the text editor * * @param string $value * @return string */ private static function revertH5PEditorTextEscape($value) { return str_replace('<', '<', str_replace('>', '>', str_replace(''', "'", str_replace('"', '"', $value)))); } /** * Return path to h5p package. * * Creates package if not already created * * @param array $content * @return string */ public function createExportFile($content) { // Get path to temporary folder, where export will be contained $tmpPath = $this->h5pC->fs->getTmpPath(); mkdir($tmpPath, 0777, true); try { // Create content folder and populate with files $this->h5pC->fs->exportContent($content['id'], "{$tmpPath}/content"); } catch (Exception $e) { $this->h5pF->setErrorMessage($this->h5pF->t($e->getMessage()), 'failed-creating-export-file'); H5PCore::deleteFileTree($tmpPath); return FALSE; } // Update content.json with content from database file_put_contents("{$tmpPath}/content/content.json", $content['filtered']); // Make embedType into an array $embedTypes = explode(', ', $content['embedType']); // Build h5p.json, the en-/de-coding will ensure proper escaping $h5pJson = array ( 'title' => self::revertH5PEditorTextEscape($content['title']), 'language' => (isset($content['language']) && strlen(trim($content['language'])) !== 0) ? $content['language'] : 'und', 'mainLibrary' => $content['library']['name'], 'embedTypes' => $embedTypes ); foreach(array('authors', 'source', 'license', 'licenseVersion', 'licenseExtras' ,'yearFrom', 'yearTo', 'changes', 'authorComments', 'defaultLanguage') as $field) { if (isset($content['metadata'][$field]) && $content['metadata'][$field] !== '') { if (($field !== 'authors' && $field !== 'changes') || (!empty($content['metadata'][$field]))) { $h5pJson[$field] = json_decode(json_encode($content['metadata'][$field], TRUE)); } } } // Remove all values that are not set foreach ($h5pJson as $key => $value) { if (!isset($value)) { unset($h5pJson[$key]); } } // Add dependencies to h5p foreach ($content['dependencies'] as $dependency) { $library = $dependency['library']; try { $exportFolder = NULL; // Determine path of export library if (isset($this->h5pC) && isset($this->h5pC->h5pD)) { // Tries to find library in development folder $isDevLibrary = $this->h5pC->h5pD->getLibrary( $library['machineName'], $library['majorVersion'], $library['minorVersion'] ); if ($isDevLibrary !== NULL && isset($library['path'])) { $exportFolder = "/" . $library['path']; } } // Export required libraries $this->h5pC->fs->exportLibrary($library, $tmpPath, $exportFolder); } catch (Exception $e) { $this->h5pF->setErrorMessage($this->h5pF->t($e->getMessage()), 'failed-creating-export-file'); H5PCore::deleteFileTree($tmpPath); return FALSE; } // Do not add editor dependencies to h5p json. if ($dependency['type'] === 'editor') { continue; } // Add to h5p.json dependencies $h5pJson[$dependency['type'] . 'Dependencies'][] = array( 'machineName' => $library['machineName'], 'majorVersion' => $library['majorVersion'], 'minorVersion' => $library['minorVersion'] ); } // Save h5p.json $results = print_r(json_encode($h5pJson), true); file_put_contents("{$tmpPath}/h5p.json", $results); // Get a complete file list from our tmp dir $files = array(); self::populateFileList($tmpPath, $files); // Get path to temporary export target file $tmpFile = $this->h5pC->fs->getTmpPath(); // Create new zip instance. $zip = new ZipArchive(); $zip->open($tmpFile, ZipArchive::CREATE | ZipArchive::OVERWRITE); // Add all the files from the tmp dir. foreach ($files as $file) { // Please note that the zip format has no concept of folders, we must // use forward slashes to separate our directories. if (file_exists(realpath($file->absolutePath))) { $zip->addFile(realpath($file->absolutePath), $file->relativePath); } } // Close zip and remove tmp dir $zip->close(); H5PCore::deleteFileTree($tmpPath); $filename = $content['slug'] . '-' . $content['id'] . '.h5p'; try { // Save export $this->h5pC->fs->saveExport($tmpFile, $filename); } catch (Exception $e) { $this->h5pF->setErrorMessage($this->h5pF->t($e->getMessage()), 'failed-creating-export-file'); return false; } unlink($tmpFile); $this->h5pF->afterExportCreated($content, $filename); return true; } /** * Recursive function the will add the files of the given directory to the * given files list. All files are objects with an absolute path and * a relative path. The relative path is forward slashes only! Great for * use in zip files and URLs. * * @param string $dir path * @param array $files list * @param string $relative prefix. Optional */ private static function populateFileList($dir, &$files, $relative = '') { $strip = strlen($dir) + 1; $contents = glob($dir . '/' . '*'); if (!empty($contents)) { foreach ($contents as $file) { $rel = $relative . substr($file, $strip); if (is_dir($file)) { self::populateFileList($file, $files, $rel . '/'); } else { $files[] = (object) array( 'absolutePath' => $file, 'relativePath' => $rel ); } } } } /** * Delete .h5p file * * @param array $content object */ public function deleteExport($content) { $this->h5pC->fs->deleteExport(($content['slug'] ? $content['slug'] . '-' : '') . $content['id'] . '.h5p'); } /** * Add editor libraries to the list of libraries * * These are not supposed to go into h5p.json, but must be included with the rest * of the libraries * * TODO This is a private function that is not currently being used * * @param array $libraries * List of libraries keyed by machineName * @param array $editorLibraries * List of libraries keyed by machineName * @return array List of libraries keyed by machineName */ private function addEditorLibraries($libraries, $editorLibraries) { foreach ($editorLibraries as $editorLibrary) { $libraries[$editorLibrary['machineName']] = $editorLibrary; } return $libraries; } } abstract class H5PPermission { const DOWNLOAD_H5P = 0; const EMBED_H5P = 1; const CREATE_RESTRICTED = 2; const UPDATE_LIBRARIES = 3; const INSTALL_RECOMMENDED = 4; const COPY_H5P = 8; } abstract class H5PDisplayOptionBehaviour { const NEVER_SHOW = 0; const CONTROLLED_BY_AUTHOR_DEFAULT_ON = 1; const CONTROLLED_BY_AUTHOR_DEFAULT_OFF = 2; const ALWAYS_SHOW = 3; const CONTROLLED_BY_PERMISSIONS = 4; } abstract class H5PContentHubSyncStatus { const NOT_SYNCED = 0; const SYNCED = 1; const WAITING = 2; const FAILED = 3; } abstract class H5PContentStatus { const STATUS_UNPUBLISHED = 0; const STATUS_DOWNLOADED = 1; const STATUS_WAITING = 2; const STATUS_FAILED_DOWNLOAD = 3; const STATUS_FAILED_VALIDATION = 4; const STATUS_SUSPENDED = 5; } abstract class H5PHubEndpoints { const CONTENT_TYPES = 'api.h5p.org/v1/content-types/'; const SITES = 'api.h5p.org/v1/sites'; const METADATA = 'hub-api.h5p.org/v1/metadata'; const CONTENT = 'hub-api.h5p.org/v1/contents'; const REGISTER = 'hub-api.h5p.org/v1/accounts'; public static function createURL($endpoint) { $protocol = (extension_loaded('openssl') ? 'https' : 'http'); return "{$protocol}://{$endpoint}"; } } /** * Functions and storage shared by the other H5P classes */ class H5PCore { public static $coreApi = array( 'majorVersion' => 1, 'minorVersion' => 27 ); public static $styles = array( 'styles/h5p.css', 'styles/h5p-confirmation-dialog.css', 'styles/h5p-core-button.css', 'styles/h5p-tooltip.css', 'styles/h5p-table.css', ); public static $scripts = array( 'js/jquery.js', 'js/h5p.js', 'js/h5p-event-dispatcher.js', 'js/h5p-x-api-event.js', 'js/h5p-x-api.js', 'js/h5p-content-type.js', 'js/h5p-confirmation-dialog.js', 'js/h5p-action-bar.js', 'js/request-queue.js', 'js/h5p-tooltip.js', ); public static $adminScripts = array( 'js/jquery.js', 'js/h5p-utils.js', ); public static $defaultContentWhitelist = 'json png jpg jpeg gif bmp tif tiff eot ttf woff woff2 otf webm mp4 ogg mp3 m4a wav txt pdf rtf doc docx xls xlsx ppt pptx odt ods odp csv diff patch swf md textile vtt webvtt gltf glb'; public static $defaultLibraryWhitelistExtras = 'js css svg xml'; public $librariesJsonData, $contentJsonData, $mainJsonData, $h5pF, $fs, $h5pD, $disableFileCheck; const SECONDS_IN_WEEK = 604800; private $exportEnabled; // Disable flags const DISABLE_NONE = 0; const DISABLE_FRAME = 1; const DISABLE_DOWNLOAD = 2; const DISABLE_EMBED = 4; const DISABLE_COPYRIGHT = 8; const DISABLE_ABOUT = 16; const DISPLAY_OPTION_FRAME = 'frame'; const DISPLAY_OPTION_DOWNLOAD = 'export'; const DISPLAY_OPTION_EMBED = 'embed'; const DISPLAY_OPTION_COPYRIGHT = 'copyright'; const DISPLAY_OPTION_ABOUT = 'icon'; const DISPLAY_OPTION_COPY = 'copy'; // Map flags to string public static $disable = array( self::DISABLE_FRAME => self::DISPLAY_OPTION_FRAME, self::DISABLE_DOWNLOAD => self::DISPLAY_OPTION_DOWNLOAD, self::DISABLE_EMBED => self::DISPLAY_OPTION_EMBED, self::DISABLE_COPYRIGHT => self::DISPLAY_OPTION_COPYRIGHT ); /** @var string */ public $url; /** @var int evelopment mode. */ public $development_mode; /** @var bool aggregated files for assets. */ public $aggregateAssets; /** @var string full path of plugin. */ protected $fullPluginPath; /** @var string regex for converting copied files paths. */ public $relativePathRegExp; /** * Constructor for the H5PCore * * @param H5PFrameworkInterface $H5PFramework * The frameworks implementation of the H5PFrameworkInterface * @param string|H5PFileStorage $path H5P file storage directory or class. * @param string $url To file storage directory. * @param string $language code. Defaults to english. * @param boolean $export enabled? */ public function __construct(H5PFrameworkInterface $H5PFramework, $path, $url, $language = 'en', $export = FALSE) { $this->h5pF = $H5PFramework; $this->fs = ($path instanceof H5PFileStorage ? $path : new H5PDefaultStorage($path)); $this->url = $url; $this->exportEnabled = $export; $this->development_mode = H5PDevelopment::MODE_NONE; $this->aggregateAssets = FALSE; // Off by default.. for now $this->detectSiteType(); $this->fullPluginPath = preg_replace('/\/[^\/]+[\/]?$/', '' , dirname(__FILE__)); // Standard regex for converting copied files paths $this->relativePathRegExp = '/^((\.\.\/){1,2})(.*content\/)?(\d+|editor)\/(.+)$/'; } /** * Save content and clear cache. * * @param array $content * @param null|int $contentMainId * @return int Content ID */ public function saveContent($content, $contentMainId = NULL) { if (isset($content['id'])) { $this->h5pF->updateContent($content, $contentMainId); } else { $content['id'] = $this->h5pF->insertContent($content, $contentMainId); } // Some user data for content has to be reset when the content changes. $this->h5pF->resetContentUserData($contentMainId ? $contentMainId : $content['id']); return $content['id']; } /** * Load content. * * @param int $id for content. * @return object */ public function loadContent($id) { $content = $this->h5pF->loadContent($id); if ($content !== NULL) { // Validate main content's metadata $validator = new H5PContentValidator($this->h5pF, $this); $content['metadata'] = $validator->validateMetadata($content['metadata']); $content['library'] = array( 'id' => $content['libraryId'], 'name' => $content['libraryName'], 'majorVersion' => $content['libraryMajorVersion'], 'minorVersion' => $content['libraryMinorVersion'], 'embedTypes' => $content['libraryEmbedTypes'], 'fullscreen' => $content['libraryFullscreen'], ); unset($content['libraryId'], $content['libraryName'], $content['libraryEmbedTypes'], $content['libraryFullscreen']); // // TODO: Move to filterParameters? // if (isset($this->h5pD)) { // // TODO: Remove Drupal specific stuff // $json_content_path = file_create_path(file_directory_path() . '/' . variable_get('h5p_default_path', 'h5p') . '/content/' . $id . '/content.json'); // if (file_exists($json_content_path) === TRUE) { // $json_content = file_get_contents($json_content_path); // if (json_decode($json_content, TRUE) !== FALSE) { // drupal_set_message(t('Invalid json in json content'), 'warning'); // } // $content['params'] = $json_content; // } // } } return $content; } /** * Filter content run parameters, rebuild content dependency cache and export file. * * @param Object|array $content * @return Object NULL on failure. */ public function filterParameters(&$content) { if (!empty($content['filtered']) && (!$this->exportEnabled || ($content['slug'] && $this->fs->hasExport($content['slug'] . '-' . $content['id'] . '.h5p')))) { return $content['filtered']; } if (!(isset($content['library']) && isset($content['params']))) { return NULL; } // Validate and filter against main library semantics. $validator = new H5PContentValidator($this->h5pF, $this); $params = (object) array( 'library' => H5PCore::libraryToString($content['library']), 'params' => json_decode($content['params']) ); if (!$params->params) { return NULL; } $validator->validateLibrary($params, (object) array('options' => array($params->library))); // Handle addons: $addons = $this->h5pF->loadAddons(); foreach ($addons as $addon) { $add_to = json_decode($addon['addTo']); if (isset($add_to->content->types)) { foreach($add_to->content->types as $type) { if (isset($type->text->regex) && $this->textAddonMatches($params->params, $type->text->regex)) { $validator->addon($addon); // An addon shall only be added once break; } } } } $params = json_encode($params->params); // Update content dependencies. $content['dependencies'] = $validator->getDependencies(); // Sometimes the parameters are filtered before content has been created if ($content['id']) { $this->h5pF->deleteLibraryUsage($content['id']); $this->h5pF->saveLibraryUsage($content['id'], $content['dependencies']); if (!$content['slug']) { $content['slug'] = $this->generateContentSlug($content); // Remove old export file $this->fs->deleteExport($content['id'] . '.h5p'); } if ($this->exportEnabled) { // Recreate export file $exporter = new H5PExport($this->h5pF, $this); $content['filtered'] = $params; $exporter->createExportFile($content); } // Cache. $this->h5pF->updateContentFields($content['id'], array( 'filtered' => $params, 'slug' => $content['slug'] )); } return $params; } /** * Retrieve a value from a nested mixed array structure. * * @param Array $params Array to be looked in. * @param String $path Supposed path to the value. * @param String [$delimiter='.'] Property delimiter within the path. * @return Object|NULL The object found or NULL. */ private function retrieveValue ($params, $path, $delimiter='.') { $path = explode($delimiter, $path); // Property not found if (!isset($params[$path[0]])) { return NULL; } $first = $params[$path[0]]; // End of path, done if (sizeof($path) === 1) { return $first; } // We cannot go deeper if (!is_array($first)) { return NULL; } // Regular Array if (isset($first[0])) { foreach($first as $number => $object) { $found = $this->retrieveValue($object, implode($delimiter, array_slice($path, 1))); if (isset($found)) { return $found; } } return NULL; } // Associative Array return $this->retrieveValue($first, implode('.', array_slice($path, 1))); } /** * Determine if params contain any match. * * @param {object} params - Parameters. * @param {string} [pattern] - Regular expression to identify pattern. * @param {boolean} [found] - Used for recursion. * @return {boolean} True, if params matches pattern. */ private function textAddonMatches($params, $pattern, $found = false) { $type = gettype($params); if ($type === 'string') { if (preg_match($pattern, $params) === 1) { return true; } } elseif ($type === 'array' || $type === 'object') { foreach ($params as $value) { $found = $this->textAddonMatches($value, $pattern, $found); if ($found === true) { return true; } } } return false; } /** * Generate content slug * * @param array $content object * @return string unique content slug */ private function generateContentSlug($content) { $slug = H5PCore::slugify($content['title']); $available = NULL; while (!$available) { if ($available === FALSE) { // If not available, add number suffix. $matches = array(); if (preg_match('/(.+-)([0-9]+)$/', $slug, $matches)) { $slug = $matches[1] . (intval($matches[2]) + 1); } else { $slug .= '-2'; } } $available = $this->h5pF->isContentSlugAvailable($slug); } return $slug; } /** * Find the files required for this content to work. * * @param int $id for content. * @param null $type * @return array */ public function loadContentDependencies($id, $type = NULL) { $dependencies = $this->h5pF->loadContentDependencies($id, $type); if (isset($this->h5pD)) { $developmentLibraries = $this->h5pD->getLibraries(); foreach ($dependencies as $key => $dependency) { $libraryString = H5PCore::libraryToString($dependency); if (isset($developmentLibraries[$libraryString])) { $developmentLibraries[$libraryString]['dependencyType'] = $dependencies[$key]['dependencyType']; $dependencies[$key] = $developmentLibraries[$libraryString]; } } } return $dependencies; } /** * Get all dependency assets of the given type * * @param array $dependency * @param string $type * @param array $assets * @param string $prefix Optional. Make paths relative to another dir. */ private function getDependencyAssets($dependency, $type, &$assets, $prefix = '') { // Check if dependency has any files of this type if (empty($dependency[$type]) || $dependency[$type][0] === '') { return; } // Check if we should skip CSS. if ($type === 'preloadedCss' && (isset($dependency['dropCss']) && $dependency['dropCss'] === '1')) { return; } foreach ($dependency[$type] as $file) { $assets[] = (object) array( 'path' => $prefix . '/' . $dependency['path'] . '/' . trim(is_array($file) ? $file['path'] : $file), 'version' => $dependency['version'] ); } } /** * Combines path with cache buster / version. * * @param array $assets * @return array */ public function getAssetsUrls($assets) { $urls = array(); foreach ($assets as $asset) { $url = $asset->path; // Add URL prefix if not external if (strpos($asset->path, '://') === FALSE) { $url = $this->url . $url; } // Add version/cache buster if set if (isset($asset->version)) { $url .= $asset->version; } $urls[] = $url; } return $urls; } /** * Return file paths for all dependencies files. * * @param array $dependencies * @param string $prefix Optional. Make paths relative to another dir. * @return array files. */ public function getDependenciesFiles($dependencies, $prefix = '') { // Build files list for assets $files = array( 'scripts' => array(), 'styles' => array() ); $key = null; // Avoid caching empty files if (empty($dependencies)) { return $files; } if ($this->aggregateAssets) { // Get aggregated files for assets $key = self::getDependenciesHash($dependencies); $cachedAssets = $this->fs->getCachedAssets($key); if ($cachedAssets !== NULL) { return array_merge($files, $cachedAssets); // Using cached assets } } // Using content dependencies foreach ($dependencies as $dependency) { if (isset($dependency['path']) === FALSE) { $dependency['path'] = $this->getDependencyPath($dependency); $dependency['preloadedJs'] = explode(',', $dependency['preloadedJs']); $dependency['preloadedCss'] = explode(',', $dependency['preloadedCss']); } $dependency['version'] = "?ver={$dependency['majorVersion']}.{$dependency['minorVersion']}.{$dependency['patchVersion']}"; $this->getDependencyAssets($dependency, 'preloadedJs', $files['scripts'], $prefix); $this->getDependencyAssets($dependency, 'preloadedCss', $files['styles'], $prefix); } if ($this->aggregateAssets) { // Aggregate and store assets $this->fs->cacheAssets($files, $key); // Keep track of which libraries have been cached in case they are updated $this->h5pF->saveCachedAssets($key, $dependencies); } return $files; } /** * Get the path to the dependency. * * @param array $dependency * @return string */ protected function getDependencyPath(array $dependency) { return 'libraries/' . H5PCore::libraryToFolderName($dependency); } private static function getDependenciesHash(&$dependencies) { // Build hash of dependencies $toHash = array(); // Use unique identifier for each library version foreach ($dependencies as $dep) { $toHash[] = "{$dep['machineName']}-{$dep['majorVersion']}.{$dep['minorVersion']}.{$dep['patchVersion']}"; } // Sort in case the same dependencies comes in a different order sort($toHash); // Calculate hash sum return hash('sha1', implode('', $toHash)); } /** * Load library semantics. * * @param $name * @param $majorVersion * @param $minorVersion * @return string */ public function loadLibrarySemantics($name, $majorVersion, $minorVersion) { $semantics = NULL; if (isset($this->h5pD)) { // Try to load from dev lib $semantics = $this->h5pD->getSemantics($name, $majorVersion, $minorVersion); } if ($semantics === NULL) { // Try to load from DB. $semantics = $this->h5pF->loadLibrarySemantics($name, $majorVersion, $minorVersion); } if ($semantics !== NULL) { $semantics = json_decode($semantics); $this->h5pF->alterLibrarySemantics($semantics, $name, $majorVersion, $minorVersion); } return $semantics; } /** * Load library. * * @param $name * @param $majorVersion * @param $minorVersion * @return array or null. */ public function loadLibrary($name, $majorVersion, $minorVersion) { $library = NULL; if (isset($this->h5pD)) { // Try to load from dev $library = $this->h5pD->getLibrary($name, $majorVersion, $minorVersion); if ($library !== NULL) { $library['semantics'] = $this->h5pD->getSemantics($name, $majorVersion, $minorVersion); } } if ($library === NULL) { // Try to load from DB. $library = $this->h5pF->loadLibrary($name, $majorVersion, $minorVersion); } return $library; } /** * Deletes a library * * @param stdClass $libraryId */ public function deleteLibrary($libraryId) { $this->h5pF->deleteLibrary($libraryId); } /** * Recursive. Goes through the dependency tree for the given library and * adds all the dependencies to the given array in a flat format. * * @param $dependencies * @param array $library To find all dependencies for. * @param int $nextWeight An integer determining the order of the libraries * when they are loaded * @param bool $editor Used internally to force all preloaded sub dependencies * of an editor dependency to be editor dependencies. * @return int */ public function findLibraryDependencies(&$dependencies, $library, $nextWeight = 1, $editor = FALSE) { foreach (array('dynamic', 'preloaded', 'editor') as $type) { $property = $type . 'Dependencies'; if (!isset($library[$property])) { continue; // Skip, no such dependencies. } if ($type === 'preloaded' && $editor === TRUE) { // All preloaded dependencies of an editor library is set to editor. $type = 'editor'; } foreach ($library[$property] as $dependency) { $dependencyKey = $type . '-' . $dependency['machineName']; if (isset($dependencies[$dependencyKey]) === TRUE) { continue; // Skip, already have this. } $dependencyLibrary = $this->loadLibrary($dependency['machineName'], $dependency['majorVersion'], $dependency['minorVersion']); if ($dependencyLibrary) { $dependencies[$dependencyKey] = array( 'library' => $dependencyLibrary, 'type' => $type ); $nextWeight = $this->findLibraryDependencies($dependencies, $dependencyLibrary, $nextWeight, $type === 'editor'); $dependencies[$dependencyKey]['weight'] = $nextWeight++; } else { // This site is missing a dependency! $this->h5pF->setErrorMessage($this->h5pF->t('Missing dependency @dep required by @lib.', array('@dep' => H5PCore::libraryToString($dependency), '@lib' => H5PCore::libraryToString($library))), 'missing-library-dependency'); } } } return $nextWeight; } /** * Check if a library is of the version we're looking for * * Same version means that the majorVersion and minorVersion is the same * * @param array $library * Data from library.json * @param array $dependency * Definition of what library we're looking for * @return boolean * TRUE if the library is the same version as the dependency * FALSE otherwise */ public function isSameVersion($library, $dependency) { if ($library['machineName'] != $dependency['machineName']) { return FALSE; } if ($library['majorVersion'] != $dependency['majorVersion']) { return FALSE; } if ($library['minorVersion'] != $dependency['minorVersion']) { return FALSE; } return TRUE; } /** * Recursive function for removing directories. * * @param string $dir * Path to the directory we'll be deleting * @return boolean * Indicates if the directory existed. */ public static function deleteFileTree($dir) { if (!is_dir($dir)) { return false; } if (is_link($dir)) { // Do not traverse and delete linked content, simply unlink. unlink($dir); return; } $files = array_diff(scandir($dir), array('.','..')); foreach ($files as $file) { $filepath = "$dir/$file"; // Note that links may resolve as directories if (!is_dir($filepath) || is_link($filepath)) { // Unlink files and links unlink($filepath); } else { // Traverse subdir and delete files self::deleteFileTree($filepath); } } return rmdir($dir); } /** * Writes library data as string on the form {machineName} {majorVersion}.{minorVersion} * * @param array $library * With keys (machineName and/or name), majorVersion and minorVersion * @return string * On the form {machineName} {majorVersion}.{minorVersion} */ public static function libraryToString($library) { $name = $library['machineName'] ?? $library['name']; return "{$name} {$library['majorVersion']}.{$library['minorVersion']}"; } /** * Get the name of a library's folder name * * @return string */ public static function libraryToFolderName($library) { $name = $library['machineName'] ?? $library['name']; $includePatchVersion = $library['patchVersionInFolderName'] ?? false; return "{$name}-{$library['majorVersion']}.{$library['minorVersion']}" . ($includePatchVersion ? ".{$library['patchVersion']}" : ''); } /** * Parses library data from a string on the form {machineName} {majorVersion}.{minorVersion} * * @param string $libraryString * On the form {machineName} {majorVersion}.{minorVersion} * @return array|FALSE * With keys machineName, majorVersion and minorVersion. * Returns FALSE only if string is not parsable in the normal library * string formats "Lib.Name-x.y" or "Lib.Name x.y" */ public static function libraryFromString($libraryString) { $re = '/^([\w0-9\-\.]{1,255})[\-\ ]([0-9]{1,5})\.([0-9]{1,5})$/i'; $matches = array(); $res = preg_match($re, $libraryString, $matches); if ($res) { return array( 'machineName' => $matches[1], 'majorVersion' => $matches[2], 'minorVersion' => $matches[3] ); } return FALSE; } /** * Determine the correct embed type to use. * * @param $contentEmbedType * @param $libraryEmbedTypes * @return string 'div' or 'iframe'. */ public static function determineEmbedType($contentEmbedType, $libraryEmbedTypes) { // Detect content embed type $embedType = strpos(strtolower($contentEmbedType), 'div') !== FALSE ? 'div' : 'iframe'; if ($libraryEmbedTypes !== NULL && $libraryEmbedTypes !== '') { // Check that embed type is available for library $embedTypes = strtolower($libraryEmbedTypes); if (strpos($embedTypes, $embedType) === FALSE) { // Not available, pick default. $embedType = strpos($embedTypes, 'div') !== FALSE ? 'div' : 'iframe'; } } return $embedType; } /** * Get the absolute version for the library as a human readable string. * * @param object $library * @return string */ public static function libraryVersion($library) { return $library->major_version . '.' . $library->minor_version . '.' . $library->patch_version; } /** * Determine which versions content with the given library can be upgraded to. * * @param object $library * @param array $versions * @return array */ public function getUpgrades($library, $versions) { $upgrades = array(); foreach ($versions as $upgrade) { if ($upgrade->major_version > $library->major_version || $upgrade->major_version === $library->major_version && $upgrade->minor_version > $library->minor_version) { $upgrades[$upgrade->id] = H5PCore::libraryVersion($upgrade); } } return $upgrades; } /** * Converts all the properties of the given object or array from * snake_case to camelCase. Useful after fetching data from the database. * * Note that some databases does not support camelCase. * * @param mixed $arr input * @param boolean $obj return object * @return mixed object or array */ public static function snakeToCamel($arr, $obj = false) { $newArr = array(); foreach ($arr as $key => $val) { $next = -1; while (($next = strpos($key, '_', $next + 1)) !== FALSE) { $key = substr_replace($key, strtoupper($key[$next + 1]), $next, 2); } $newArr[$key] = $val; } return $obj ? (object) $newArr : $newArr; } /** * Detects if the site was accessed from localhost, * through a local network or from the internet. */ public function detectSiteType() { $type = $this->h5pF->getOption('site_type', 'local'); // Determine remote/visitor origin if ($type === 'network' || ($type === 'local' && isset($_SERVER['REMOTE_ADDR']) && !preg_match('/^localhost$|^127(?:\.[0-9]+){0,2}\.[0-9]+$|^(?:0*\:)*?:?0*1$/i', $_SERVER['REMOTE_ADDR']))) { if (isset($_SERVER['REMOTE_ADDR']) && filter_var($_SERVER['REMOTE_ADDR'], FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE)) { // Internet $this->h5pF->setOption('site_type', 'internet'); } elseif ($type === 'local') { // Local network $this->h5pF->setOption('site_type', 'network'); } } } /** * Get a list of installed libraries, different minor versions will * return separate entries. * * @return array * A distinct array of installed libraries */ public function getLibrariesInstalled() { $librariesInstalled = array(); $libs = $this->h5pF->loadLibraries(); foreach($libs as $libName => $library) { foreach($library as $libVersion) { $librariesInstalled[$libName.' '.$libVersion->major_version.'.'.$libVersion->minor_version] = $libVersion->patch_version; } } return $librariesInstalled; } /** * Easy way to combine similar data sets. * * @param array $inputs Multiple arrays with data * @return array */ public function combineArrayValues($inputs) { $results = array(); foreach ($inputs as $index => $values) { foreach ($values as $key => $value) { $results[$key][$index] = $value; } } return $results; } /** * Communicate with H5P.org and get content type cache. Each platform * implementation is responsible for invoking this, eg using cron * * @param bool $fetchingDisabled * @param bool $onlyRegister Only register site with H5P.org * * @return bool|object Returns endpoint data if found, otherwise FALSE */ public function fetchLibrariesMetadata($fetchingDisabled = FALSE, $onlyRegister = false) { // Gather data $uuid = $this->h5pF->getOption('site_uuid', ''); $platform = $this->h5pF->getPlatformInfo(); $registrationData = array( 'uuid' => $uuid, 'platform_name' => $platform['name'], 'platform_version' => $platform['version'], 'h5p_version' => $platform['h5pVersion'], 'disabled' => $fetchingDisabled ? 1 : 0, 'local_id' => hash('crc32', $this->fullPluginPath), 'type' => $this->h5pF->getOption('site_type', 'local'), 'core_api_version' => H5PCore::$coreApi['majorVersion'] . '.' . H5PCore::$coreApi['minorVersion'] ); // Register site if it is not registered if (empty($uuid)) { $registration = $this->h5pF->fetchExternalData(H5PHubEndpoints::createURL(H5PHubEndpoints::SITES), $registrationData); // Failed retrieving uuid if (!$registration) { $errorMessage = $this->h5pF->t('Site could not be registered with the hub. Please contact your site administrator.'); $this->h5pF->setErrorMessage($errorMessage); $this->h5pF->setErrorMessage( $this->h5pF->t('The H5P Hub has been disabled until this problem can be resolved. You may still upload libraries through the "H5P Libraries" page.'), 'registration-failed-hub-disabled' ); return FALSE; } // Successfully retrieved new uuid $json = json_decode($registration); $registrationData['uuid'] = $json->uuid; $this->h5pF->setOption('site_uuid', $json->uuid); $this->h5pF->setInfoMessage( $this->h5pF->t('Your site was successfully registered with the H5P Hub.') ); $uuid = $json->uuid; // TODO: Uncomment when key is once again available in H5P Settings // $this->h5pF->setInfoMessage( // $this->h5pF->t('You have been provided a unique key that identifies you with the Hub when receiving new updates. The key is available for viewing in the "H5P Settings" page.') // ); } if ($onlyRegister) { return $uuid; } if ($this->h5pF->getOption('send_usage_statistics', TRUE)) { $siteData = array_merge( $registrationData, array( 'num_authors' => $this->h5pF->getNumAuthors(), 'libraries' => json_encode($this->combineArrayValues(array( 'patch' => $this->getLibrariesInstalled(), 'content' => $this->h5pF->getLibraryContentCount(), 'loaded' => $this->h5pF->getLibraryStats('library'), 'created' => $this->h5pF->getLibraryStats('content create'), 'createdUpload' => $this->h5pF->getLibraryStats('content create upload'), 'deleted' => $this->h5pF->getLibraryStats('content delete'), 'resultViews' => $this->h5pF->getLibraryStats('results content'), 'shortcodeInserts' => $this->h5pF->getLibraryStats('content shortcode insert') ))) ) ); } else { $siteData = $registrationData; } $result = $this->updateContentTypeCache($siteData); // No data received if (!$result || empty($result)) { return FALSE; } // Handle libraries metadata if (isset($result->libraries)) { foreach ($result->libraries as $library) { if (isset($library->tutorialUrl) && isset($library->machineName)) { $this->h5pF->setLibraryTutorialUrl($library->machineNamee, $library->tutorialUrl); } } } return $result; } /** * Create representation of display options as int * * @param array $sources * @param int $current * @return int */ public function getStorableDisplayOptions(&$sources, $current) { // Download - force setting it if always on or always off $download = $this->h5pF->getOption(self::DISPLAY_OPTION_DOWNLOAD, H5PDisplayOptionBehaviour::ALWAYS_SHOW); if ($download == H5PDisplayOptionBehaviour::ALWAYS_SHOW || $download == H5PDisplayOptionBehaviour::NEVER_SHOW) { $sources[self::DISPLAY_OPTION_DOWNLOAD] = ($download == H5PDisplayOptionBehaviour::ALWAYS_SHOW); } // Embed - force setting it if always on or always off $embed = $this->h5pF->getOption(self::DISPLAY_OPTION_EMBED, H5PDisplayOptionBehaviour::ALWAYS_SHOW); if ($embed == H5PDisplayOptionBehaviour::ALWAYS_SHOW || $embed == H5PDisplayOptionBehaviour::NEVER_SHOW) { $sources[self::DISPLAY_OPTION_EMBED] = ($embed == H5PDisplayOptionBehaviour::ALWAYS_SHOW); } foreach (H5PCore::$disable as $bit => $option) { if (!isset($sources[$option]) || !$sources[$option]) { $current |= $bit; // Disable } else { $current &= ~$bit; // Enable } } return $current; } /** * Determine display options visibility and value on edit * * @param int $disable * @return array */ public function getDisplayOptionsForEdit($disable = NULL) { $display_options = array(); $current_display_options = $disable === NULL ? array() : $this->getDisplayOptionsAsArray($disable); if ($this->h5pF->getOption(self::DISPLAY_OPTION_FRAME, TRUE)) { $display_options[self::DISPLAY_OPTION_FRAME] = isset($current_display_options[self::DISPLAY_OPTION_FRAME]) ? $current_display_options[self::DISPLAY_OPTION_FRAME] : TRUE; // Download $export = $this->h5pF->getOption(self::DISPLAY_OPTION_DOWNLOAD, H5PDisplayOptionBehaviour::ALWAYS_SHOW); if ($export == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON || $export == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF) { $display_options[self::DISPLAY_OPTION_DOWNLOAD] = isset($current_display_options[self::DISPLAY_OPTION_DOWNLOAD]) ? $current_display_options[self::DISPLAY_OPTION_DOWNLOAD] : ($export == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON); } // Embed $embed = $this->h5pF->getOption(self::DISPLAY_OPTION_EMBED, H5PDisplayOptionBehaviour::ALWAYS_SHOW); if ($embed == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON || $embed == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_OFF) { $display_options[self::DISPLAY_OPTION_EMBED] = isset($current_display_options[self::DISPLAY_OPTION_EMBED]) ? $current_display_options[self::DISPLAY_OPTION_EMBED] : ($embed == H5PDisplayOptionBehaviour::CONTROLLED_BY_AUTHOR_DEFAULT_ON); } // Copyright if ($this->h5pF->getOption(self::DISPLAY_OPTION_COPYRIGHT, TRUE)) { $display_options[self::DISPLAY_OPTION_COPYRIGHT] = isset($current_display_options[self::DISPLAY_OPTION_COPYRIGHT]) ? $current_display_options[self::DISPLAY_OPTION_COPYRIGHT] : TRUE; } } return $display_options; } /** * Helper function used to figure out embed & download behaviour * * @param string $option_name * @param H5PPermission $permission * @param int $id * @param bool &$value */ private function setDisplayOptionOverrides($option_name, $permission, $id, &$value) { $behaviour = $this->h5pF->getOption($option_name, H5PDisplayOptionBehaviour::ALWAYS_SHOW); // If never show globally, force hide if ($behaviour == H5PDisplayOptionBehaviour::NEVER_SHOW) { $value = false; } elseif ($behaviour == H5PDisplayOptionBehaviour::ALWAYS_SHOW) { // If always show or permissions say so, force show $value = true; } elseif ($behaviour == H5PDisplayOptionBehaviour::CONTROLLED_BY_PERMISSIONS) { $value = $this->h5pF->hasPermission($permission, $id); } } /** * Determine display option visibility when viewing H5P * * @param int $display_options * @param int $id Might be content id or user id. * Depends on what the platform needs to be able to determine permissions. * @return array */ public function getDisplayOptionsForView($disable, $id) { $display_options = $this->getDisplayOptionsAsArray($disable); if ($this->h5pF->getOption(self::DISPLAY_OPTION_FRAME, TRUE) == FALSE) { $display_options[self::DISPLAY_OPTION_FRAME] = false; } else { $this->setDisplayOptionOverrides(self::DISPLAY_OPTION_DOWNLOAD, H5PPermission::DOWNLOAD_H5P, $id, $display_options[self::DISPLAY_OPTION_DOWNLOAD]); $this->setDisplayOptionOverrides(self::DISPLAY_OPTION_EMBED, H5PPermission::EMBED_H5P, $id, $display_options[self::DISPLAY_OPTION_EMBED]); if ($this->h5pF->getOption(self::DISPLAY_OPTION_COPYRIGHT, TRUE) == FALSE) { $display_options[self::DISPLAY_OPTION_COPYRIGHT] = false; } } $display_options[self::DISPLAY_OPTION_COPY] = $this->h5pF->hasPermission(H5PPermission::COPY_H5P, $id); return $display_options; } /** * Convert display options as single byte to array * * @param int $disable * @return array */ private function getDisplayOptionsAsArray($disable) { return array( self::DISPLAY_OPTION_FRAME => !($disable & H5PCore::DISABLE_FRAME), self::DISPLAY_OPTION_DOWNLOAD => !($disable & H5PCore::DISABLE_DOWNLOAD), self::DISPLAY_OPTION_EMBED => !($disable & H5PCore::DISABLE_EMBED), self::DISPLAY_OPTION_COPYRIGHT => !($disable & H5PCore::DISABLE_COPYRIGHT), self::DISPLAY_OPTION_ABOUT => !!$this->h5pF->getOption(self::DISPLAY_OPTION_ABOUT, TRUE), ); } /** * Small helper for getting the library's ID. * * @param array $library * @param string [$libString] * @return int Identifier, or FALSE if non-existent */ public function getLibraryId($library, $libString = NULL) { static $libraryIdMap = []; if (!$libString) { $libString = self::libraryToString($library); } if (!isset($libraryIdMap[$libString])) { $libraryIdMap[$libString] = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']); } return $libraryIdMap[$libString]; } /** * Convert strings of text into simple kebab case slugs. * Very useful for readable urls etc. * * @param string $input * @return string */ public static function slugify($input) { // Down low $input = strtolower($input); // Replace common chars $input = str_replace( array('æ', 'ø', 'ö', 'ó', 'ô', 'Ò', 'Õ', 'Ý', 'ý', 'ÿ', 'ā', 'ă', 'ą', 'œ', 'å', 'ä', 'á', 'à', 'â', 'ã', 'ç', 'ć', 'ĉ', 'ċ', 'č', 'é', 'è', 'ê', 'ë', 'í', 'ì', 'î', 'ï', 'ú', 'ñ', 'ü', 'ù', 'û', 'ß', 'ď', 'đ', 'ē', 'ĕ', 'ė', 'ę', 'ě', 'ĝ', 'ğ', 'ġ', 'ģ', 'ĥ', 'ħ', 'ĩ', 'ī', 'ĭ', 'į', 'ı', 'ij', 'ĵ', 'ķ', 'ĺ', 'ļ', 'ľ', 'ŀ', 'ł', 'ń', 'ņ', 'ň', 'ʼn', 'ō', 'ŏ', 'ő', 'ŕ', 'ŗ', 'ř', 'ś', 'ŝ', 'ş', 'š', 'ţ', 'ť', 'ŧ', 'ũ', 'ū', 'ŭ', 'ů', 'ű', 'ų', 'ŵ', 'ŷ', 'ź', 'ż', 'ž', 'ſ', 'ƒ', 'ơ', 'ư', 'ǎ', 'ǐ', 'ǒ', 'ǔ', 'ǖ', 'ǘ', 'ǚ', 'ǜ', 'ǻ', 'ǽ', 'ǿ'), array('ae', 'oe', 'o', 'o', 'o', 'oe', 'o', 'o', 'y', 'y', 'y', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'a', 'c', 'c', 'c', 'c', 'c', 'e', 'e', 'e', 'e', 'i', 'i', 'i', 'i', 'u', 'n', 'u', 'u', 'u', 'es', 'd', 'd', 'e', 'e', 'e', 'e', 'e', 'g', 'g', 'g', 'g', 'h', 'h', 'i', 'i', 'i', 'i', 'i', 'ij', 'j', 'k', 'l', 'l', 'l', 'l', 'l', 'n', 'n', 'n', 'n', 'o', 'o', 'o', 'r', 'r', 'r', 's', 's', 's', 's', 't', 't', 't', 'u', 'u', 'u', 'u', 'u', 'u', 'w', 'y', 'z', 'z', 'z', 's', 'f', 'o', 'u', 'a', 'i', 'o', 'u', 'u', 'u', 'u', 'u', 'a', 'ae', 'oe'), $input); // Replace everything else $input = preg_replace('/[^a-z0-9]/', '-', $input); // Prevent double hyphen $input = preg_replace('/-{2,}/', '-', $input); // Prevent hyphen in beginning or end $input = trim($input, '-'); // Prevent to long slug if (strlen($input) > 91) { $input = substr($input, 0, 92); } // Prevent empty slug if ($input === '') { $input = 'interactive'; } return $input; } /** * Makes it easier to print response when AJAX request succeeds. * * @param mixed $data * @since 1.6.0 */ public static function ajaxSuccess($data = NULL, $only_data = FALSE) { $response = array( 'success' => TRUE ); if ($data !== NULL) { $response['data'] = $data; // Pass data flatly to support old methods if ($only_data) { $response = $data; } } self::printJson($response); } /** * Makes it easier to print response when AJAX request fails. * Will exit after printing error. * * @param string $message A human readable error message * @param string $error_code An machine readable error code that a client * should be able to interpret * @param null|int $status_code Http response code * @param array [$details=null] Better description of the error and possible which action to take * @since 1.6.0 */ public static function ajaxError($message = NULL, $error_code = NULL, $status_code = NULL, $details = NULL) { $response = array( 'success' => FALSE ); if ($message !== NULL) { $response['message'] = $message; } if ($error_code !== NULL) { $response['errorCode'] = $error_code; } if ($details !== NULL) { $response['details'] = $details; } self::printJson($response, $status_code); } /** * Print JSON headers with UTF-8 charset and json encode response data. * Makes it easier to respond using JSON. * * @param mixed $data * @param null|int $status_code Http response code */ private static function printJson($data, $status_code = NULL) { header('Cache-Control: no-cache'); header('Content-Type: application/json; charset=utf-8'); print json_encode($data); } /** * Get a new H5P security token for the given action. * * @param string $action * @return string token */ public static function createToken($action) { // Create and return token return self::hashToken($action, self::getTimeFactor()); } /** * Create a time based number which is unique for each 12 hour. * @return int */ private static function getTimeFactor() { return ceil(time() / (86400 / 2)); } /** * Generate a unique hash string based on action, time and token * * @param string $action * @param int $time_factor * @return string */ private static function hashToken($action, $time_factor) { global $SESSION; if (!isset($SESSION->h5p_token)) { // Create an unique key which is used to create action tokens for this session. if (function_exists('random_bytes')) { $SESSION->h5p_token = base64_encode(random_bytes(15)); } else if (function_exists('openssl_random_pseudo_bytes')) { $SESSION->h5p_token = base64_encode(openssl_random_pseudo_bytes(15)); } else { $SESSION->h5p_token = uniqid('', TRUE); } } // Create hash and return return substr(hash('md5', $action . $time_factor . $SESSION->h5p_token), -16, 13); } /** * Verify if the given token is valid for the given action. * * @param string $action * @param string $token * @return boolean valid token */ public static function validToken($action, $token) { // Get the timefactor $time_factor = self::getTimeFactor(); // Check token to see if it's valid return $token === self::hashToken($action, $time_factor) || // Under 12 hours $token === self::hashToken($action, $time_factor - 1); // Between 12-24 hours } /** * Update content type cache * * @param object $postData Data sent to the hub * * @return bool|object Returns endpoint data if found, otherwise FALSE */ public function updateContentTypeCache($postData = NULL) { $interface = $this->h5pF; // Make sure data is sent! if (!isset($postData) || !isset($postData['uuid'])) { return $this->fetchLibrariesMetadata(); } $postData['current_cache'] = $this->h5pF->getOption('content_type_cache_updated_at', 0); $data = $interface->fetchExternalData(H5PHubEndpoints::createURL(H5PHubEndpoints::CONTENT_TYPES), $postData); if (! $this->h5pF->getOption('hub_is_enabled', TRUE)) { return TRUE; } // No data received if (!$data) { $interface->setErrorMessage( $interface->t("Couldn't communicate with the H5P Hub. Please try again later."), 'failed-communicationg-with-hub' ); return FALSE; } $json = json_decode($data); // No libraries received if (!isset($json->contentTypes) || empty($json->contentTypes)) { $interface->setErrorMessage( $interface->t('No content types were received from the H5P Hub. Please try again later.'), 'no-content-types-from-hub' ); return FALSE; } // Replace content type cache $interface->replaceContentTypeCache($json); // Inform of the changes and update timestamp $interface->setInfoMessage($interface->t('Library cache was successfully updated!')); $interface->setOption('content_type_cache_updated_at', time()); return $data; } /** * Update content hub metadata cache */ public function updateContentHubMetadataCache($lang = 'en') { $url = H5PHubEndpoints::createURL(H5PHubEndpoints::METADATA); $lastModified = $this->h5pF->getContentHubMetadataChecked($lang); $headers = array(); if (!empty($lastModified)) { $headers['If-Modified-Since'] = $lastModified; } $data = $this->h5pF->fetchExternalData("{$url}?lang={$lang}", NULL, TRUE, NULL, TRUE, $headers, NULL, 'GET'); $lastChecked = new DateTime('now', new DateTimeZone('GMT')); if ($data['status'] !== 200 && $data['status'] !== 304) { // If this was not a success, set the error message and return $this->h5pF->setErrorMessage( $this->h5pF->t('No metadata was received from the H5P Hub. Please try again later.') ); return null; } // Update timestamp $this->h5pF->setContentHubMetadataChecked($lastChecked->getTimestamp(), $lang); // Not modified if ($data['status'] === 304) { return null; } $this->h5pF->replaceContentHubMetadataCache($data['data'], $lang); // TODO: If 200 should we have checked if it decodes? Or 'success'? Not sure if necessary though return $data['data']; } /** * Get updated content hub metadata cache * * @param string $lang Language as ISO 639-1 code * * @return JsonSerializable|string */ public function getUpdatedContentHubMetadataCache($lang = 'en') { $lastUpdate = $this->h5pF->getContentHubMetadataChecked($lang); if (!$lastUpdate) { return $this->updateContentHubMetadataCache($lang); } $lastUpdate = new DateTime($lastUpdate); $expirationTime = $lastUpdate->getTimestamp() + (60 * 60 * 24); // Check once per day if (time() > $expirationTime) { $update = $this->updateContentHubMetadataCache($lang); if (!empty($update)) { return $update; } } $storedCache = $this->h5pF->getContentHubMetadataCache($lang); if (!$storedCache) { // We don't have the value stored for some reason, reset last update and re-fetch $this->h5pF->setContentHubMetadataChecked(null, $lang); return $this->updateContentHubMetadataCache($lang); } return $storedCache; } /** * Check if the current server setup is valid and set error messages * * @return object Setup object with errors and disable hub properties */ public function checkSetupErrorMessage() { $setup = (object) array( 'errors' => array(), 'disable_hub' => FALSE ); if (!class_exists('ZipArchive')) { $setup->errors[] = $this->h5pF->t('Your PHP version does not support ZipArchive.'); $setup->disable_hub = TRUE; } if (!extension_loaded('mbstring')) { $setup->errors[] = $this->h5pF->t( 'The mbstring PHP extension is not loaded. H5P needs this to function properly' ); $setup->disable_hub = TRUE; } // Check php version >= 5.2 $php_version = explode('.', phpversion()); if ($php_version[0] < 5 || ($php_version[0] === 5 && $php_version[1] < 2)) { $setup->errors[] = $this->h5pF->t('Your PHP version is outdated. H5P requires version 5.2 to function properly. Version 5.6 or later is recommended.'); $setup->disable_hub = TRUE; } // Check write access if (!$this->fs->hasWriteAccess()) { $setup->errors[] = $this->h5pF->t('A problem with the server write access was detected. Please make sure that your server can write to your data folder.'); $setup->disable_hub = TRUE; } $max_upload_size = self::returnBytes(ini_get('upload_max_filesize')); $max_post_size = self::returnBytes(ini_get('post_max_size')); $byte_threshold = 5000000; // 5MB if ($max_upload_size < $byte_threshold) { $setup->errors[] = $this->h5pF->t('Your PHP max upload size is quite small. With your current setup, you may not upload files larger than %number MB. This might be a problem when trying to upload H5Ps, images and videos. Please consider to increase it to more than 5MB.', array('%number' => number_format($max_upload_size / 1024 / 1024, 2, '.', ' '))); } if ($max_post_size < $byte_threshold) { $setup->errors[] = $this->h5pF->t('Your PHP max post size is quite small. With your current setup, you may not upload files larger than %number MB. This might be a problem when trying to upload H5Ps, images and videos. Please consider to increase it to more than 5MB', array('%number' => number_format($max_upload_size / 1024 / 1024, 2, '.', ' '))); } if ($max_upload_size > $max_post_size) { $setup->errors[] = $this->h5pF->t('Your PHP max upload size is bigger than your max post size. This is known to cause issues in some installations.'); } // Check SSL if (!extension_loaded('openssl')) { $setup->errors[] = $this->h5pF->t('Your server does not have SSL enabled. SSL should be enabled to ensure a secure connection with the H5P hub.'); $setup->disable_hub = TRUE; } return $setup; } /** * Check that all H5P requirements for the server setup is met. */ public function checkSetupForRequirements() { $setup = $this->checkSetupErrorMessage(); $this->h5pF->setOption('hub_is_enabled', !$setup->disable_hub); if (!empty($setup->errors)) { foreach ($setup->errors as $err) { $this->h5pF->setErrorMessage($err); } } if ($setup->disable_hub) { // Inform how to re-enable hub $this->h5pF->setErrorMessage( $this->h5pF->t('H5P hub communication has been disabled because one or more H5P requirements failed.') ); $this->h5pF->setErrorMessage( $this->h5pF->t('When you have revised your server setup you may re-enable H5P hub communication in H5P Settings.') ); } } /** * Return bytes from php_ini string value * * @param string $val * * @return int|string */ public static function returnBytes($val) { $val = trim($val); $last = strtolower($val[strlen($val) - 1]); $bytes = (int) $val; switch ($last) { case 'g': $bytes *= 1024; case 'm': $bytes *= 1024; case 'k': $bytes *= 1024; } return $bytes; } /** * Check if the current user has permission to update and install new * libraries. * * @param bool [$set] Optional, sets the permission * @return bool */ public function mayUpdateLibraries($set = null) { static $can; if ($set !== null) { // Use value set $can = $set; } if ($can === null) { // Ask our framework $can = $this->h5pF->mayUpdateLibraries(); } return $can; } /** * Provide localization for the Core JS * @return array */ public function getLocalization() { return array( 'fullscreen' => $this->h5pF->t('Fullscreen'), 'disableFullscreen' => $this->h5pF->t('Disable fullscreen'), 'download' => $this->h5pF->t('Download'), 'copyrights' => $this->h5pF->t('Rights of use'), 'embed' => $this->h5pF->t('Embed'), 'size' => $this->h5pF->t('Size'), 'showAdvanced' => $this->h5pF->t('Show advanced'), 'hideAdvanced' => $this->h5pF->t('Hide advanced'), 'advancedHelp' => $this->h5pF->t('Include this script on your website if you want dynamic sizing of the embedded content:'), 'copyrightInformation' => $this->h5pF->t('Rights of use'), 'close' => $this->h5pF->t('Close'), 'title' => $this->h5pF->t('Title'), 'author' => $this->h5pF->t('Author'), 'year' => $this->h5pF->t('Year'), 'source' => $this->h5pF->t('Source'), 'license' => $this->h5pF->t('License'), 'thumbnail' => $this->h5pF->t('Thumbnail'), 'noCopyrights' => $this->h5pF->t('No copyright information available for this content.'), 'reuse' => $this->h5pF->t('Reuse'), 'reuseContent' => $this->h5pF->t('Reuse Content'), 'reuseDescription' => $this->h5pF->t('Reuse this content.'), 'downloadDescription' => $this->h5pF->t('Download this content as a H5P file.'), 'copyrightsDescription' => $this->h5pF->t('View copyright information for this content.'), 'embedDescription' => $this->h5pF->t('View the embed code for this content.'), 'h5pDescription' => $this->h5pF->t('Visit H5P.org to check out more cool content.'), 'contentChanged' => $this->h5pF->t('This content has changed since you last used it.'), 'startingOver' => $this->h5pF->t("You'll be starting over."), 'by' => $this->h5pF->t('by'), 'showMore' => $this->h5pF->t('Show more'), 'showLess' => $this->h5pF->t('Show less'), 'subLevel' => $this->h5pF->t('Sublevel'), 'confirmDialogHeader' => $this->h5pF->t('Confirm action'), 'confirmDialogBody' => $this->h5pF->t('Please confirm that you wish to proceed. This action is not reversible.'), 'cancelLabel' => $this->h5pF->t('Cancel'), 'confirmLabel' => $this->h5pF->t('Confirm'), 'licenseU' => $this->h5pF->t('Undisclosed'), 'licenseCCBY' => $this->h5pF->t('Attribution'), 'licenseCCBYSA' => $this->h5pF->t('Attribution-ShareAlike'), 'licenseCCBYND' => $this->h5pF->t('Attribution-NoDerivs'), 'licenseCCBYNC' => $this->h5pF->t('Attribution-NonCommercial'), 'licenseCCBYNCSA' => $this->h5pF->t('Attribution-NonCommercial-ShareAlike'), 'licenseCCBYNCND' => $this->h5pF->t('Attribution-NonCommercial-NoDerivs'), 'licenseCC40' => $this->h5pF->t('4.0 International'), 'licenseCC30' => $this->h5pF->t('3.0 Unported'), 'licenseCC25' => $this->h5pF->t('2.5 Generic'), 'licenseCC20' => $this->h5pF->t('2.0 Generic'), 'licenseCC10' => $this->h5pF->t('1.0 Generic'), 'licenseGPL' => $this->h5pF->t('General Public License'), 'licenseV3' => $this->h5pF->t('Version 3'), 'licenseV2' => $this->h5pF->t('Version 2'), 'licenseV1' => $this->h5pF->t('Version 1'), 'licensePD' => $this->h5pF->t('Public Domain'), 'licenseCC010' => $this->h5pF->t('CC0 1.0 Universal (CC0 1.0) Public Domain Dedication'), 'licensePDM' => $this->h5pF->t('Public Domain Mark'), 'licenseC' => $this->h5pF->t('Copyright'), 'contentType' => $this->h5pF->t('Content Type'), 'licenseExtras' => $this->h5pF->t('License Extras'), 'changes' => $this->h5pF->t('Changelog'), 'contentCopied' => $this->h5pF->t('Content is copied to the clipboard'), 'connectionLost' => $this->h5pF->t('Connection lost. Results will be stored and sent when you regain connection.'), 'connectionReestablished' => $this->h5pF->t('Connection reestablished.'), 'resubmitScores' => $this->h5pF->t('Attempting to submit stored results.'), 'offlineDialogHeader' => $this->h5pF->t('Your connection to the server was lost'), 'offlineDialogBody' => $this->h5pF->t('We were unable to send information about your completion of this task. Please check your internet connection.'), 'offlineDialogRetryMessage' => $this->h5pF->t('Retrying in :num....'), 'offlineDialogRetryButtonLabel' => $this->h5pF->t('Retry now'), 'offlineSuccessfulSubmit' => $this->h5pF->t('Successfully submitted results.'), 'mainTitle' => $this->h5pF->t('Sharing :title'), 'editInfoTitle' => $this->h5pF->t('Edit info for :title'), 'cancel' => $this->h5pF->t('Cancel'), 'back' => $this->h5pF->t('Back'), 'next' => $this->h5pF->t('Next'), 'reviewInfo' => $this->h5pF->t('Review info'), 'share' => $this->h5pF->t('Share'), 'saveChanges' => $this->h5pF->t('Save changes'), 'registerOnHub' => $this->h5pF->t('Register on the H5P Hub'), 'updateRegistrationOnHub' => $this->h5pF->t('Save account settings'), 'requiredInfo' => $this->h5pF->t('Required Info'), 'optionalInfo' => $this->h5pF->t('Optional Info'), 'reviewAndShare' => $this->h5pF->t('Review & Share'), 'reviewAndSave' => $this->h5pF->t('Review & Save'), 'shared' => $this->h5pF->t('Shared'), 'currentStep' => $this->h5pF->t('Step :step of :total'), 'sharingNote' => $this->h5pF->t('All content details can be edited after sharing'), 'licenseDescription' => $this->h5pF->t('Select a license for your content'), 'licenseVersion' => $this->h5pF->t('License Version'), 'licenseVersionDescription' => $this->h5pF->t('Select a license version'), 'disciplineLabel' => $this->h5pF->t('Disciplines'), 'disciplineDescription' => $this->h5pF->t('You can select multiple disciplines'), 'disciplineLimitReachedMessage' => $this->h5pF->t('You can select up to :numDisciplines disciplines'), 'discipline' => array( 'searchPlaceholder' => $this->h5pF->t('Type to search for disciplines'), 'in' => $this->h5pF->t('in'), 'dropdownButton' => $this->h5pF->t('Dropdown button'), ), 'removeChip' => $this->h5pF->t('Remove :chip from the list'), 'keywordsPlaceholder' => $this->h5pF->t('Add keywords'), 'keywords' => $this->h5pF->t('Keywords'), 'keywordsDescription' => $this->h5pF->t('You can add multiple keywords separated by commas. Press "Enter" or "Add" to confirm keywords'), 'altText' => $this->h5pF->t('Alt text'), 'reviewMessage' => $this->h5pF->t('Please review the info below before you share'), 'subContentWarning' => $this->h5pF->t('Sub-content (images, questions etc.) will be shared under :license unless otherwise specified in the authoring tool'), 'disciplines' => $this->h5pF->t('Disciplines'), 'shortDescription' => $this->h5pF->t('Short description'), 'longDescription' => $this->h5pF->t('Long description'), 'icon' => $this->h5pF->t('Icon'), 'screenshots' => $this->h5pF->t('Screenshots'), 'helpChoosingLicense' => $this->h5pF->t('Help me choose a license'), 'shareFailed' => $this->h5pF->t('Share failed.'), 'editingFailed' => $this->h5pF->t('Editing failed.'), 'shareTryAgain' => $this->h5pF->t('Something went wrong, please try to share again.'), 'pleaseWait' => $this->h5pF->t('Please wait...'), 'language' => $this->h5pF->t('Language'), 'level' => $this->h5pF->t('Level'), 'shortDescriptionPlaceholder' => $this->h5pF->t('Short description of your content'), 'longDescriptionPlaceholder' => $this->h5pF->t('Long description of your content'), 'description' => $this->h5pF->t('Description'), 'iconDescription' => $this->h5pF->t('640x480px. If not selected content will use category icon'), 'screenshotsDescription' => $this->h5pF->t('Add up to five screenshots of your content'), 'submitted' => $this->h5pF->t('Submitted!'), 'isNowSubmitted' => $this->h5pF->t('Is now submitted to H5P Hub'), 'changeHasBeenSubmitted' => $this->h5pF->t('A change has been submited for'), 'contentAvailable' => $this->h5pF->t('Your content will normally be available in the Hub within one business day.'), 'contentUpdateSoon' => $this->h5pF->t('Your content will update soon'), 'contentLicenseTitle' => $this->h5pF->t('Content License Info'), 'licenseDialogDescription' => $this->h5pF->t('Click on a specific license to get info about proper usage'), 'publisherFieldTitle' => $this->h5pF->t('Publisher'), 'publisherFieldDescription' => $this->h5pF->t('This will display as the "Publisher name" on shared content'), 'emailAddress' => $this->h5pF->t('Email Address'), 'publisherDescription' => $this->h5pF->t('Publisher description'), 'publisherDescriptionText' => $this->h5pF->t('This will be displayed under "Publisher info" on shared content'), 'contactPerson' => $this->h5pF->t('Contact Person'), 'phone' => $this->h5pF->t('Phone'), 'address' => $this->h5pF->t('Address'), 'city' => $this->h5pF->t('City'), 'zip' => $this->h5pF->t('Zip'), 'country' => $this->h5pF->t('Country'), 'logoUploadText' => $this->h5pF->t('Organization logo or avatar'), 'acceptTerms' => $this->h5pF->t('I accept the
terms of use'), 'successfullyRegistred' => $this->h5pF->t('You have successfully registered an account on the H5P Hub'), 'successfullyRegistredDescription' => $this->h5pF->t('You account details can be changed'), 'successfullyUpdated' => $this->h5pF->t('Your H5P Hub account settings have successfully been changed'), 'accountDetailsLinkText' => $this->h5pF->t('here'), 'registrationTitle' => $this->h5pF->t('H5P Hub Registration'), 'registrationFailed' => $this->h5pF->t('An error occurred'), 'registrationFailedDescription' => $this->h5pF->t('We were not able to create an account at this point. Something went wrong. Try again later.'), 'maxLength' => $this->h5pF->t(':length is the maximum number of characters'), 'keywordExists' => $this->h5pF->t('Keyword already exists!'), 'licenseDetails' => $this->h5pF->t('License details'), 'remove' => $this->h5pF->t('Remove'), 'removeImage' => $this->h5pF->t('Remove image'), 'cancelPublishConfirmationDialogTitle' => $this->h5pF->t('Cancel sharing'), 'cancelPublishConfirmationDialogDescription' => $this->h5pF->t('Are you sure you want to cancel the sharing process?'), 'cancelPublishConfirmationDialogCancelButtonText' => $this->h5pF->t('No'), 'cancelPublishConfirmationDialogConfirmButtonText' => $this->h5pF->t('Yes'), 'add' => $this->h5pF->t('Add'), 'age' => $this->h5pF->t('Typical age'), 'ageDescription' => $this->h5pF->t('The target audience of this content. Possible input formats separated by commas: "1,34-45,-50,59-".'), 'invalidAge' => $this->h5pF->t('Invalid input format for Typical age. Possible input formats separated by commas: "1, 34-45, -50, -59-".'), 'contactPersonDescription' => $this->h5pF->t('H5P will reach out to the contact person in case there are any issues with the content shared by the publisher. The contact person\'s name or other information will not be published or shared with third parties'), 'emailAddressDescription' => $this->h5pF->t('The email address will be used by H5P to reach out to the publisher in case of any issues with the content or in case the publisher needs to recover their account. It will not be published or shared with any third parties'), 'copyrightWarning' => $this->h5pF->t('Copyrighted material cannot be shared in the H5P Content Hub. If the content is licensed with a OER friendly license like Creative Commons, please choose the appropriate license. If not this content cannot be shared.'), 'keywordsExits' => $this->h5pF->t('Keywords already exists!'), 'someKeywordsExits' => $this->h5pF->t('Some of these keywords already exist'), 'width' => $this->h5pF->t('width'), 'height' => $this->h5pF->t('height'), 'rotateLeft' => $this->h5pF->t('Rotate Left'), 'rotateRight' => $this->h5pF->t('Rotate Right'), 'cropImage' => $this->h5pF->t('Crop Image'), 'confirmCrop' => $this->h5pF->t('Confirm Crop'), 'cancelCrop' => $this->h5pF->t('Cancel Crop') ); } /** * Publish content on the H5P Hub. * * @param bigint $id * @return stdClass */ public function hubRetrieveContent($id) { $headers = array( 'Authorization' => $this->hubGetAuthorizationHeader(), 'Accept' => 'application/json', ); $response = $this->h5pF->fetchExternalData( H5PHubEndpoints::createURL(H5PHubEndpoints::CONTENT . "/{$id}"), NULL, TRUE, NULL, TRUE, $headers ); if (empty($response['data'])) { throw new Exception($this->h5pF->t('Unable to authorize with the H5P Hub. Please check your Hub registration and connection.')); } if (isset($response['status']) && $response['status'] !== 200) { if ($response['status'] === 404) { $this->h5pF->setErrorMessage($this->h5pF->t('Content is not shared on the H5P OER Hub.')); return NULL; } throw new Exception($this->h5pF->t("Couldn't communicate with the H5P Hub. Please try again later.")); } $hub_content = json_decode($response['data'])->data; $hub_content->id = "$hub_content->id"; return $hub_content; } /** * Publish content on the H5P Hub. * * @param array $data Data from content publishing process * @param array $files Files to upload with the content publish * @param bigint $content_hub_id For updating existing content * @return stdClass */ public function hubPublishContent($data, $files, $content_hub_id = NULL) { $headers = array( 'Authorization' => $this->hubGetAuthorizationHeader(), 'Accept' => 'application/json', ); $data['published'] = '1'; $endpoint = H5PHubEndpoints::CONTENT; if ($content_hub_id !== NULL) { $endpoint .= "/{$content_hub_id}"; $data['_method'] = 'PUT'; } $response = $this->h5pF->fetchExternalData( H5PHubEndpoints::createURL($endpoint), $data, TRUE, NULL, TRUE, $headers, $files ); if (empty($response['data']) || $response['status'] === 403) { throw new Exception($this->h5pF->t('Unable to authorize with the H5P Hub. Please check your Hub registration and connection.')); } if (isset($response['status']) && $response['status'] !== 200) { throw new Exception($this->h5pF->t('Connecting to the content hub failed, please try again later.')); } $result = json_decode($response['data']); if (isset($result->success) && $result->success === TRUE) { return $result; } elseif (!empty($result->errors)) { // Relay any error messages $e = new Exception($this->h5pF->t('Validation failed.')); $e->errors = $result->errors; throw $e; } } /** * Creates the authorization header needed to access the private parts of * the H5P Hub. * * @return string */ public function hubGetAuthorizationHeader() { $site_uuid = $this->h5pF->getOption('site_uuid', ''); $hub_secret = $this->h5pF->getOption('hub_secret', ''); if (empty($site_uuid)) { $this->h5pF->setErrorMessage($this->h5pF->t('Missing Site UUID. Please check your Hub registration.')); } elseif (empty($hub_secret)) { $this->h5pF->setErrorMessage($this->h5pF->t('Missing Hub Secret. Please check your Hub registration.')); } return 'Basic ' . base64_encode("$site_uuid:$hub_secret"); } /** * Unpublish content from content hub * * @param integer $hubId Content hub id * * @return bool True if successful */ public function hubUnpublishContent($hubId) { $headers = array( 'Authorization' => $this->hubGetAuthorizationHeader(), 'Accept' => 'application/json', ); $url = H5PHubEndpoints::createURL(H5PHubEndpoints::CONTENT); $response = $this->h5pF->fetchExternalData("{$url}/{$hubId}", array( 'published' => '0', ), true, null, true, $headers, array(), 'PUT'); // Remove shared status if successful if (!empty($response) && $response['status'] === 200) { $msg = $this->h5pF->t('Content successfully unpublished'); $this->h5pF->setInfoMessage($msg); return true; } $msg = $this->h5pF->t('Content unpublish failed'); $this->h5pF->setErrorMessage($msg); return false; } /** * Sync content with content hub * * @param integer $hubId Content hub id * @param string $exportPath Export path where .h5p for content can be found * * @return bool */ public function hubSyncContent($hubId, $exportPath) { $headers = array( 'Authorization' => $this->hubGetAuthorizationHeader(), 'Accept' => 'application/json', ); $url = H5PHubEndpoints::createURL(H5PHubEndpoints::CONTENT); $response = $this->h5pF->fetchExternalData("{$url}/{$hubId}", array( 'download_url' => $exportPath, 'resync' => '1', ), true, null, true, $headers, array(), 'PUT'); if (!empty($response) && $response['status'] === 200) { $msg = $this->h5pF->t('Content sync queued'); $this->h5pF->setInfoMessage($msg); return true; } $msg = $this->h5pF->t('Content sync failed'); $this->h5pF->setErrorMessage($msg); return false; } /** * Fetch account info for our site from the content hub * * @return array|bool|string False if account is not setup, otherwise data */ public function hubAccountInfo() { $siteUuid = $this->h5pF->getOption('site_uuid', null); $secret = $this->h5pF->getOption('hub_secret', null); if (empty($siteUuid) && !empty($secret)) { $this->h5pF->setErrorMessage($this->h5pF->t('H5P Hub secret is set without a site uuid. This may be fixed by restoring the site uuid or removing the hub secret and registering a new account with the content hub.')); throw new Exception('Hub secret not set'); } if (empty($siteUuid) || empty($secret)) { return false; } $headers = array( 'Authorization' => $this->hubGetAuthorizationHeader(), 'Accept' => 'application/json', ); $url = H5PHubEndpoints::createURL(H5PHubEndpoints::REGISTER); $accountInfo = $this->h5pF->fetchExternalData("{$url}/{$siteUuid}", null, true, null, true, $headers, array(), 'GET'); if ($accountInfo['status'] === 401) { // Unauthenticated, invalid hub secret and site uuid combination $this->h5pF->setErrorMessage($this->h5pF->t('Hub account authentication info is invalid. This may be fixed by an admin by restoring the hub secret or register a new account with the content hub.')); return false; } if ($accountInfo['status'] !== 200) { $this->h5pF->setErrorMessage($this->h5pF->t('Unable to retrieve HUB account information. Please contact support.')); return false; } return json_decode($accountInfo['data'])->data; } /** * Register account * * @param array $formData Form data. Should include: name, email, description, * contact_person, phone, address, city, zip, country, remove_logo * @param object $logo Input image * * @return array */ public function hubRegisterAccount($formData, $logo) { $uuid = $this->h5pF->getOption('site_uuid', ''); if (empty($uuid)) { // Attempt to fetch a new site uuid $uuid = $this->fetchLibrariesMetadata(false, true); if (!$uuid) { return [ 'message' => $this->h5pF->t('Site is missing a unique site uuid and was unable to set a new one. The H5P Content Hub is disabled until this problem can be resolved. Please make sure the H5P Hub is enabled in the H5P settings and try again later.'), 'status_code' => 403, 'error_code' => 'MISSING_SITE_UUID', 'success' => FALSE, ]; } } $formData['site_uuid'] = $uuid; $headers = []; $endpoint = H5PHubEndpoints::REGISTER; // Update if already registered $hasRegistered = $this->h5pF->getOption('hub_secret'); if ($hasRegistered) { $endpoint .= "/{$uuid}"; $formData['_method'] = 'PUT'; $headers = [ 'Authorization' => $this->hubGetAuthorizationHeader(), ]; } $url = H5PHubEndpoints::createURL($endpoint); $registration = $this->h5pF->fetchExternalData( $url, $formData, NULL, NULL, TRUE, $headers, isset($logo) ? ['logo' => $logo] : [] ); try { $results = json_decode($registration['data']); } catch (Exception $e) { return [ 'message' => 'Could not parse json response.', 'status_code' => 424, 'error_code' => 'COULD_NOT_PARSE_RESPONSE', 'success' => FALSE, ]; } if (isset($results->errors->site_uuid)) { return [ 'message' => 'Site UUID is not unique. This must be fixed by an admin by restoring the hub secret or remove the site uuid and register as a new account with the content hub.', 'status_code' => 403, 'error_code' => 'SITE_UUID_NOT_UNIQUE', 'success' => FALSE, ]; } if (isset($results->errors->logo)) { return [ 'message' => $results->errors->logo[0], 'status_code' => 400, 'success' => FALSE, ]; } if ( !isset($results->success) || $results->success === FALSE || !$hasRegistered && !isset($results->account->secret) || $registration['status'] !== 200 ) { return [ 'message' => 'Unable to register the account. Please contact support team.', 'status_code' => 422, 'error_code' => 'REGISTRATION_FAILED', 'success' => FALSE, ]; } if (!$hasRegistered) { $this->h5pF->setOption('hub_secret', $results->account->secret); } return [ 'message' => $this->h5pF->t('Account successfully registered.'), 'status_code' => 200, 'success' => TRUE, ]; } /** * Get status of content from content hub * * @param string $hubContentId * @param int $syncStatus * * @return false|int Returns a new H5PContentStatus if successful, else false */ public function getHubContentStatus($hubContentId, $syncStatus) { $headers = array( 'Authorization' => $this->hubGetAuthorizationHeader(), 'Accept' => 'application/json', ); $url = H5PHubEndpoints::createURL(H5PHubEndpoints::CONTENT); $response = $this->h5pF->fetchExternalData("{$url}/{$hubContentId}/status", null, true, null, true, $headers); if (isset($response['status']) && $response['status'] === 403) { $msg = $this->h5pF->t('The request for content status was unauthorized. This could be because the content belongs to a different account, or your account is not setup properly.'); $this->h5pF->setErrorMessage($msg); return false; } if (empty($response) || $response['status'] !== 200) { $msg = $this->h5pF->t('Could not get content hub sync status for content.'); $this->h5pF->setErrorMessage($msg); return false; } $data = json_decode($response['data']); if (isset($data->messages)) { // TODO: Is this the right place/way to display them? if (!empty($data->messages->info)) { foreach ($data->messages->info as $info) { $this->h5pF->setInfoMessage($info); } } if (!empty($data->messages->error)) { foreach ($data->messages->error as $error) { $this->h5pF->setErrorMessage($error->message, $error->code); } } } $contentStatus = intval($data->status); // Content status updated if ($contentStatus !== H5PContentStatus::STATUS_WAITING) { $newState = H5PContentHubSyncStatus::SYNCED; if ($contentStatus !== H5PContentStatus::STATUS_DOWNLOADED) { $newState = H5PContentHubSyncStatus::FAILED; } else if (intval($syncStatus) !== $contentStatus) { // Content status successfully transitioned to synced/downloaded $successMsg = $this->h5pF->t('Content was successfully shared on the content hub.'); $this->h5pF->setInfoMessage($successMsg); } return $newState; } return false; } } /** * Functions for validating basic types from H5P library semantics. * @property bool allowedStyles */ class H5PContentValidator { public $h5pF; public $h5pC; private $typeMap, $libraries, $dependencies, $nextWeight; private static $allowed_styleable_tags = [ 'span', 'p', 'div', 'h1', 'h2', 'h3', 'table', 'col', 'figure', 'td', 'th', 'li' ]; /** @var bool Allowed styles status. */ protected $allowedStyles; /** * Constructor for the H5PContentValidator * * @param object $H5PFramework * The frameworks implementation of the H5PFrameworkInterface * @param object $H5PCore * The main H5PCore instance */ public function __construct($H5PFramework, $H5PCore) { $this->h5pF = $H5PFramework; $this->h5pC = $H5PCore; $this->typeMap = array( 'text' => 'validateText', 'number' => 'validateNumber', 'boolean' => 'validateBoolean', 'list' => 'validateList', 'group' => 'validateGroup', 'file' => 'validateFile', 'image' => 'validateImage', 'video' => 'validateVideo', 'audio' => 'validateAudio', 'select' => 'validateSelect', 'library' => 'validateLibrary', ); $this->nextWeight = 1; // Keep track of the libraries we load to avoid loading it multiple times. $this->libraries = array(); // Keep track of all dependencies for the given content. $this->dependencies = array(); } /** * Add Addon library. */ public function addon($library) { $depKey = 'preloaded-' . $library['machineName']; $this->dependencies[$depKey] = array( 'library' => $library, 'type' => 'preloaded' ); $this->nextWeight = $this->h5pC->findLibraryDependencies($this->dependencies, $library, $this->nextWeight); $this->dependencies[$depKey]['weight'] = $this->nextWeight++; } /** * Get the flat dependency tree. * * @return array */ public function getDependencies() { return $this->dependencies; } /** * Validate metadata * * @param array $metadata * @return array Validated & filtered */ public function validateMetadata($metadata) { $semantics = $this->getMetadataSemantics(); $group = (object)$metadata; // Stop complaining about "invalid selected option in select" for // old content without license chosen. if (!isset($group->license)) { $group->license = 'U'; } $this->validateGroup($group, (object) array( 'type' => 'group', 'fields' => $semantics, ), FALSE); return (array)$group; } /** * Validate given text value against text semantics. * @param $text * @param $semantics */ public function validateText(&$text, $semantics) { if (!is_string($text)) { $text = ''; } if (isset($semantics->tags)) { // Not testing for empty array allows us to use the 4 defaults without // specifying them in semantics. $tags = array_merge(array('div', 'span', 'p', 'br'), $semantics->tags); // Add related tags for table etc. if (in_array('table', $tags)) { $tags = array_merge($tags, array('tr', 'td', 'th', 'colgroup', 'col', 'thead', 'tbody', 'tfoot', 'figure', 'figcaption')); } if (in_array('b', $tags) && ! in_array('strong', $tags)) { $tags[] = 'strong'; } if (in_array('i', $tags) && ! in_array('em', $tags)) { $tags[] = 'em'; } if (in_array('ul', $tags) || in_array('ol', $tags) && ! in_array('li', $tags)) { $tags[] = 'li'; } if (in_array('del', $tags) || in_array('strike', $tags) && ! in_array('s', $tags)) { $tags[] = 's'; } // Determine allowed style tags $stylePatterns = array(); // All styles must be start to end patterns (^...$) if (isset($semantics->font)) { if (isset($semantics->font->size) && $semantics->font->size) { $stylePatterns[] = '/^font-size: *[0-9.]+(em|px|%) *;?$/i'; } if (isset($semantics->font->family) && $semantics->font->family) { $stylePatterns[] = '/^font-family: *[-a-z0-9,\'&; ]+;?$/i'; } if (isset($semantics->font->color) && $semantics->font->color) { $stylePatterns[] = '/^color: *(#[a-f0-9]{3}[a-f0-9]{3}?|rgba?\([0-9, ]+\)|hsla?\([0-9,.% ]+\)) *;?$/i'; } if (isset($semantics->font->background) && $semantics->font->background) { $stylePatterns[] = '/^background-color: *(#[a-f0-9]{3}[a-f0-9]{3}?|rgba?\([0-9, ]+\)|hsla?\([0-9,.% ]+\)) *;?$/i'; } if (isset($semantics->font->spacing) && $semantics->font->spacing) { $stylePatterns[] = '/^letter-spacing: *[0-9.]+(em|px|%) *;?$/i'; } if (isset($semantics->font->height) && $semantics->font->height) { $stylePatterns[] = '/^line-height: *[0-9.]+(em|px|%|) *;?$/i'; } } // Allow styling of tables if they are allowed if (isset($semantics->tags) && in_array('table', $semantics->tags)) { // CKEditor outputs border as width style color $stylePatterns[] = '/^border: *[0-9.]+(em|px|%|) *(none|solid|dotted|dashed|double|groove|ridge|inset|outset) *(#[a-f0-9]{3}[a-f0-9]{3}?|rgba?\([0-9, ]+\)|hsla?\([0-9,.% ]+\)) *;?$/i'; $stylePatterns[] = '/^border-style: *(none|solid|dotted|dashed|double|groove|ridge|inset|outset) *;?$/i'; $stylePatterns[] = '/^border-width: *[0-9.]+(em|px|%|) *;?$/i'; $stylePatterns[] = '/^border-color: *(#[a-f0-9]{3}[a-f0-9]{3}?|rgba?\([0-9, ]+\)|hsla?\([0-9,.% ]+\)) *;?$/i'; $stylePatterns[] = '/^vertical-align: *(middle|top|bottom);?$/i'; $stylePatterns[] = '/^padding: *[0-9.]+(em|px|%|) *;?$/i'; $stylePatterns[] = '/^width: *[0-9.]+(em|px|%|) *;?$/i'; $stylePatterns[] = '/^height: *[0-9.]+(em|px|%|) *;?$/i'; $stylePatterns[] = '/^float: *(right|left|none) *;?$/i'; // Needed for backwards compatibility $stylePatterns[] = '/^border-collapse: *collapse *;?$/i'; // Table can have background color when font bgcolor is disabled // Double entry of bgcolor in stylePatterns shouldn't matter $stylePatterns[] = '/^background-color: *(#[a-f0-9]{3}[a-f0-9]{3}?|rgba?\([0-9, ]+\)|hsla?\([0-9,.% ]+\)) *;?$/i'; } // Alignment is allowed for all wysiwyg texts $stylePatterns[] = '/^text-align: *(center|left|right);?$/i'; // Strip invalid HTML tags. $text = $this->filter_xss($text, $tags, $stylePatterns); } else { // Filter text to plain text. $text = htmlspecialchars($text, ENT_QUOTES, 'UTF-8', FALSE); } // Check if string is within allowed length if (isset($semantics->maxLength)) { if (!extension_loaded('mbstring')) { $this->h5pF->setErrorMessage($this->h5pF->t('The mbstring PHP extension is not loaded. H5P need this to function properly'), 'mbstring-unsupported'); } else { $text = mb_substr($text, 0, $semantics->maxLength); } } // Check if string is according to optional regexp in semantics if (!($text === '' && isset($semantics->optional) && $semantics->optional) && isset($semantics->regexp)) { // Escaping '/' found in patterns, so that it does not break regexp fencing. $pattern = '/' . str_replace('/', '\\/', $semantics->regexp->pattern) . '/'; $pattern .= isset($semantics->regexp->modifiers) ? $semantics->regexp->modifiers : ''; if (preg_match($pattern, $text) === 0) { // Note: explicitly ignore return value FALSE, to avoid removing text // if regexp is invalid... $this->h5pF->setErrorMessage($this->h5pF->t('Provided string is not valid according to regexp in semantics. (value: "%value", regexp: "%regexp")', array('%value' => $text, '%regexp' => $pattern)), 'semantics-invalid-according-regexp'); $text = ''; } } } /** * Validates content files * * @param string $contentPath * The path containing content files to validate. * @param bool $isLibrary * @return bool TRUE if all files are valid * TRUE if all files are valid * FALSE if one or more files fail validation. Error message should be set accordingly by validator. */ public function validateContentFiles($contentPath, $isLibrary = FALSE) { if ($this->h5pC->disableFileCheck === TRUE) { return TRUE; } // Scan content directory for files, recurse into sub directories. $files = array_diff(scandir($contentPath), array('.','..')); $valid = TRUE; $whitelist = $this->h5pF->getWhitelist($isLibrary, H5PCore::$defaultContentWhitelist, H5PCore::$defaultLibraryWhitelistExtras); $wl_regex = '/\.(' . preg_replace('/ +/i', '|', preg_quote($whitelist)) . ')$/i'; foreach ($files as $file) { $filePath = $contentPath . '/' . $file; if (is_dir($filePath)) { $valid = $this->validateContentFiles($filePath, $isLibrary) && $valid; } else { // Snipped from drupal 6 "file_validate_extensions". Using own code // to avoid 1. creating a file-like object just to test for the known // file name, 2. testing against a returned error array that could // never be more than 1 element long anyway, 3. recreating the regex // for every file. if (!extension_loaded('mbstring')) { $this->h5pF->setErrorMessage($this->h5pF->t('The mbstring PHP extension is not loaded. H5P need this to function properly'), 'mbstring-unsupported'); $valid = FALSE; } else if (!preg_match($wl_regex, mb_strtolower($file))) { $this->h5pF->setErrorMessage($this->h5pF->t('File "%filename" not allowed. Only files with the following extensions are allowed: %files-allowed.', array('%filename' => $file, '%files-allowed' => $whitelist)), 'not-in-whitelist'); $valid = FALSE; } } } return $valid; } /** * Validate given value against number semantics * @param $number * @param $semantics */ public function validateNumber(&$number, $semantics) { // Validate that $number is indeed a number if (!is_numeric($number)) { $number = 0; } // Check if number is within valid bounds. Move within bounds if not. if (isset($semantics->min) && $number < $semantics->min) { $number = $semantics->min; } if (isset($semantics->max) && $number > $semantics->max) { $number = $semantics->max; } // Check if number is within allowed bounds even if step value is set. if (isset($semantics->step)) { $testNumber = $number - (isset($semantics->min) ? $semantics->min : 0); $rest = $testNumber % $semantics->step; if ($rest !== 0) { $number -= $rest; } } // Check if number has proper number of decimals. if (isset($semantics->decimals)) { $number = round($number, $semantics->decimals); } } /** * Validate given value against boolean semantics * @param $bool * @return bool */ public function validateBoolean(&$bool) { return is_bool($bool); } /** * Validate select values * @param $select * @param $semantics */ public function validateSelect(&$select, $semantics) { $optional = isset($semantics->optional) && $semantics->optional; $strict = FALSE; if (isset($semantics->options) && !empty($semantics->options)) { // We have a strict set of options to choose from. $strict = TRUE; $options = array(); foreach ($semantics->options as $option) { // Support optgroup - just flatten options into one if (isset($option->type) && $option->type === 'optgroup') { foreach ($option->options as $suboption) { $options[$suboption->value] = TRUE; } } elseif (isset($option->value)) { $options[$option->value] = TRUE; } } } if (isset($semantics->multiple) && $semantics->multiple) { // Multi-choice generates array of values. Test each one against valid // options, if we are strict. First make sure we are working on an // array. if (!is_array($select)) { $select = array($select); } foreach ($select as $key => &$value) { if ($strict && !$optional && !isset($options[$value])) { $this->h5pF->setErrorMessage($this->h5pF->t('Invalid selected option in multi-select.')); unset($select[$key]); } else { $select[$key] = htmlspecialchars($value, ENT_QUOTES, 'UTF-8', FALSE); } } } else { // Single mode. If we get an array in here, we chop off the first // element and use that instead. if (is_array($select)) { $select = $select[0]; } if ($strict && !$optional && !isset($options[$select])) { $this->h5pF->setErrorMessage($this->h5pF->t('Invalid selected option in select.')); $select = $semantics->options[0]->value; } $select = htmlspecialchars($select, ENT_QUOTES, 'UTF-8', FALSE); } } /** * Validate given list value against list semantics. * Will recurse into validating each item in the list according to the type. * @param $list * @param $semantics */ public function validateList(&$list, $semantics) { $field = $semantics->field; $function = $this->typeMap[$field->type]; // Check that list is not longer than allowed length. We do this before // iterating to avoid unnecessary work. if (isset($semantics->max)) { array_splice($list, $semantics->max); } if (!is_array($list)) { $list = array(); } // Validate each element in list. foreach ($list as $key => &$value) { if (!is_int($key)) { array_splice($list, $key, 1); continue; } $this->$function($value, $field); if ($value === NULL) { array_splice($list, $key, 1); } } if (count($list) === 0) { $list = NULL; } } /** * Validate a file like object, such as video, image, audio and file. * @param $file * @param $semantics * @param array $typeValidKeys */ private function _validateFilelike(&$file, $semantics, $typeValidKeys = array()) { // Do not allow to use files from other content folders. $matches = array(); if (preg_match($this->h5pC->relativePathRegExp, $file->path, $matches)) { $file->path = $matches[5]; } // Remove temporary files suffix if (substr($file->path, -4, 4) === '#tmp') { $file->path = substr($file->path, 0, strlen($file->path) - 4); } // Make sure path and mime does not have any special chars $file->path = htmlspecialchars($file->path, ENT_QUOTES, 'UTF-8', FALSE); if (isset($file->mime)) { $file->mime = htmlspecialchars($file->mime, ENT_QUOTES, 'UTF-8', FALSE); } // Remove attributes that should not exist, they may contain JSON escape // code. $validKeys = array_merge(array('path', 'mime', 'copyright'), $typeValidKeys); if (isset($semantics->extraAttributes)) { $validKeys = array_merge($validKeys, $semantics->extraAttributes); // TODO: Validate extraAttributes } $this->filterParams($file, $validKeys); if (isset($file->width)) { $file->width = intval($file->width); } if (isset($file->height)) { $file->height = intval($file->height); } if (isset($file->codecs)) { $file->codecs = htmlspecialchars($file->codecs, ENT_QUOTES, 'UTF-8', FALSE); } if (isset($file->bitrate)) { $file->bitrate = intval($file->bitrate); } if (isset($file->quality)) { if (!is_object($file->quality) || !isset($file->quality->level) || !isset($file->quality->label)) { unset($file->quality); } else { $this->filterParams($file->quality, array('level', 'label')); $file->quality->level = intval($file->quality->level); $file->quality->label = htmlspecialchars($file->quality->label, ENT_QUOTES, 'UTF-8', FALSE); } } if (isset($file->copyright)) { $this->validateGroup($file->copyright, $this->getCopyrightSemantics()); } } /** * Validate given file data * @param $file * @param $semantics */ public function validateFile(&$file, $semantics) { $this->_validateFilelike($file, $semantics); } /** * Validate given image data * @param $image * @param $semantics */ public function validateImage(&$image, $semantics) { $this->_validateFilelike($image, $semantics, array('width', 'height', 'originalImage')); } /** * Validate given video data * @param $video * @param $semantics */ public function validateVideo(&$video, $semantics) { foreach ($video as &$variant) { $this->_validateFilelike($variant, $semantics, array('width', 'height', 'codecs', 'quality', 'bitrate')); } } /** * Validate given audio data * @param $audio * @param $semantics */ public function validateAudio(&$audio, $semantics) { foreach ($audio as &$variant) { $this->_validateFilelike($variant, $semantics); } } /** * Validate given group value against group semantics. * Will recurse into validating each group member. * @param $group * @param $semantics * @param bool $flatten */ public function validateGroup(&$group, $semantics, $flatten = TRUE) { // Groups with just one field are compressed in the editor to only output // the child content. (Exemption for fake groups created by // "validateBySemantics" above) $function = null; $field = null; $isSubContent = isset($semantics->isSubContent) && $semantics->isSubContent === TRUE; if (count($semantics->fields) == 1 && $flatten && !$isSubContent) { $field = $semantics->fields[0]; $function = $this->typeMap[$field->type]; $this->$function($group, $field); } else { foreach ($group as $key => &$value) { // If subContentId is set, keep value if($isSubContent && ($key == 'subContentId')){ continue; } // Find semantics for name=$key $found = FALSE; foreach ($semantics->fields as $field) { if ($field->name == $key) { if (isset($semantics->optional) && $semantics->optional) { $field->optional = TRUE; } $function = $this->typeMap[$field->type]; $found = TRUE; break; } } if ($found) { if ($function) { $this->$function($value, $field); if ($value === NULL) { unset($group->$key); } } else { // We have a field type in semantics for which we don't have a // known validator. $this->h5pF->setErrorMessage($this->h5pF->t('H5P internal error: unknown content type "@type" in semantics. Removing content!', array('@type' => $field->type)), 'semantics-unknown-type'); unset($group->$key); } } else { // If validator is not found, something exists in content that does // not have a corresponding semantics field. Remove it. // $this->h5pF->setErrorMessage($this->h5pF->t('H5P internal error: no validator exists for @key', array('@key' => $key))); unset($group->$key); } } } } /** * Validate given library value against library semantics. * Check if provided library is within allowed options. * * Will recurse into validating the library's semantics too. * @param $value * @param $semantics */ public function validateLibrary(&$value, $semantics) { if (!isset($value->library)) { $value = NULL; return; } // Check for array of objects or array of strings if (is_object($semantics->options[0])) { $getLibraryNames = function ($item) { return $item->name; }; $libraryNames = array_map($getLibraryNames, $semantics->options); } else { $libraryNames = $semantics->options; } if (!in_array($value->library, $libraryNames)) { $message = NULL; // Create an understandable error message: $machineNameArray = explode(' ', $value->library); $machineName = $machineNameArray[0]; foreach ($libraryNames as $semanticsLibrary) { $semanticsMachineNameArray = explode(' ', $semanticsLibrary); $semanticsMachineName = $semanticsMachineNameArray[0]; if ($machineName === $semanticsMachineName) { // Using the wrong version of the library in the content $message = $this->h5pF->t('The version of the H5P library %machineName used in this content is not valid. Content contains %contentLibrary, but it should be %semanticsLibrary.', array( '%machineName' => $machineName, '%contentLibrary' => $value->library, '%semanticsLibrary' => $semanticsLibrary )); break; } } // Using a library in content that is not present at all in semantics if ($message === NULL) { $message = $this->h5pF->t('The H5P library %library used in the content is not valid', array( '%library' => $value->library )); } $this->h5pF->setErrorMessage($message); $value = NULL; return; } if (!isset($this->libraries[$value->library])) { $libSpec = H5PCore::libraryFromString($value->library); $library = $this->h5pC->loadLibrary($libSpec['machineName'], $libSpec['majorVersion'], $libSpec['minorVersion']); $library['semantics'] = $this->h5pC->loadLibrarySemantics($libSpec['machineName'], $libSpec['majorVersion'], $libSpec['minorVersion']); $this->libraries[$value->library] = $library; } else { $library = $this->libraries[$value->library]; } // Validate parameters $this->validateGroup($value->params, (object) array( 'type' => 'group', 'fields' => $library['semantics'], ), FALSE); // Validate subcontent's metadata if (isset($value->metadata)) { $value->metadata = $this->validateMetadata($value->metadata); } $validKeys = array('library', 'params', 'subContentId', 'metadata'); if (isset($semantics->extraAttributes)) { $validKeys = array_merge($validKeys, $semantics->extraAttributes); } $this->filterParams($value, $validKeys); if (isset($value->subContentId) && ! preg_match('/^\{?[a-f0-9]{8}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{4}-[a-f0-9]{12}\}?$/', $value->subContentId)) { unset($value->subContentId); } // Find all dependencies for this library $depKey = 'preloaded-' . $library['machineName']; if (!isset($this->dependencies[$depKey])) { $this->dependencies[$depKey] = array( 'library' => $library, 'type' => 'preloaded' ); $this->nextWeight = $this->h5pC->findLibraryDependencies($this->dependencies, $library, $this->nextWeight); $this->dependencies[$depKey]['weight'] = $this->nextWeight++; } } /** * Check params for a whitelist of allowed properties * * @param array/object $params * @param array $whitelist */ public function filterParams(&$params, $whitelist) { foreach ($params as $key => $value) { if (!in_array($key, $whitelist)) { unset($params->{$key}); } } } // XSS filters copied from drupal 7 common.inc. Some modifications done to // replace Drupal one-liner functions with corresponding flat PHP. /** * Filters HTML to prevent cross-site-scripting (XSS) vulnerabilities. * * Based on kses by Ulf Harnhammar, see http://sourceforge.net/projects/kses. * For examples of various XSS attacks, see: http://ha.ckers.org/xss.html. * * This code does four things: * - Removes characters and constructs that can trick browsers. * - Makes sure all HTML entities are well-formed. * - Makes sure all HTML tags and attributes are well-formed. * - Makes sure no HTML tags contain URLs with a disallowed protocol (e.g. * javascript:). * * @param $string * The string with raw HTML in it. It will be stripped of everything that can * cause an XSS attack. * @param array $allowed_tags * An array of allowed tags. * * @param bool $allowedStyles * @return mixed|string An XSS safe version of $string, or an empty string if $string is not * An XSS safe version of $string, or an empty string if $string is not * valid UTF-8. * @ingroup sanitation */ private function filter_xss($string, $allowed_tags = array('a', 'em', 'strong', 'cite', 'blockquote', 'code', 'ul', 'ol', 'li', 'dl', 'dt', 'dd'), $allowedStyles = FALSE) { if (strlen($string) == 0) { return $string; } // Only operate on valid UTF-8 strings. This is necessary to prevent cross // site scripting issues on Internet Explorer 6. (Line copied from // drupal_validate_utf8) if (preg_match('/^./us', $string) != 1) { return ''; } $this->allowedStyles = $allowedStyles; // Store the text format. $this->_filter_xss_split($allowed_tags, TRUE); // Remove NULL characters (ignored by some browsers). $string = str_replace(chr(0), '', $string); // Remove Netscape 4 JS entities. $string = preg_replace('%&\s*\{[^}]*(\}\s*;?|$)%', '', $string); // Defuse all HTML entities. $string = str_replace('&', '&', $string); // Change back only well-formed entities in our whitelist: // Decimal numeric entities. $string = preg_replace('/&#([0-9]+;)/', '&#\1', $string); // Hexadecimal numeric entities. $string = preg_replace('/&#[Xx]0*((?:[0-9A-Fa-f]{2})+;)/', '&#x\1', $string); // Named entities. $string = preg_replace('/&([A-Za-z][A-Za-z0-9]*;)/', '&\1', $string); return preg_replace_callback('% ( <(?=[^a-zA-Z!/]) # a lone < | # or # a comment | # or <[^>]*(>|$) # a string that starts with a <, up until the > or the end of the string | # or > # just a > )%x', array($this, '_filter_xss_split'), $string); } /** * Processes an HTML tag. * * @param $m * An array with various meaning depending on the value of $store. * If $store is TRUE then the array contains the allowed tags. * If $store is FALSE then the array has one element, the HTML tag to process. * @param bool $store * Whether to store $m. * @return string If the element isn't allowed, an empty string. Otherwise, the cleaned up * If the element isn't allowed, an empty string. Otherwise, the cleaned up * version of the HTML element. */ private function _filter_xss_split($m, $store = FALSE) { static $allowed_html; if ($store) { $allowed_html = array_flip($m); return $allowed_html; } $string = $m[1]; if (substr($string, 0, 1) != '<') { // We matched a lone ">" character. return '>'; } elseif (strlen($string) == 1) { // We matched a lone "<" character. return '<'; } if (!preg_match('%^<\s*(/\s*)?([a-zA-Z0-9\-]+)\s*([^>]*)>?|()$%', $string, $matches)) { // Seriously malformed. return ''; } $slash = trim($matches[1]); $elem = &$matches[2]; $attrList = &$matches[3]; $comment = &$matches[4]; if ($comment) { $elem = '!--'; } if (!isset($allowed_html[strtolower($elem)])) { // Disallowed HTML element. return ''; } if ($comment) { return $comment; } if ($slash != '') { return ""; } // Is there a closing XHTML slash at the end of the attributes? $attrList = preg_replace('%(\s?)/\s*$%', '\1', $attrList, -1, $count); $xhtml_slash = $count ? ' /' : ''; // Clean up attributes. $attr2 = implode(' ', $this->_filter_xss_attributes($attrList, (in_array($elem, self::$allowed_styleable_tags) ? $this->allowedStyles : FALSE))); $attr2 = preg_replace('/[<>]/', '', $attr2); $attr2 = strlen($attr2) ? ' ' . $attr2 : ''; return "<$elem$attr2$xhtml_slash>"; } /** * Processes a string of HTML attributes. * * @param $attr * @param array|bool|object $allowedStyles * @return array Cleaned up version of the HTML attributes. * Cleaned up version of the HTML attributes. */ private function _filter_xss_attributes($attr, $allowedStyles = FALSE) { $attrArr = array(); $mode = 0; $attrName = ''; $skip = false; while (strlen($attr) != 0) { // Was the last operation successful? $working = 0; switch ($mode) { case 0: // Attribute name, href for instance. if (preg_match('/^([-a-zA-Z]+)/', $attr, $match)) { $attrName = strtolower($match[1]); $skip = ( $attrName == 'style' || substr($attrName, 0, 2) == 'on' || substr($attrName, 0, 1) == '-' || // Ignore long attributes to avoid unnecessary processing overhead. strlen($attrName) > 96 ); $working = $mode = 1; $attr = preg_replace('/^[-a-zA-Z]+/', '', $attr); } break; case 1: // Equals sign or valueless ("selected"). if (preg_match('/^\s*=\s*/', $attr)) { $working = 1; $mode = 2; $attr = preg_replace('/^\s*=\s*/', '', $attr); break; } if (preg_match('/^\s+/', $attr)) { $working = 1; $mode = 0; if (!$skip) { $attrArr[] = $attrName; } $attr = preg_replace('/^\s+/', '', $attr); } break; case 2: // Attribute value, a URL after href= for instance. if (preg_match('/^"([^"]*)"(\s+|$)/', $attr, $match)) { if ($allowedStyles && $attrName === 'style') { // Allow certain styles // Prevent font family from getting split wrong because of the ; in " if (str_contains($match[1], 'font-family')) { $match[1] = str_replace('"', "'", $match[1]); } $validatedStyles = []; $styles = explode(';', $match[1]); foreach ($allowedStyles as $pattern) { foreach ($styles as $style) { $style = trim($style); if (preg_match($pattern, $style)) { $validatedStyles[] = $style; } } } $attrArr[] = 'style="' . implode(';', $validatedStyles) . ';"'; break; } $thisVal = $this->filter_xss_bad_protocol($match[1]); if (!$skip) { $attrArr[] = "$attrName=\"$thisVal\""; } $working = 1; $mode = 0; $attr = preg_replace('/^"[^"]*"(\s+|$)/', '', $attr); break; } if (preg_match("/^'([^']*)'(\s+|$)/", $attr, $match)) { $thisVal = $this->filter_xss_bad_protocol($match[1]); if (!$skip) { $attrArr[] = "$attrName='$thisVal'"; } $working = 1; $mode = 0; $attr = preg_replace("/^'[^']*'(\s+|$)/", '', $attr); break; } if (preg_match("%^([^\s\"']+)(\s+|$)%", $attr, $match)) { $thisVal = $this->filter_xss_bad_protocol($match[1]); if (!$skip) { $attrArr[] = "$attrName=\"$thisVal\""; } $working = 1; $mode = 0; $attr = preg_replace("%^[^\s\"']+(\s+|$)%", '', $attr); } break; } if ($working == 0) { // Not well formed; remove and try again. $attr = preg_replace('/ ^ ( "[^"]*("|$) # - a string that starts with a double quote, up until the next double quote or the end of the string | # or \'[^\']*(\'|$)| # - a string that starts with a quote, up until the next quote or the end of the string | # or \S # - a non-whitespace character )* # any number of the above three \s* # any number of whitespaces /x', '', $attr); $mode = 0; } } // The attribute list ends with a valueless attribute like "selected". if ($mode == 1 && !$skip) { $attrArr[] = $attrName; } return $attrArr; } // TODO: Remove Drupal related stuff in docs. /** * Processes an HTML attribute value and strips dangerous protocols from URLs. * * @param $string * The string with the attribute value. * @param bool $decode * (deprecated) Whether to decode entities in the $string. Set to FALSE if the * $string is in plain text, TRUE otherwise. Defaults to TRUE. This parameter * is deprecated and will be removed in Drupal 8. To process a plain-text URI, * call _strip_dangerous_protocols() or check_url() instead. * @return string Cleaned up and HTML-escaped version of $string. * Cleaned up and HTML-escaped version of $string. */ private function filter_xss_bad_protocol($string, $decode = TRUE) { // Get the plain text representation of the attribute value (i.e. its meaning). // @todo Remove the $decode parameter in Drupal 8, and always assume an HTML // string that needs decoding. if ($decode) { $string = html_entity_decode($string, ENT_QUOTES, 'UTF-8'); } return htmlspecialchars($this->_strip_dangerous_protocols($string), ENT_QUOTES, 'UTF-8', FALSE); } /** * Strips dangerous protocols (e.g. 'javascript:') from a URI. * * This function must be called for all URIs within user-entered input prior * to being output to an HTML attribute value. It is often called as part of * check_url() or filter_xss(), but those functions return an HTML-encoded * string, so this function can be called independently when the output needs to * be a plain-text string for passing to t(), l(), drupal_attributes(), or * another function that will call check_plain() separately. * * @param $uri * A plain-text URI that might contain dangerous protocols. * @return string A plain-text URI stripped of dangerous protocols. As with all plain-text * A plain-text URI stripped of dangerous protocols. As with all plain-text * strings, this return value must not be output to an HTML page without * check_plain() being called on it. However, it can be passed to functions * expecting plain-text strings. * @see check_url() */ private function _strip_dangerous_protocols($uri) { static $allowed_protocols; if (!isset($allowed_protocols)) { $allowed_protocols = array_flip(array('ftp', 'http', 'https', 'mailto')); } // Iteratively remove any invalid protocol found. do { $before = $uri; $colonPos = strpos($uri, ':'); if ($colonPos > 0) { // We found a colon, possibly a protocol. Verify. $protocol = substr($uri, 0, $colonPos); // If a colon is preceded by a slash, question mark or hash, it cannot // possibly be part of the URL scheme. This must be a relative URL, which // inherits the (safe) protocol of the base document. if (preg_match('![/?#]!', $protocol)) { break; } // Check if this is a disallowed protocol. Per RFC2616, section 3.2.3 // (URI Comparison) scheme comparison must be case-insensitive. if (!isset($allowed_protocols[strtolower($protocol)])) { $uri = substr($uri, $colonPos + 1); } } } while ($before != $uri); return $uri; } public function getMetadataSemantics() { static $semantics; $cc_versions = array( (object) array( 'value' => '4.0', 'label' => $this->h5pF->t('4.0 International') ), (object) array( 'value' => '3.0', 'label' => $this->h5pF->t('3.0 Unported') ), (object) array( 'value' => '2.5', 'label' => $this->h5pF->t('2.5 Generic') ), (object) array( 'value' => '2.0', 'label' => $this->h5pF->t('2.0 Generic') ), (object) array( 'value' => '1.0', 'label' => $this->h5pF->t('1.0 Generic') ) ); $semantics = array( (object) array( 'name' => 'title', 'type' => 'text', 'label' => $this->h5pF->t('Title'), 'placeholder' => 'La Gioconda' ), (object) array( 'name' => 'a11yTitle', 'type' => 'text', 'label' => $this->h5pF->t('Assistive Technologies label'), 'optional' => TRUE, ), (object) array( 'name' => 'license', 'type' => 'select', 'label' => $this->h5pF->t('License'), 'default' => 'U', 'options' => array( (object) array( 'value' => 'U', 'label' => $this->h5pF->t('Undisclosed') ), (object) array( 'type' => 'optgroup', 'label' => $this->h5pF->t('Creative Commons'), 'options' => array( (object) array( 'value' => 'CC BY', 'label' => $this->h5pF->t('Attribution (CC BY)'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-SA', 'label' => $this->h5pF->t('Attribution-ShareAlike (CC BY-SA)'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-ND', 'label' => $this->h5pF->t('Attribution-NoDerivs (CC BY-ND)'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-NC', 'label' => $this->h5pF->t('Attribution-NonCommercial (CC BY-NC)'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-NC-SA', 'label' => $this->h5pF->t('Attribution-NonCommercial-ShareAlike (CC BY-NC-SA)'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-NC-ND', 'label' => $this->h5pF->t('Attribution-NonCommercial-NoDerivs (CC BY-NC-ND)'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC0 1.0', 'label' => $this->h5pF->t('Public Domain Dedication (CC0)') ), (object) array( 'value' => 'CC PDM', 'label' => $this->h5pF->t('Public Domain Mark (PDM)') ), ) ), (object) array( 'value' => 'GNU GPL', 'label' => $this->h5pF->t('General Public License v3') ), (object) array( 'value' => 'PD', 'label' => $this->h5pF->t('Public Domain') ), (object) array( 'value' => 'ODC PDDL', 'label' => $this->h5pF->t('Public Domain Dedication and Licence') ), (object) array( 'value' => 'C', 'label' => $this->h5pF->t('Copyright') ) ) ), (object) array( 'name' => 'licenseVersion', 'type' => 'select', 'label' => $this->h5pF->t('License Version'), 'options' => $cc_versions, 'optional' => TRUE ), (object) array( 'name' => 'yearFrom', 'type' => 'number', 'label' => $this->h5pF->t('Years (from)'), 'placeholder' => '1991', 'min' => '-9999', 'max' => '9999', 'optional' => TRUE ), (object) array( 'name' => 'yearTo', 'type' => 'number', 'label' => $this->h5pF->t('Years (to)'), 'placeholder' => '1992', 'min' => '-9999', 'max' => '9999', 'optional' => TRUE ), (object) array( 'name' => 'source', 'type' => 'text', 'label' => $this->h5pF->t('Source'), 'placeholder' => 'https://', 'optional' => TRUE ), (object) array( 'name' => 'authors', 'type' => 'list', 'field' => (object) array ( 'name' => 'author', 'type' => 'group', 'fields'=> array( (object) array( 'label' => $this->h5pF->t("Author's name"), 'name' => 'name', 'optional' => TRUE, 'type' => 'text' ), (object) array( 'name' => 'role', 'type' => 'select', 'label' => $this->h5pF->t("Author's role"), 'default' => 'Author', 'options' => array( (object) array( 'value' => 'Author', 'label' => $this->h5pF->t('Author') ), (object) array( 'value' => 'Editor', 'label' => $this->h5pF->t('Editor') ), (object) array( 'value' => 'Licensee', 'label' => $this->h5pF->t('Licensee') ), (object) array( 'value' => 'Originator', 'label' => $this->h5pF->t('Originator') ) ) ) ) ) ), (object) array( 'name' => 'licenseExtras', 'type' => 'text', 'widget' => 'textarea', 'label' => $this->h5pF->t('License Extras'), 'optional' => TRUE, 'description' => $this->h5pF->t('Any additional information about the license') ), (object) array( 'name' => 'changes', 'type' => 'list', 'field' => (object) array( 'name' => 'change', 'type' => 'group', 'label' => $this->h5pF->t('Changelog'), 'fields' => array( (object) array( 'name' => 'date', 'type' => 'text', 'label' => $this->h5pF->t('Date'), 'optional' => TRUE ), (object) array( 'name' => 'author', 'type' => 'text', 'label' => $this->h5pF->t('Changed by'), 'optional' => TRUE ), (object) array( 'name' => 'log', 'type' => 'text', 'widget' => 'textarea', 'label' => $this->h5pF->t('Description of change'), 'placeholder' => $this->h5pF->t('Photo cropped, text changed, etc.'), 'optional' => TRUE ) ) ) ), (object) array ( 'name' => 'authorComments', 'type' => 'text', 'widget' => 'textarea', 'label' => $this->h5pF->t('Author comments'), 'description' => $this->h5pF->t('Comments for the editor of the content (This text will not be published as a part of copyright info)'), 'optional' => TRUE ), (object) array( 'name' => 'contentType', 'type' => 'text', 'widget' => 'none' ), (object) array( 'name' => 'defaultLanguage', 'type' => 'text', 'widget' => 'none' ) ); return $semantics; } public function getCopyrightSemantics() { static $semantics; if ($semantics === NULL) { $cc_versions = array( (object) array( 'value' => '4.0', 'label' => $this->h5pF->t('4.0 International') ), (object) array( 'value' => '3.0', 'label' => $this->h5pF->t('3.0 Unported') ), (object) array( 'value' => '2.5', 'label' => $this->h5pF->t('2.5 Generic') ), (object) array( 'value' => '2.0', 'label' => $this->h5pF->t('2.0 Generic') ), (object) array( 'value' => '1.0', 'label' => $this->h5pF->t('1.0 Generic') ) ); $semantics = (object) array( 'name' => 'copyright', 'type' => 'group', 'label' => $this->h5pF->t('Copyright information'), 'fields' => array( (object) array( 'name' => 'title', 'type' => 'text', 'label' => $this->h5pF->t('Title'), 'placeholder' => 'La Gioconda', 'optional' => TRUE ), (object) array( 'name' => 'author', 'type' => 'text', 'label' => $this->h5pF->t('Author'), 'placeholder' => 'Leonardo da Vinci', 'optional' => TRUE ), (object) array( 'name' => 'year', 'type' => 'text', 'label' => $this->h5pF->t('Year(s)'), 'placeholder' => '1503 - 1517', 'optional' => TRUE ), (object) array( 'name' => 'source', 'type' => 'text', 'label' => $this->h5pF->t('Source'), 'placeholder' => 'http://en.wikipedia.org/wiki/Mona_Lisa', 'optional' => true, 'regexp' => (object) array( 'pattern' => '^http[s]?://.+', 'modifiers' => 'i' ) ), (object) array( 'name' => 'license', 'type' => 'select', 'label' => $this->h5pF->t('License'), 'default' => 'U', 'options' => array( (object) array( 'value' => 'U', 'label' => $this->h5pF->t('Undisclosed') ), (object) array( 'value' => 'CC BY', 'label' => $this->h5pF->t('Attribution'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-SA', 'label' => $this->h5pF->t('Attribution-ShareAlike'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-ND', 'label' => $this->h5pF->t('Attribution-NoDerivs'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-NC', 'label' => $this->h5pF->t('Attribution-NonCommercial'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-NC-SA', 'label' => $this->h5pF->t('Attribution-NonCommercial-ShareAlike'), 'versions' => $cc_versions ), (object) array( 'value' => 'CC BY-NC-ND', 'label' => $this->h5pF->t('Attribution-NonCommercial-NoDerivs'), 'versions' => $cc_versions ), (object) array( 'value' => 'GNU GPL', 'label' => $this->h5pF->t('General Public License'), 'versions' => array( (object) array( 'value' => 'v3', 'label' => $this->h5pF->t('Version 3') ), (object) array( 'value' => 'v2', 'label' => $this->h5pF->t('Version 2') ), (object) array( 'value' => 'v1', 'label' => $this->h5pF->t('Version 1') ) ) ), (object) array( 'value' => 'PD', 'label' => $this->h5pF->t('Public Domain'), 'versions' => array( (object) array( 'value' => '-', 'label' => '-' ), (object) array( 'value' => 'CC0 1.0', 'label' => $this->h5pF->t('CC0 1.0 Universal') ), (object) array( 'value' => 'CC PDM', 'label' => $this->h5pF->t('Public Domain Mark') ) ) ), (object) array( 'value' => 'C', 'label' => $this->h5pF->t('Copyright') ) ) ), (object) array( 'name' => 'version', 'type' => 'select', 'label' => $this->h5pF->t('License Version'), 'options' => array() ) ) ); } return $semantics; } } PK*\7[G]]0h5plib/v127/joubel/core/h5p-event-base.class.phpnu[ – content view * embed – viewed through embed code * shortcode – viewed through internal shortcode * edit – opened in editor * delete – deleted * create – created through editor * create upload – created through upload * update – updated through editor * update upload – updated through upload * upgrade – upgraded * * results, – view own results * content – view results for content * set – new results inserted or updated * * settings, – settings page loaded * * library, – loaded in editor * create – new library installed * update – old library updated * * @param string $type * Name of event type * @param string $sub_type * Name of event sub type * @param string $content_id * Identifier for content affected by the event * @param string $content_title * Content title (makes it easier to know which content was deleted etc.) * @param string $library_name * Name of the library affected by the event * @param string $library_version * Library version */ function __construct($type, $sub_type = NULL, $content_id = NULL, $content_title = NULL, $library_name = NULL, $library_version = NULL) { $this->type = $type; $this->sub_type = $sub_type; $this->content_id = $content_id; $this->content_title = $content_title; $this->library_name = $library_name; $this->library_version = $library_version; $this->time = time(); if (self::validLogLevel($type, $sub_type)) { $this->save(); } if (self::validStats($type, $sub_type)) { $this->saveStats(); } } /** * Determines if the event type should be saved/logged. * * @param string $type * Name of event type * @param string $sub_type * Name of event sub type * @return boolean */ private static function validLogLevel($type, $sub_type) { switch (self::$log_level) { default: case self::LOG_NONE: return FALSE; case self::LOG_ALL: return TRUE; // Log everything case self::LOG_ACTIONS: if (self::isAction($type, $sub_type)) { return TRUE; // Log actions } return FALSE; } } /** * Check if the event should be included in the statistics counter. * * @param string $type * Name of event type * @param string $sub_type * Name of event sub type * @return boolean */ private static function validStats($type, $sub_type) { if ( ($type === 'content' && $sub_type === 'shortcode insert') || // Count number of shortcode inserts ($type === 'library' && $sub_type === NULL) || // Count number of times library is loaded in editor ($type === 'results' && $sub_type === 'content') ) { // Count number of times results page has been opened return TRUE; } elseif (self::isAction($type, $sub_type)) { // Count all actions return TRUE; } return FALSE; } /** * Check if event type is an action. * * @param string $type * Name of event type * @param string $sub_type * Name of event sub type * @return boolean */ private static function isAction($type, $sub_type) { if ( ($type === 'content' && in_array($sub_type, array('create', 'create upload', 'update', 'update upload', 'upgrade', 'delete'))) || ($type === 'library' && in_array($sub_type, array('create', 'update'))) ) { return TRUE; // Log actions } return FALSE; } /** * A helper which makes it easier for systems to save the data. * Add all relevant properties to a assoc. array. * There are no NULL values. Empty string or 0 is used instead. * Used by both Drupal and WordPress. * * @return array with keyed values */ protected function getDataArray() { return array( 'created_at' => $this->time, 'type' => $this->type, 'sub_type' => empty($this->sub_type) ? '' : $this->sub_type, 'content_id' => empty($this->content_id) ? 0 : $this->content_id, 'content_title' => empty($this->content_title) ? '' : $this->content_title, 'library_name' => empty($this->library_name) ? '' : $this->library_name, 'library_version' => empty($this->library_version) ? '' : $this->library_version ); } /** * A helper which makes it easier for systems to save the data. * Used in WordPress. * * @return array with strings */ protected function getFormatArray() { return array( '%d', '%s', '%s', '%d', '%s', '%s', '%s' ); } /** * Stores the event data in the database. * * Must be overridden by plugin. */ abstract protected function save(); /** * Add current event data to statistics counter. * * Must be overridden by plugin. */ abstract protected function saveStats(); } PK*\Ƥ~JJ#h5plib/v127/joubel/core/LICENSE.txtnu[ GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007 Copyright (C) 2007 Free Software Foundation, Inc. Everyone is permitted to copy and distribute verbatim copies of this license document, but changing it is not allowed. Preamble The GNU General Public License is a free, copyleft license for software and other kinds of works. The licenses for most software and other practical works are designed to take away your freedom to share and change the works. By contrast, the GNU General Public License is intended to guarantee your freedom to share and change all versions of a program--to make sure it remains free software for all its users. We, the Free Software Foundation, use the GNU General Public License for most of our software; it applies also to any other work released this way by its authors. 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 them 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 prevent others from denying you these rights or asking you to surrender the rights. Therefore, you have certain responsibilities if you distribute copies of the software, or if you modify it: responsibilities to respect the freedom of others. For example, if you distribute copies of such a program, whether gratis or for a fee, you must pass on to the recipients the same freedoms that you received. 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. Developers that use the GNU GPL protect your rights with two steps: (1) assert copyright on the software, and (2) offer you this License giving you legal permission to copy, distribute and/or modify it. For the developers' and authors' protection, the GPL clearly explains that there is no warranty for this free software. For both users' and authors' sake, the GPL requires that modified versions be marked as changed, so that their problems will not be attributed erroneously to authors of previous versions. Some devices are designed to deny users access to install or run modified versions of the software inside them, although the manufacturer can do so. This is fundamentally incompatible with the aim of protecting users' freedom to change the software. The systematic pattern of such abuse occurs in the area of products for individuals to use, which is precisely where it is most unacceptable. Therefore, we have designed this version of the GPL to prohibit the practice for those products. If such problems arise substantially in other domains, we stand ready to extend this provision to those domains in future versions of the GPL, as needed to protect the freedom of users. Finally, every program is threatened constantly by software patents. States should not allow patents to restrict development and use of software on general-purpose computers, but in those that do, we wish to avoid the special danger that patents applied to a free program could make it effectively proprietary. To prevent this, the GPL assures that patents cannot be used to render the program non-free. The precise terms and conditions for copying, distribution and modification follow. TERMS AND CONDITIONS 0. Definitions. "This License" refers to version 3 of the GNU General Public License. "Copyright" also means copyright-like laws that apply to other kinds of works, such as semiconductor masks. "The Program" refers to any copyrightable work licensed under this License. Each licensee is addressed as "you". "Licensees" and "recipients" may be individuals or organizations. To "modify" a work means to copy from or adapt all or part of the work in a fashion requiring copyright permission, other than the making of an exact copy. The resulting work is called a "modified version" of the earlier work or a work "based on" the earlier work. A "covered work" means either the unmodified Program or a work based on the Program. To "propagate" a work means to do anything with it that, without permission, would make you directly or secondarily liable for infringement under applicable copyright law, except executing it on a computer or modifying a private copy. Propagation includes copying, distribution (with or without modification), making available to the public, and in some countries other activities as well. To "convey" a work means any kind of propagation that enables other parties to make or receive copies. Mere interaction with a user through a computer network, with no transfer of a copy, is not conveying. An interactive user interface displays "Appropriate Legal Notices" to the extent that it includes a convenient and prominently visible feature that (1) displays an appropriate copyright notice, and (2) tells the user that there is no warranty for the work (except to the extent that warranties are provided), that licensees may convey the work under this License, and how to view a copy of this License. If the interface presents a list of user commands or options, such as a menu, a prominent item in the list meets this criterion. 1. Source Code. The "source code" for a work means the preferred form of the work for making modifications to it. "Object code" means any non-source form of a work. A "Standard Interface" means an interface that either is an official standard defined by a recognized standards body, or, in the case of interfaces specified for a particular programming language, one that is widely used among developers working in that language. The "System Libraries" of an executable work include anything, other than the work as a whole, that (a) is included in the normal form of packaging a Major Component, but which is not part of that Major Component, and (b) serves only to enable use of the work with that Major Component, or to implement a Standard Interface for which an implementation is available to the public in source code form. A "Major Component", in this context, means a major essential component (kernel, window system, and so on) of the specific operating system (if any) on which the executable work runs, or a compiler used to produce the work, or an object code interpreter used to run it. The "Corresponding Source" for a work in object code form means all the source code needed to generate, install, and (for an executable work) run the object code and to modify the work, including scripts to control those activities. However, it does not include the work's System Libraries, or general-purpose tools or generally available free programs which are used unmodified in performing those activities but which are not part of the work. For example, Corresponding Source includes interface definition files associated with source files for the work, and the source code for shared libraries and dynamically linked subprograms that the work is specifically designed to require, such as by intimate data communication or control flow between those subprograms and other parts of the work. The Corresponding Source need not include anything that users can regenerate automatically from other parts of the Corresponding Source. The Corresponding Source for a work in source code form is that same work. 2. Basic Permissions. All rights granted under this License are granted for the term of copyright on the Program, and are irrevocable provided the stated conditions are met. This License explicitly affirms your unlimited permission to run the unmodified Program. The output from running a covered work is covered by this License only if the output, given its content, constitutes a covered work. This License acknowledges your rights of fair use or other equivalent, as provided by copyright law. You may make, run and propagate covered works that you do not convey, without conditions so long as your license otherwise remains in force. You may convey covered works to others for the sole purpose of having them make modifications exclusively for you, or provide you with facilities for running those works, provided that you comply with the terms of this License in conveying all material for which you do not control copyright. Those thus making or running the covered works for you must do so exclusively on your behalf, under your direction and control, on terms that prohibit them from making any copies of your copyrighted material outside their relationship with you. Conveying under any other circumstances is permitted solely under the conditions stated below. Sublicensing is not allowed; section 10 makes it unnecessary. 3. Protecting Users' Legal Rights From Anti-Circumvention Law. No covered work shall be deemed part of an effective technological measure under any applicable law fulfilling obligations under article 11 of the WIPO copyright treaty adopted on 20 December 1996, or similar laws prohibiting or restricting circumvention of such measures. When you convey a covered work, you waive any legal power to forbid circumvention of technological measures to the extent such circumvention is effected by exercising rights under this License with respect to the covered work, and you disclaim any intention to limit operation or modification of the work as a means of enforcing, against the work's users, your or third parties' legal rights to forbid circumvention of technological measures. 4. Conveying Verbatim Copies. You may convey 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; keep intact all notices stating that this License and any non-permissive terms added in accord with section 7 apply to the code; keep intact all notices of the absence of any warranty; and give all recipients a copy of this License along with the Program. You may charge any price or no price for each copy that you convey, and you may offer support or warranty protection for a fee. 5. Conveying Modified Source Versions. You may convey a work based on the Program, or the modifications to produce it from the Program, in the form of source code under the terms of section 4, provided that you also meet all of these conditions: a) The work must carry prominent notices stating that you modified it, and giving a relevant date. b) The work must carry prominent notices stating that it is released under this License and any conditions added under section 7. This requirement modifies the requirement in section 4 to "keep intact all notices". c) You must license the entire work, as a whole, under this License to anyone who comes into possession of a copy. This License will therefore apply, along with any applicable section 7 additional terms, to the whole of the work, and all its parts, regardless of how they are packaged. This License gives no permission to license the work in any other way, but it does not invalidate such permission if you have separately received it. d) If the work has interactive user interfaces, each must display Appropriate Legal Notices; however, if the Program has interactive interfaces that do not display Appropriate Legal Notices, your work need not make them do so. A compilation of a covered work with other separate and independent works, which are not by their nature extensions of the covered work, and which are not combined with it such as to form a larger program, in or on a volume of a storage or distribution medium, is called an "aggregate" if the compilation and its resulting copyright are not used to limit the access or legal rights of the compilation's users beyond what the individual works permit. Inclusion of a covered work in an aggregate does not cause this License to apply to the other parts of the aggregate. 6. Conveying Non-Source Forms. You may convey a covered work in object code form under the terms of sections 4 and 5, provided that you also convey the machine-readable Corresponding Source under the terms of this License, in one of these ways: a) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by the Corresponding Source fixed on a durable physical medium customarily used for software interchange. b) Convey the object code in, or embodied in, a physical product (including a physical distribution medium), accompanied by a written offer, valid for at least three years and valid for as long as you offer spare parts or customer support for that product model, to give anyone who possesses the object code either (1) a copy of the Corresponding Source for all the software in the product that is covered by this License, on a durable physical medium customarily used for software interchange, for a price no more than your reasonable cost of physically performing this conveying of source, or (2) access to copy the Corresponding Source from a network server at no charge. c) Convey individual copies of the object code with a copy of the written offer to provide the Corresponding Source. This alternative is allowed only occasionally and noncommercially, and only if you received the object code with such an offer, in accord with subsection 6b. d) Convey the object code by offering access from a designated place (gratis or for a charge), and offer equivalent access to the Corresponding Source in the same way through the same place at no further charge. You need not require recipients to copy the Corresponding Source along with the object code. If the place to copy the object code is a network server, the Corresponding Source may be on a different server (operated by you or a third party) that supports equivalent copying facilities, provided you maintain clear directions next to the object code saying where to find the Corresponding Source. Regardless of what server hosts the Corresponding Source, you remain obligated to ensure that it is available for as long as needed to satisfy these requirements. e) Convey the object code using peer-to-peer transmission, provided you inform other peers where the object code and Corresponding Source of the work are being offered to the general public at no charge under subsection 6d. A separable portion of the object code, whose source code is excluded from the Corresponding Source as a System Library, need not be included in conveying the object code work. A "User Product" is either (1) a "consumer product", which means any tangible personal property which is normally used for personal, family, or household purposes, or (2) anything designed or sold for incorporation into a dwelling. In determining whether a product is a consumer product, doubtful cases shall be resolved in favor of coverage. For a particular product received by a particular user, "normally used" refers to a typical or common use of that class of product, regardless of the status of the particular user or of the way in which the particular user actually uses, or expects or is expected to use, the product. A product is a consumer product regardless of whether the product has substantial commercial, industrial or non-consumer uses, unless such uses represent the only significant mode of use of the product. "Installation Information" for a User Product means any methods, procedures, authorization keys, or other information required to install and execute modified versions of a covered work in that User Product from a modified version of its Corresponding Source. The information must suffice to ensure that the continued functioning of the modified object code is in no case prevented or interfered with solely because modification has been made. If you convey an object code work under this section in, or with, or specifically for use in, a User Product, and the conveying occurs as part of a transaction in which the right of possession and use of the User Product is transferred to the recipient in perpetuity or for a fixed term (regardless of how the transaction is characterized), the Corresponding Source conveyed under this section must be accompanied by the Installation Information. But this requirement does not apply if neither you nor any third party retains the ability to install modified object code on the User Product (for example, the work has been installed in ROM). The requirement to provide Installation Information does not include a requirement to continue to provide support service, warranty, or updates for a work that has been modified or installed by the recipient, or for the User Product in which it has been modified or installed. Access to a network may be denied when the modification itself materially and adversely affects the operation of the network or violates the rules and protocols for communication across the network. Corresponding Source conveyed, and Installation Information provided, in accord with this section must be in a format that is publicly documented (and with an implementation available to the public in source code form), and must require no special password or key for unpacking, reading or copying. 7. Additional Terms. "Additional permissions" are terms that supplement the terms of this License by making exceptions from one or more of its conditions. Additional permissions that are applicable to the entire Program shall be treated as though they were included in this License, to the extent that they are valid under applicable law. If additional permissions apply only to part of the Program, that part may be used separately under those permissions, but the entire Program remains governed by this License without regard to the additional permissions. When you convey a copy of a covered work, you may at your option remove any additional permissions from that copy, or from any part of it. (Additional permissions may be written to require their own removal in certain cases when you modify the work.) You may place additional permissions on material, added by you to a covered work, for which you have or can give appropriate copyright permission. Notwithstanding any other provision of this License, for material you add to a covered work, you may (if authorized by the copyright holders of that material) supplement the terms of this License with terms: a) Disclaiming warranty or limiting liability differently from the terms of sections 15 and 16 of this License; or b) Requiring preservation of specified reasonable legal notices or author attributions in that material or in the Appropriate Legal Notices displayed by works containing it; or c) Prohibiting misrepresentation of the origin of that material, or requiring that modified versions of such material be marked in reasonable ways as different from the original version; or d) Limiting the use for publicity purposes of names of licensors or authors of the material; or e) Declining to grant rights under trademark law for use of some trade names, trademarks, or service marks; or f) Requiring indemnification of licensors and authors of that material by anyone who conveys the material (or modified versions of it) with contractual assumptions of liability to the recipient, for any liability that these contractual assumptions directly impose on those licensors and authors. All other non-permissive additional terms are considered "further restrictions" within the meaning of section 10. If the Program as you received it, or any part of it, contains a notice stating that it is governed by this License along with a term that is a further restriction, you may remove that term. If a license document contains a further restriction but permits relicensing or conveying under this License, you may add to a covered work material governed by the terms of that license document, provided that the further restriction does not survive such relicensing or conveying. If you add terms to a covered work in accord with this section, you must place, in the relevant source files, a statement of the additional terms that apply to those files, or a notice indicating where to find the applicable terms. Additional terms, permissive or non-permissive, may be stated in the form of a separately written license, or stated as exceptions; the above requirements apply either way. 8. Termination. You may not propagate or modify a covered work except as expressly provided under this License. Any attempt otherwise to propagate or modify it is void, and will automatically terminate your rights under this License (including any patent licenses granted under the third paragraph of section 11). However, if you cease all violation of this License, then your license from a particular copyright holder is reinstated (a) provisionally, unless and until the copyright holder explicitly and finally terminates your license, and (b) permanently, if the copyright holder fails to notify you of the violation by some reasonable means prior to 60 days after the cessation. Moreover, your license from a particular copyright holder is reinstated permanently if the copyright holder notifies you of the violation by some reasonable means, this is the first time you have received notice of violation of this License (for any work) from that copyright holder, and you cure the violation prior to 30 days after your receipt of the notice. Termination of your rights under this section does not terminate the licenses of parties who have received copies or rights from you under this License. If your rights have been terminated and not permanently reinstated, you do not qualify to receive new licenses for the same material under section 10. 9. Acceptance Not Required for Having Copies. You are not required to accept this License in order to receive or run a copy of the Program. Ancillary propagation of a covered work occurring solely as a consequence of using peer-to-peer transmission to receive a copy likewise does not require acceptance. However, nothing other than this License grants you permission to propagate or modify any covered work. These actions infringe copyright if you do not accept this License. Therefore, by modifying or propagating a covered work, you indicate your acceptance of this License to do so. 10. Automatic Licensing of Downstream Recipients. Each time you convey a covered work, the recipient automatically receives a license from the original licensors, to run, modify and propagate that work, subject to this License. You are not responsible for enforcing compliance by third parties with this License. An "entity transaction" is a transaction transferring control of an organization, or substantially all assets of one, or subdividing an organization, or merging organizations. If propagation of a covered work results from an entity transaction, each party to that transaction who receives a copy of the work also receives whatever licenses to the work the party's predecessor in interest had or could give under the previous paragraph, plus a right to possession of the Corresponding Source of the work from the predecessor in interest, if the predecessor has it or can get it with reasonable efforts. You may not impose any further restrictions on the exercise of the rights granted or affirmed under this License. For example, you may not impose a license fee, royalty, or other charge for exercise of rights granted under this License, and you may not initiate litigation (including a cross-claim or counterclaim in a lawsuit) alleging that any patent claim is infringed by making, using, selling, offering for sale, or importing the Program or any portion of it. 11. Patents. A "contributor" is a copyright holder who authorizes use under this License of the Program or a work on which the Program is based. The work thus licensed is called the contributor's "contributor version". A contributor's "essential patent claims" are all patent claims owned or controlled by the contributor, whether already acquired or hereafter acquired, that would be infringed by some manner, permitted by this License, of making, using, or selling its contributor version, but do not include claims that would be infringed only as a consequence of further modification of the contributor version. For purposes of this definition, "control" includes the right to grant patent sublicenses in a manner consistent with the requirements of this License. Each contributor grants you a non-exclusive, worldwide, royalty-free patent license under the contributor's essential patent claims, to make, use, sell, offer for sale, import and otherwise run, modify and propagate the contents of its contributor version. In the following three paragraphs, a "patent license" is any express agreement or commitment, however denominated, not to enforce a patent (such as an express permission to practice a patent or covenant not to sue for patent infringement). To "grant" such a patent license to a party means to make such an agreement or commitment not to enforce a patent against the party. If you convey a covered work, knowingly relying on a patent license, and the Corresponding Source of the work is not available for anyone to copy, free of charge and under the terms of this License, through a publicly available network server or other readily accessible means, then you must either (1) cause the Corresponding Source to be so available, or (2) arrange to deprive yourself of the benefit of the patent license for this particular work, or (3) arrange, in a manner consistent with the requirements of this License, to extend the patent license to downstream recipients. "Knowingly relying" means you have actual knowledge that, but for the patent license, your conveying the covered work in a country, or your recipient's use of the covered work in a country, would infringe one or more identifiable patents in that country that you have reason to believe are valid. If, pursuant to or in connection with a single transaction or arrangement, you convey, or propagate by procuring conveyance of, a covered work, and grant a patent license to some of the parties receiving the covered work authorizing them to use, propagate, modify or convey a specific copy of the covered work, then the patent license you grant is automatically extended to all recipients of the covered work and works based on it. A patent license is "discriminatory" if it does not include within the scope of its coverage, prohibits the exercise of, or is conditioned on the non-exercise of one or more of the rights that are specifically granted under this License. You may not convey a covered work if you are a party to an arrangement with a third party that is in the business of distributing software, under which you make payment to the third party based on the extent of your activity of conveying the work, and under which the third party grants, to any of the parties who would receive the covered work from you, a discriminatory patent license (a) in connection with copies of the covered work conveyed by you (or copies made from those copies), or (b) primarily for and in connection with specific products or compilations that contain the covered work, unless you entered into that arrangement, or that patent license was granted, prior to 28 March 2007. Nothing in this License shall be construed as excluding or limiting any implied license or other defenses to infringement that may otherwise be available to you under applicable patent law. 12. No Surrender of Others' Freedom. If 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 convey a covered work so as to satisfy simultaneously your obligations under this License and any other pertinent obligations, then as a consequence you may not convey it at all. For example, if you agree to terms that obligate you to collect a royalty for further conveying from those to whom you convey the Program, the only way you could satisfy both those terms and this License would be to refrain entirely from conveying the Program. 13. Use with the GNU Affero General Public License. Notwithstanding any other provision of this License, you have permission to link or combine any covered work with a work licensed under version 3 of the GNU Affero General Public License into a single combined work, and to convey the resulting work. The terms of this License will continue to apply to the part which is the covered work, but the special requirements of the GNU Affero General Public License, section 13, concerning interaction through a network will apply to the combination as such. 14. Revised Versions of this License. The Free Software Foundation may publish revised and/or new versions of the GNU 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 that a certain numbered version of the GNU General Public License "or any later version" applies to it, you have the option of following the terms and conditions either of that numbered version or of any later version published by the Free Software Foundation. If the Program does not specify a version number of the GNU General Public License, you may choose any version ever published by the Free Software Foundation. If the Program specifies that a proxy can decide which future versions of the GNU General Public License can be used, that proxy's public statement of acceptance of a version permanently authorizes you to choose that version for the Program. Later license versions may give you additional or different permissions. However, no additional obligations are imposed on any author or copyright holder as a result of your choosing to follow a later version. 15. Disclaimer of Warranty. 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. 16. Limitation of Liability. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS 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. 17. Interpretation of Sections 15 and 16. If the disclaimer of warranty and limitation of liability provided above cannot be given local legal effect according to their terms, reviewing courts shall apply local law that most closely approximates an absolute waiver of all civil liability in connection with the Program, unless a warranty or assumption of liability accompanies a copy of the Program in return for a fee. 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 state the exclusion of warranty; and each file should have at least the "copyright" line and a pointer to where the full notice is found. Copyright (C) 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 3 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, see . Also add information on how to contact you by electronic and paper mail. If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: Copyright (C) This program 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, your program's commands might be different; for a GUI interface, you would use an "about box". You should also get your employer (if you work as a programmer) or school, if any, to sign a "copyright disclaimer" for the program, if necessary. For more information on this, and how to apply and follow the GNU GPL, see . The GNU 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. But first, please read .PK*\0N| | ,h5plib/v127/joubel/core/js/h5p-action-bar.jsnu[/** * @class * @augments H5P.EventDispatcher * @param {Object} displayOptions * @param {boolean} displayOptions.export Triggers the display of the 'Download' button * @param {boolean} displayOptions.copyright Triggers the display of the 'Copyright' button * @param {boolean} displayOptions.embed Triggers the display of the 'Embed' button * @param {boolean} displayOptions.icon Triggers the display of the 'H5P icon' link */ H5P.ActionBar = (function ($, EventDispatcher) { "use strict"; function ActionBar(displayOptions) { EventDispatcher.call(this); /** @alias H5P.ActionBar# */ var self = this; var hasActions = false; // Create action bar var $actions = H5P.jQuery('
    '); /** * Helper for creating action bar buttons. * * @private * @param {string} type * @param {string} customClass Instead of type class */ var addActionButton = function (type, customClass) { /** * Handles selection of action */ var handler = function () { self.trigger(type); }; const $actionList = H5P.jQuery('
  • ', { 'class': 'h5p-button h5p-noselect h5p-' + (customClass ? customClass : type), appendTo: $actions }); const $actionButton = H5P.jQuery('' + (library.detailsUrl ? '' : '') + (library.deleteUrl ? '' : '') + '' ]); H5PLibraryList.addRestricted($('.h5p-admin-restricted', $libraryRow), library.restrictedUrl, library.restricted); var hasContent = !(library.numContent === '' || library.numContent === 0); if (library.upgradeUrl === null) { $('.h5p-admin-upgrade-library', $libraryRow).remove(); } else if (library.upgradeUrl === false || !hasContent) { $('.h5p-admin-upgrade-library', $libraryRow).attr('disabled', true); } else { $('.h5p-admin-upgrade-library', $libraryRow).attr('title', t.upgradeLibrary).click(function () { window.location.href = library.upgradeUrl; }); } // Open details view when clicked $('.h5p-admin-view-library', $libraryRow).on('click', function () { window.location.href = library.detailsUrl; }); var $deleteButton = $('.h5p-admin-delete-library', $libraryRow); if (libraries.notCached !== undefined || hasContent || (library.numContentDependencies !== '' && library.numContentDependencies !== 0) || (library.numLibraryDependencies !== '' && library.numLibraryDependencies !== 0)) { // Disabled delete if content. $deleteButton.attr('disabled', true); } else { // Go to delete page om click. $deleteButton.attr('title', t.deleteLibrary).on('click', function () { window.location.href = library.deleteUrl; }); } $table.append($libraryRow); }); return $table; }; H5PLibraryList.addRestricted = function ($checkbox, url, selected) { if (selected === null) { $checkbox.remove(); } else { $checkbox.change(function () { $checkbox.attr('disabled', true); $.ajax({ dataType: 'json', url: url, cache: false }).fail(function () { $checkbox.attr('disabled', false); // Reset $checkbox.attr('checked', !$checkbox.is(':checked')); }).done(function (result) { url = result.url; $checkbox.attr('disabled', false); }); }); if (selected) { $checkbox.attr('checked', true); } } }; // Initialize me: $(document).ready(function () { if (!H5PLibraryList.initialized) { H5PLibraryList.initialized = true; H5PLibraryList.init(); } }); })(H5P.jQuery); PK*\專e8"8"-h5plib/v127/joubel/core/js/h5p-x-api-event.jsnu[var H5P = window.H5P = window.H5P || {}; /** * Used for xAPI events. * * @class * @extends H5P.Event */ H5P.XAPIEvent = function () { H5P.Event.call(this, 'xAPI', {'statement': {}}, {bubbles: true, external: true}); }; H5P.XAPIEvent.prototype = Object.create(H5P.Event.prototype); H5P.XAPIEvent.prototype.constructor = H5P.XAPIEvent; /** * Set scored result statements. * * @param {number} score * @param {number} maxScore * @param {object} instance * @param {boolean} completion * @param {boolean} success */ H5P.XAPIEvent.prototype.setScoredResult = function (score, maxScore, instance, completion, success) { this.data.statement.result = {}; if (typeof score !== 'undefined') { if (typeof maxScore === 'undefined') { this.data.statement.result.score = {'raw': score}; } else { this.data.statement.result.score = { 'min': 0, 'max': maxScore, 'raw': score }; if (maxScore > 0) { this.data.statement.result.score.scaled = Math.round(score / maxScore * 10000) / 10000; } } } if (typeof completion === 'undefined') { this.data.statement.result.completion = (this.getVerb() === 'completed' || this.getVerb() === 'answered'); } else { this.data.statement.result.completion = completion; } if (typeof success !== 'undefined') { this.data.statement.result.success = success; } if (instance && instance.activityStartTime) { var duration = Math.round((Date.now() - instance.activityStartTime ) / 10) / 100; // xAPI spec allows a precision of 0.01 seconds this.data.statement.result.duration = 'PT' + duration + 'S'; } }; /** * Set a verb. * * @param {string} verb * Verb in short form, one of the verbs defined at * {@link http://adlnet.gov/expapi/verbs/|ADL xAPI Vocabulary} * */ H5P.XAPIEvent.prototype.setVerb = function (verb) { if (H5P.jQuery.inArray(verb, H5P.XAPIEvent.allowedXAPIVerbs) !== -1) { this.data.statement.verb = { 'id': 'http://adlnet.gov/expapi/verbs/' + verb, 'display': { 'en-US': verb } }; } else if (verb.id !== undefined) { this.data.statement.verb = verb; } }; /** * Get the statements verb id. * * @param {boolean} full * if true the full verb id prefixed by http://adlnet.gov/expapi/verbs/ * will be returned * @returns {string} * Verb or null if no verb with an id has been defined */ H5P.XAPIEvent.prototype.getVerb = function (full) { var statement = this.data.statement; if ('verb' in statement) { if (full === true) { return statement.verb; } return statement.verb.id.slice(31); } else { return null; } }; /** * Set the object part of the statement. * * The id is found automatically (the url to the content) * * @param {Object} instance * The H5P instance */ H5P.XAPIEvent.prototype.setObject = function (instance) { if (instance.contentId) { this.data.statement.object = { 'id': this.getContentXAPIId(instance), 'objectType': 'Activity', 'definition': { 'extensions': { 'http://h5p.org/x-api/h5p-local-content-id': instance.contentId } } }; if (instance.subContentId) { this.data.statement.object.definition.extensions['http://h5p.org/x-api/h5p-subContentId'] = instance.subContentId; // Don't set titles on main content, title should come from publishing platform if (typeof instance.getTitle === 'function') { this.data.statement.object.definition.name = { "en-US": instance.getTitle() }; } } else { var content = H5P.getContentForInstance(instance.contentId); if (content && content.metadata && content.metadata.title) { this.data.statement.object.definition.name = { "en-US": H5P.createTitle(content.metadata.title) }; } } } else { // Content types view always expect to have a contentId when they are displayed. // This is not the case if they are displayed in the editor as part of a preview. // The fix is to set an empty object with definition for the xAPI event, so all // the content types that rely on this does not have to handle it. This means // that content types that are being previewed will send xAPI completed events, // but since there are no scripts that catch these events in the editor, // this is not a problem. this.data.statement.object = { definition: {} }; } }; /** * Set the context part of the statement. * * @param {Object} instance * The H5P instance */ H5P.XAPIEvent.prototype.setContext = function (instance) { if (instance.parent && (instance.parent.contentId || instance.parent.subContentId)) { this.data.statement.context = { "contextActivities": { "parent": [ { "id": this.getContentXAPIId(instance.parent), "objectType": "Activity" } ] } }; } if (instance.libraryInfo) { if (this.data.statement.context === undefined) { this.data.statement.context = {"contextActivities":{}}; } this.data.statement.context.contextActivities.category = [ { "id": "http://h5p.org/libraries/" + instance.libraryInfo.versionedNameNoSpaces, "objectType": "Activity" } ]; } }; /** * Set the actor. Email and name will be added automatically. */ H5P.XAPIEvent.prototype.setActor = function () { if (H5PIntegration.user !== undefined) { this.data.statement.actor = { 'name': H5PIntegration.user.name, 'mbox': 'mailto:' + H5PIntegration.user.mail, 'objectType': 'Agent' }; } else { var uuid; try { if (localStorage.H5PUserUUID) { uuid = localStorage.H5PUserUUID; } else { uuid = H5P.createUUID(); localStorage.H5PUserUUID = uuid; } } catch (err) { // LocalStorage and Cookies are probably disabled. Do not track the user. uuid = 'not-trackable-' + H5P.createUUID(); } this.data.statement.actor = { 'account': { 'name': uuid, 'homePage': H5PIntegration.siteUrl }, 'objectType': 'Agent' }; } }; /** * Get the max value of the result - score part of the statement * * @returns {number} * The max score, or null if not defined */ H5P.XAPIEvent.prototype.getMaxScore = function () { return this.getVerifiedStatementValue(['result', 'score', 'max']); }; /** * Get the raw value of the result - score part of the statement * * @returns {number} * The score, or null if not defined */ H5P.XAPIEvent.prototype.getScore = function () { return this.getVerifiedStatementValue(['result', 'score', 'raw']); }; /** * Get content xAPI ID. * * @param {Object} instance * The H5P instance */ H5P.XAPIEvent.prototype.getContentXAPIId = function (instance) { var xAPIId; if (instance.contentId && H5PIntegration && H5PIntegration.contents && H5PIntegration.contents['cid-' + instance.contentId]) { xAPIId = H5PIntegration.contents['cid-' + instance.contentId].url; if (instance.subContentId) { xAPIId += '?subContentId=' + instance.subContentId; } } return xAPIId; }; /** * Check if this event is sent from a child (i.e not from grandchild) * * @return {Boolean} */ H5P.XAPIEvent.prototype.isFromChild = function () { var parentId = this.getVerifiedStatementValue(['context', 'contextActivities', 'parent', 0, 'id']); return !parentId || parentId.indexOf('subContentId') === -1; }; /** * Figure out if a property exists in the statement and return it * * @param {string[]} keys * List describing the property we're looking for. For instance * ['result', 'score', 'raw'] for result.score.raw * @returns {*} * The value of the property if it is set, null otherwise. */ H5P.XAPIEvent.prototype.getVerifiedStatementValue = function (keys) { var val = this.data.statement; for (var i = 0; i < keys.length; i++) { if (val[keys[i]] === undefined) { return null; } val = val[keys[i]]; } return val; }; /** * List of verbs defined at {@link http://adlnet.gov/expapi/verbs/|ADL xAPI Vocabulary} * * @type Array */ H5P.XAPIEvent.allowedXAPIVerbs = [ 'answered', 'asked', 'attempted', 'attended', 'commented', 'completed', 'exited', 'experienced', 'failed', 'imported', 'initialized', 'interacted', 'launched', 'mastered', 'passed', 'preferred', 'progressed', 'registered', 'responded', 'resumed', 'scored', 'shared', 'suspended', 'terminated', 'voided', // Custom verbs used for action toolbar below content 'downloaded', 'copied', 'accessed-reuse', 'accessed-embed', 'accessed-copyright' ]; PK*\z)'h5plib/v127/joubel/core/js/h5p-embed.jsnu[/*jshint multistr: true */ /** * Converts old script tag embed to iframe */ var H5POldEmbed = H5POldEmbed || (function () { var head = document.getElementsByTagName('head')[0]; var resizer = false; /** * Loads the resizing script */ var loadResizer = function (url) { var data, callback = 'H5POldEmbed'; resizer = true; // Callback for when content data is loaded. window[callback] = function (content) { // Add resizing script to head var resizer = document.createElement('script'); resizer.src = content; head.appendChild(resizer); // Clean up head.removeChild(data); delete window[callback]; }; // Create data script data = document.createElement('script'); data.src = url + (url.indexOf('?') === -1 ? '?' : '&') + 'callback=' + callback; head.appendChild(data); }; /** * Replaced script tag with iframe */ var addIframe = function (script) { // Add iframe var iframe = document.createElement('iframe'); iframe.src = script.getAttribute('data-h5p'); iframe.frameBorder = false; iframe.allowFullscreen = true; var parent = script.parentNode; parent.insertBefore(iframe, script); parent.removeChild(script); }; /** * Go throught all script tags with the data-h5p attribute and load content. */ function H5POldEmbed() { var scripts = document.getElementsByTagName('script'); var h5ps = []; // Use seperate array since scripts grow in size. for (var i = 0; i < scripts.length; i++) { var script = scripts[i]; if (script.src.indexOf('/h5p-resizer.js') !== -1) { resizer = true; } else if (script.hasAttribute('data-h5p')) { h5ps.push(script); } } for (i = 0; i < h5ps.length; i++) { if (!resizer) { loadResizer(h5ps[i].getAttribute('data-h5p')); } addIframe(h5ps[i]); } } return H5POldEmbed; })(); new H5POldEmbed(); PK*\˂d005h5plib/v127/joubel/core/js/h5p-confirmation-dialog.jsnu[/*global H5P*/ H5P.ConfirmationDialog = (function (EventDispatcher) { "use strict"; /** * Create a confirmation dialog * * @param [options] Options for confirmation dialog * @param [options.instance] Instance that uses confirmation dialog * @param [options.headerText] Header text * @param [options.dialogText] Dialog text * @param [options.cancelText] Cancel dialog button text * @param [options.confirmText] Confirm dialog button text * @param [options.hideCancel] Hide cancel button * @param [options.hideExit] Hide exit button * @param [options.skipRestoreFocus] Skip restoring focus when hiding the dialog * @param [options.classes] Extra classes for popup * @constructor */ function ConfirmationDialog(options) { EventDispatcher.call(this); var self = this; // Make sure confirmation dialogs have unique id H5P.ConfirmationDialog.uniqueId += 1; var uniqueId = H5P.ConfirmationDialog.uniqueId; // Default options options = options || {}; options.headerText = options.headerText || H5P.t('confirmDialogHeader'); options.dialogText = options.dialogText || H5P.t('confirmDialogBody'); options.cancelText = options.cancelText || H5P.t('cancelLabel'); options.confirmText = options.confirmText || H5P.t('confirmLabel'); /** * Handle confirming event * @param {Event} e */ function dialogConfirmed(e) { self.hide(); self.trigger('confirmed'); e.preventDefault(); } /** * Handle dialog canceled * @param {Event} e */ function dialogCanceled(e) { self.hide(); self.trigger('canceled'); e.preventDefault(); } /** * Flow focus to element * @param {HTMLElement} element Next element to be focused * @param {Event} e Original tab event */ function flowTo(element, e) { element.focus(); e.preventDefault(); } // Offset of exit button var exitButtonOffset = 2 * 16; var shadowOffset = 8; // Determine if we are too large for our container and must resize var resizeIFrame = false; // Create background var popupBackground = document.createElement('div'); popupBackground.classList .add('h5p-confirmation-dialog-background', 'hidden', 'hiding'); // Create outer popup var popup = document.createElement('div'); popup.classList.add('h5p-confirmation-dialog-popup', 'hidden'); if (options.classes) { options.classes.forEach(function (popupClass) { popup.classList.add(popupClass); }); } popup.setAttribute('role', 'dialog'); popup.setAttribute('aria-labelledby', 'h5p-confirmation-dialog-dialog-text-' + uniqueId); popupBackground.appendChild(popup); popup.addEventListener('keydown', function (e) { if (e.key === 'Escape') {// Esc key // Exit dialog dialogCanceled(e); } }); // Popup header var header = document.createElement('div'); header.classList.add('h5p-confirmation-dialog-header'); popup.appendChild(header); // Header text var headerText = document.createElement('div'); headerText.classList.add('h5p-confirmation-dialog-header-text'); headerText.innerHTML = options.headerText; header.appendChild(headerText); // Popup body var body = document.createElement('div'); body.classList.add('h5p-confirmation-dialog-body'); popup.appendChild(body); // Popup text var text = document.createElement('div'); text.classList.add('h5p-confirmation-dialog-text'); text.innerHTML = options.dialogText; text.id = 'h5p-confirmation-dialog-dialog-text-' + uniqueId; body.appendChild(text); // Popup buttons var buttons = document.createElement('div'); buttons.classList.add('h5p-confirmation-dialog-buttons'); body.appendChild(buttons); // Cancel button var cancelButton = document.createElement('button'); cancelButton.classList.add('h5p-core-cancel-button'); cancelButton.textContent = options.cancelText; // Confirm button var confirmButton = document.createElement('button'); confirmButton.classList.add('h5p-core-button'); confirmButton.classList.add('h5p-confirmation-dialog-confirm-button'); confirmButton.textContent = options.confirmText; // Exit button var exitButton = document.createElement('button'); exitButton.classList.add('h5p-confirmation-dialog-exit'); exitButton.tabIndex = -1; exitButton.setAttribute('aria-label', options.cancelText); // Cancel handler cancelButton.addEventListener('click', dialogCanceled); cancelButton.addEventListener('keydown', function (e) { if (e.key === ' ') { // Space dialogCanceled(e); } else if (e.key === 'Tab' && e.shiftKey) { // Shift-tab const nextbutton = options.hideExit ? confirmButton : exitButton; flowTo(nextbutton, e); } }); if (!options.hideCancel) { buttons.appendChild(cancelButton); } else { // Center buttons buttons.classList.add('center'); } // Confirm handler confirmButton.addEventListener('click', dialogConfirmed); confirmButton.addEventListener('keydown', function (e) { if (e.key === ' ') { // Space dialogConfirmed(e); } else if (e.key === 'Tab' && !e.shiftKey) { // Tab let nextButton = confirmButton; if (!options.hideExit) { nextButton = exitButton; } else if (!options.hideCancel) { nextButton = cancelButton; } flowTo(nextButton, e); } }); buttons.appendChild(confirmButton); // Exit handler exitButton.addEventListener('click', dialogCanceled); exitButton.addEventListener('keydown', function (e) { if (e.key === ' ') { // Space dialogCanceled(e); } else if (e.key === 'Tab' && !e.shiftKey) { // Tab const nextButton = options.hideCancel ? confirmButton : cancelButton; flowTo(nextButton, e); } }); if (!options.hideExit) { popup.appendChild(exitButton); } // Wrapper element var wrapperElement; // Focus capturing var focusPredator; // Maintains hidden state of elements var wrapperSiblingsHidden = []; var popupSiblingsHidden = []; // Element with focus before dialog var previouslyFocused; /** * Set parent of confirmation dialog * @param {HTMLElement} wrapper * @returns {H5P.ConfirmationDialog} */ this.appendTo = function (wrapper) { wrapperElement = wrapper; return this; }; /** * Capture the focus element, send it to confirmation button * @param {Event} e Original focus event */ var captureFocus = function (e) { if (!popupBackground.contains(e.target)) { e.preventDefault(); confirmButton.focus(); } }; /** * Hide siblings of element from assistive technology * * @param {HTMLElement} element * @returns {Array} The previous hidden state of all siblings */ var hideSiblings = function (element) { var hiddenSiblings = []; var siblings = element.parentNode.children; var i; for (i = 0; i < siblings.length; i += 1) { // Preserve hidden state hiddenSiblings[i] = siblings[i].getAttribute('aria-hidden') ? true : false; if (siblings[i] !== element) { siblings[i].setAttribute('aria-hidden', true); } } return hiddenSiblings; }; /** * Restores assistive technology state of element's siblings * * @param {HTMLElement} element * @param {Array} hiddenSiblings Hidden state of all siblings */ var restoreSiblings = function (element, hiddenSiblings) { var siblings = element.parentNode.children; var i; for (i = 0; i < siblings.length; i += 1) { if (siblings[i] !== element && !hiddenSiblings[i]) { siblings[i].removeAttribute('aria-hidden'); } } }; /** * Start capturing focus of parent and send it to dialog */ var startCapturingFocus = function () { focusPredator = wrapperElement.parentNode || wrapperElement; focusPredator.addEventListener('focus', captureFocus, true); }; /** * Clean up event listener for capturing focus */ var stopCapturingFocus = function () { focusPredator.removeAttribute('aria-hidden'); focusPredator.removeEventListener('focus', captureFocus, true); }; /** * Hide siblings in underlay from assistive technologies */ var disableUnderlay = function () { wrapperSiblingsHidden = hideSiblings(wrapperElement); popupSiblingsHidden = hideSiblings(popupBackground); }; /** * Restore state of underlay for assistive technologies */ var restoreUnderlay = function () { restoreSiblings(wrapperElement, wrapperSiblingsHidden); restoreSiblings(popupBackground, popupSiblingsHidden); }; /** * Fit popup to container. Makes sure it doesn't overflow. * @params {number} [offsetTop] Offset of popup */ var fitToContainer = function (offsetTop) { var popupOffsetTop = parseInt(popup.style.top, 10); if (offsetTop !== undefined) { popupOffsetTop = offsetTop; } if (!popupOffsetTop) { popupOffsetTop = 0; } // Overflows height if (popupOffsetTop + popup.offsetHeight > wrapperElement.offsetHeight) { popupOffsetTop = wrapperElement.offsetHeight - popup.offsetHeight - shadowOffset; } if (popupOffsetTop - exitButtonOffset <= 0) { popupOffsetTop = exitButtonOffset + shadowOffset; // We are too big and must resize resizeIFrame = true; } popup.style.top = popupOffsetTop + 'px'; }; /** * Show confirmation dialog * @params {number} offsetTop Offset top * @returns {H5P.ConfirmationDialog} */ this.show = function (offsetTop) { // Capture focused item previouslyFocused = document.activeElement; wrapperElement.appendChild(popupBackground); startCapturingFocus(); disableUnderlay(); popupBackground.classList.remove('hidden'); fitToContainer(offsetTop); setTimeout(function () { popup.classList.remove('hidden'); popupBackground.classList.remove('hiding'); setTimeout(function () { // Focus confirm button confirmButton.focus(); // Resize iFrame if necessary if (resizeIFrame && options.instance) { var minHeight = parseInt(popup.offsetHeight, 10) + exitButtonOffset + (2 * shadowOffset); self.setViewPortMinimumHeight(minHeight); options.instance.trigger('resize'); resizeIFrame = false; } }, 100); }, 0); return this; }; /** * Hide confirmation dialog * @returns {H5P.ConfirmationDialog} */ this.hide = function () { popupBackground.classList.add('hiding'); popup.classList.add('hidden'); // Restore focus stopCapturingFocus(); if (!options.skipRestoreFocus) { previouslyFocused.focus(); } restoreUnderlay(); setTimeout(function () { popupBackground.classList.add('hidden'); wrapperElement.removeChild(popupBackground); self.setViewPortMinimumHeight(null); }, 100); return this; }; /** * Retrieve element * * @return {HTMLElement} */ this.getElement = function () { return popup; }; /** * Get previously focused element * @return {HTMLElement} */ this.getPreviouslyFocused = function () { return previouslyFocused; }; /** * Sets the minimum height of the view port * * @param {number|null} minHeight */ this.setViewPortMinimumHeight = function (minHeight) { var container = document.querySelector('.h5p-container') || document.body; container.style.minHeight = (typeof minHeight === 'number') ? (minHeight + 'px') : minHeight; }; } ConfirmationDialog.prototype = Object.create(EventDispatcher.prototype); ConfirmationDialog.prototype.constructor = ConfirmationDialog; return ConfirmationDialog; }(H5P.EventDispatcher)); H5P.ConfirmationDialog.uniqueId = -1; PK*\@$ 6h5plib/v127/joubel/core/js/settings/h5p-disable-hub.jsnu[/* global H5PDisableHubData */ /** * Global data for disable hub functionality * * @typedef {object} H5PDisableHubData Data passed in from the backend * * @property {string} selector Selector for the disable hub check-button * @property {string} overlaySelector Selector for the element that the confirmation dialog will mask * @property {Array} errors Errors found with the current server setup * * @property {string} header Header of the confirmation dialog * @property {string} confirmationDialogMsg Body of the confirmation dialog * @property {string} cancelLabel Cancel label of the confirmation dialog * @property {string} confirmLabel Confirm button label of the confirmation dialog * */ /** * Utility that makes it possible to force the user to confirm that he really * wants to use the H5P hub without proper server settings. */ (function ($) { $(document).on('ready', function () { // No data found if (!H5PDisableHubData) { return; } // No errors found, no need for confirmation dialog if (!H5PDisableHubData.errors || !H5PDisableHubData.errors.length) { return; } H5PDisableHubData.selector = H5PDisableHubData.selector || '.h5p-settings-disable-hub-checkbox'; H5PDisableHubData.overlaySelector = H5PDisableHubData.overlaySelector || '.h5p-settings-container'; var dialogHtml = '
    ' + '

    ' + H5PDisableHubData.errors.join('

    ') + '

    ' + '

    ' + H5PDisableHubData.confirmationDialogMsg + '

    '; // Create confirmation dialog, make sure to include translations var confirmationDialog = new H5P.ConfirmationDialog({ headerText: H5PDisableHubData.header, dialogText: dialogHtml, cancelText: H5PDisableHubData.cancelLabel, confirmText: H5PDisableHubData.confirmLabel }).appendTo($(H5PDisableHubData.overlaySelector).get(0)); confirmationDialog.on('confirmed', function () { enableButton.get(0).checked = true; }); confirmationDialog.on('canceled', function () { enableButton.get(0).checked = false; }); var enableButton = $(H5PDisableHubData.selector); enableButton.change(function () { if ($(this).is(':checked')) { confirmationDialog.show(enableButton.offset().top); } }); }); })(H5P.jQuery); PK*\(8)h5plib/v127/joubel/core/js/h5p-version.jsnu[H5P.Version = (function () { /** * Make it easy to keep track of version details. * * @class * @namespace H5P * @param {String} version */ function Version(version) { if (typeof version === 'string') { // Name version string (used by content upgrade) var versionSplit = version.split('.', 3); this.major =+ versionSplit[0]; this.minor =+ versionSplit[1]; } else { // Library objects (used by editor) if (version.localMajorVersion !== undefined) { this.major =+ version.localMajorVersion; this.minor =+ version.localMinorVersion; } else { this.major =+ version.majorVersion; this.minor =+ version.minorVersion; } } /** * Public. Custom string for this object. * * @returns {String} */ this.toString = function () { return version; }; } return Version; })(); PK*\~q\\!h5plib/v127/joubel/core/js/h5p.jsnu[/*jshint multistr: true */ // TODO: Should we split up the generic parts needed by the editor(and others), and the parts needed to "run" H5Ps? /** @namespace */ var H5P = window.H5P = window.H5P || {}; /** * Tells us if we're inside of an iframe. * @member {boolean} */ H5P.isFramed = (window.self !== window.parent); /** * jQuery instance of current window. * @member {H5P.jQuery} */ H5P.$window = H5P.jQuery(window); /** * List over H5P instances on the current page. * @member {Array} */ H5P.instances = []; // Detect if we support fullscreen, and what prefix to use. if (document.documentElement.requestFullscreen) { /** * Browser prefix to use when entering fullscreen mode. * undefined means no fullscreen support. * @member {string} */ H5P.fullScreenBrowserPrefix = ''; } else if (document.documentElement.webkitRequestFullScreen) { H5P.safariBrowser = navigator.userAgent.match(/version\/([.\d]+)/i); H5P.safariBrowser = (H5P.safariBrowser === null ? 0 : parseInt(H5P.safariBrowser[1])); // Do not allow fullscreen for safari < 7. if (H5P.safariBrowser === 0 || H5P.safariBrowser > 6) { H5P.fullScreenBrowserPrefix = 'webkit'; } } else if (document.documentElement.mozRequestFullScreen) { H5P.fullScreenBrowserPrefix = 'moz'; } else if (document.documentElement.msRequestFullscreen) { H5P.fullScreenBrowserPrefix = 'ms'; } /** * Keep track of when the H5Ps where started. * * @type {Object[]} */ H5P.opened = {}; /** * Initialize H5P content. * Scans for ".h5p-content" in the document and initializes H5P instances where found. * * @param {Object} target DOM Element */ H5P.init = function (target) { // Useful jQuery object. if (H5P.$body === undefined) { H5P.$body = H5P.jQuery(document.body); } // Determine if we can use full screen if (H5P.fullscreenSupported === undefined) { /** * Use this variable to check if fullscreen is supported. Fullscreen can be * restricted when embedding since not all browsers support the native * fullscreen, and the semi-fullscreen solution doesn't work when embedded. * @type {boolean} */ H5P.fullscreenSupported = !H5PIntegration.fullscreenDisabled && !H5P.fullscreenDisabled && (!(H5P.isFramed && H5P.externalEmbed !== false) || !!(document.fullscreenEnabled || document.webkitFullscreenEnabled || document.mozFullScreenEnabled)); // -We should consider document.msFullscreenEnabled when they get their // -element sizing corrected. Ref. https://connect.microsoft.com/IE/feedback/details/838286/ie-11-incorrectly-reports-dom-element-sizes-in-fullscreen-mode-when-fullscreened-element-is-within-an-iframe // Update: Seems to be no need as they've moved on to Webkit } // Deprecated variable, kept to maintain backwards compatability if (H5P.canHasFullScreen === undefined) { /** * @deprecated since version 1.11 * @type {boolean} */ H5P.canHasFullScreen = H5P.fullscreenSupported; } // H5Ps added in normal DIV. H5P.jQuery('.h5p-content:not(.h5p-initialized)', target).each(function () { var $element = H5P.jQuery(this).addClass('h5p-initialized'); var $container = H5P.jQuery('
    ').appendTo($element); var contentId = $element.data('content-id'); var contentData = H5PIntegration.contents['cid-' + contentId]; if (contentData === undefined) { return H5P.error('No data for content id ' + contentId + '. Perhaps the library is gone?'); } var library = { library: contentData.library, params: JSON.parse(contentData.jsonContent), metadata: contentData.metadata }; H5P.getUserData(contentId, 'state', function (err, previousState) { if (previousState) { library.userDatas = { state: previousState }; } else if (previousState === null && H5PIntegration.saveFreq) { // Content has been reset. Display dialog. delete contentData.contentUserData; var dialog = new H5P.Dialog('content-user-data-reset', 'Data Reset', '

    ' + H5P.t('contentChanged') + '

    ' + H5P.t('startingOver') + '

    OK
    ', $container); H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) { var closeDialog = function (event) { if (event.type === 'click' || event.which === 32) { dialog.close(); H5P.deleteUserData(contentId, 'state', 0); } }; $dialog.find('.h5p-dialog-ok-button').click(closeDialog).keypress(closeDialog); H5P.trigger(instance, 'resize'); }).on('dialog-closed', function () { H5P.trigger(instance, 'resize'); }); dialog.open(); } // If previousState is false we don't have a previous state }); // Create new instance. var instance = H5P.newRunnable(library, contentId, $container, true, {standalone: true}); H5P.offlineRequestQueue = new H5P.OfflineRequestQueue({instance: instance}); // Check if we should add and display a fullscreen button for this H5P. if (contentData.fullScreen == 1 && H5P.fullscreenSupported) { H5P.jQuery( '
    ' + '
    ' + '
    ' + '
    ') .prependTo($container) .children() .click(function () { H5P.fullScreen($container, instance); }) .keydown(function (e) { if (e.which === 32 || e.which === 13) { H5P.fullScreen($container, instance); return false; } }) ; } /** * Create action bar */ var displayOptions = contentData.displayOptions; var displayFrame = false; if (displayOptions.frame) { // Special handling of copyrights if (displayOptions.copyright) { var copyrights = H5P.getCopyrights(instance, library.params, contentId, library.metadata); if (!copyrights) { displayOptions.copyright = false; } } // Create action bar var actionBar = new H5P.ActionBar(displayOptions); var $actions = actionBar.getDOMElement(); actionBar.on('reuse', function () { H5P.openReuseDialog($actions, contentData, library, instance, contentId); instance.triggerXAPI('accessed-reuse'); }); actionBar.on('copyrights', function () { var dialog = new H5P.Dialog('copyrights', H5P.t('copyrightInformation'), copyrights, $container); dialog.open(true); instance.triggerXAPI('accessed-copyright'); }); actionBar.on('embed', function () { H5P.openEmbedDialog($actions, contentData.embedCode, contentData.resizeCode, { width: $element.width(), height: $element.height() }, instance); instance.triggerXAPI('accessed-embed'); }); if (actionBar.hasActions()) { displayFrame = true; $actions.insertAfter($container); } } $element.addClass(displayFrame ? 'h5p-frame' : 'h5p-no-frame'); // Keep track of when we started H5P.opened[contentId] = new Date(); // Handle events when the user finishes the content. Useful for logging exercise results. H5P.on(instance, 'finish', function (event) { if (event.data !== undefined) { H5P.setFinished(contentId, event.data.score, event.data.maxScore, event.data.time); } }); // Listen for xAPI events. H5P.on(instance, 'xAPI', H5P.xAPICompletedListener); // Auto save current state if supported if (H5PIntegration.saveFreq !== false && ( instance.getCurrentState instanceof Function || typeof instance.getCurrentState === 'function')) { var saveTimer, save = function () { var state = instance.getCurrentState(); if (state !== undefined) { H5P.setUserData(contentId, 'state', state, {deleteOnChange: true}); } if (H5PIntegration.saveFreq) { // Continue autosave saveTimer = setTimeout(save, H5PIntegration.saveFreq * 1000); } }; if (H5PIntegration.saveFreq) { // Start autosave saveTimer = setTimeout(save, H5PIntegration.saveFreq * 1000); } // xAPI events will schedule a save in three seconds. H5P.on(instance, 'xAPI', function (event) { var verb = event.getVerb(); if (verb === 'completed' || verb === 'progressed') { clearTimeout(saveTimer); saveTimer = setTimeout(save, 3000); } }); } if (H5P.isFramed) { var resizeDelay; if (H5P.externalEmbed === false) { // Internal embed // Make it possible to resize the iframe when the content changes size. This way we get no scrollbars. var iframe = window.frameElement; var resizeIframe = function () { if (window.parent.H5P.isFullscreen) { return; // Skip if full screen. } // Retain parent size to avoid jumping/scrolling var parentHeight = iframe.parentElement.style.height; iframe.parentElement.style.height = iframe.parentElement.clientHeight + 'px'; // Note: Force layout reflow // This fixes a flickering bug for embedded content on iPads // @see https://github.com/h5p/h5p-moodle-plugin/issues/237 iframe.getBoundingClientRect(); // Reset iframe height, in case content has shrinked. iframe.style.height = '1px'; // Resize iframe so all content is visible. iframe.style.height = (iframe.contentDocument.body.scrollHeight) + 'px'; // Free parent iframe.parentElement.style.height = parentHeight; }; H5P.on(instance, 'resize', function () { // Use a delay to make sure iframe is resized to the correct size. clearTimeout(resizeDelay); resizeDelay = setTimeout(function () { resizeIframe(); }, 1); }); } else if (H5P.communicator) { // External embed var parentIsFriendly = false; // Handle that the resizer is loaded after the iframe H5P.communicator.on('ready', function () { H5P.communicator.send('hello'); }); // Handle hello message from our parent window H5P.communicator.on('hello', function () { // Initial setup/handshake is done parentIsFriendly = true; // Make iframe responsive document.body.style.height = 'auto'; // Hide scrollbars for correct size document.body.style.overflow = 'hidden'; // Content need to be resized to fit the new iframe size H5P.trigger(instance, 'resize'); }); // When resize has been prepared tell parent window to resize H5P.communicator.on('resizePrepared', function () { H5P.communicator.send('resize', { scrollHeight: document.body.scrollHeight }); }); H5P.communicator.on('resize', function () { H5P.trigger(instance, 'resize'); }); H5P.on(instance, 'resize', function () { if (H5P.isFullscreen) { return; // Skip iframe resize } // Use a delay to make sure iframe is resized to the correct size. clearTimeout(resizeDelay); resizeDelay = setTimeout(function () { // Only resize if the iframe can be resized if (parentIsFriendly) { H5P.communicator.send('prepareResize', { scrollHeight: document.body.scrollHeight, clientHeight: document.body.clientHeight }); } else { H5P.communicator.send('hello'); } }, 0); }); } } if (!H5P.isFramed || H5P.externalEmbed === false) { // Resize everything when window is resized. H5P.jQuery(window.parent).resize(function () { H5P.trigger(instance, 'resize'); }); } H5P.instances.push(instance); // Resize content. H5P.trigger(instance, 'resize'); // Logic for hiding focus effects when using mouse $element.addClass('using-mouse'); $element.on('mousedown keydown keyup', function (event) { $element.toggleClass('using-mouse', event.type === 'mousedown'); }); if (H5P.externalDispatcher) { H5P.externalDispatcher.trigger('initialized'); } }); // Insert H5Ps that should be in iframes. H5P.jQuery('iframe.h5p-iframe:not(.h5p-initialized)', target).each(function () { const iframe = this; const $iframe = H5P.jQuery(iframe); const contentId = $iframe.data('content-id'); const contentData = H5PIntegration.contents['cid-' + contentId]; const contentLanguage = contentData && contentData.metadata && contentData.metadata.defaultLanguage ? contentData.metadata.defaultLanguage : 'en'; const writeDocument = function () { iframe.contentDocument.open(); iframe.contentDocument.write('' + H5P.getHeadTags(contentId) + '
    '); iframe.contentDocument.close(); }; $iframe.addClass('h5p-initialized') if (iframe.contentDocument === null) { // In some Edge cases the iframe isn't always loaded when the page is ready. $iframe.on('load', writeDocument); $iframe.attr('src', 'about:blank'); } else { writeDocument(); } }); }; /** * Loop through assets for iframe content and create a set of tags for head. * * @private * @param {number} contentId * @returns {string} HTML */ H5P.getHeadTags = function (contentId) { var createStyleTags = function (styles) { var tags = ''; for (var i = 0; i < styles.length; i++) { tags += ''; } return tags; }; var createScriptTags = function (scripts) { var tags = ''; for (var i = 0; i < scripts.length; i++) { tags += ''; } return tags; }; return '' + createStyleTags(H5PIntegration.core.styles) + createStyleTags(H5PIntegration.contents['cid-' + contentId].styles) + createScriptTags(H5PIntegration.core.scripts) + createScriptTags(H5PIntegration.contents['cid-' + contentId].scripts) + ''; }; /** * When embedded the communicator helps talk to the parent page. * * @type {Communicator} */ H5P.communicator = (function () { /** * @class * @private */ function Communicator() { var self = this; // Maps actions to functions var actionHandlers = {}; // Register message listener window.addEventListener('message', function receiveMessage(event) { if (window.parent !== event.source || event.data.context !== 'h5p') { return; // Only handle messages from parent and in the correct context } if (actionHandlers[event.data.action] !== undefined) { actionHandlers[event.data.action](event.data); } } , false); /** * Register action listener. * * @param {string} action What you are waiting for * @param {function} handler What you want done */ self.on = function (action, handler) { actionHandlers[action] = handler; }; /** * Send a message to the all mighty father. * * @param {string} action * @param {Object} [data] payload */ self.send = function (action, data) { if (data === undefined) { data = {}; } data.context = 'h5p'; data.action = action; // Parent origin can be anything window.parent.postMessage(data, '*'); }; } return (window.postMessage && window.addEventListener ? new Communicator() : undefined); })(); /** * Enter semi fullscreen for the given H5P instance * * @param {H5P.jQuery} $element Content container. * @param {Object} instance * @param {function} exitCallback Callback function called when user exits fullscreen. * @param {H5P.jQuery} $body For internal use. Gives the body of the iframe. */ H5P.semiFullScreen = function ($element, instance, exitCallback, body) { H5P.fullScreen($element, instance, exitCallback, body, true); }; /** * Enter fullscreen for the given H5P instance. * * @param {H5P.jQuery} $element Content container. * @param {Object} instance * @param {function} exitCallback Callback function called when user exits fullscreen. * @param {H5P.jQuery} $body For internal use. Gives the body of the iframe. * @param {Boolean} forceSemiFullScreen */ H5P.fullScreen = function ($element, instance, exitCallback, body, forceSemiFullScreen) { if (H5P.exitFullScreen !== undefined) { return; // Cannot enter new fullscreen until previous is over } if (H5P.isFramed && H5P.externalEmbed === false) { // Trigger resize on wrapper in parent window. window.parent.H5P.fullScreen($element, instance, exitCallback, H5P.$body.get(), forceSemiFullScreen); H5P.isFullscreen = true; H5P.exitFullScreen = function () { window.parent.H5P.exitFullScreen(); }; H5P.on(instance, 'exitFullScreen', function () { H5P.isFullscreen = false; H5P.exitFullScreen = undefined; }); return; } var $container = $element; var $classes, $iframe, $body; if (body === undefined) { $body = H5P.$body; } else { // We're called from an iframe. $body = H5P.jQuery(body); $classes = $body.add($element.get()); var iframeSelector = '#h5p-iframe-' + $element.parent().data('content-id'); $iframe = H5P.jQuery(iframeSelector); $element = $iframe.parent(); // Put iframe wrapper in fullscreen, not container. } $classes = $element.add(H5P.$body).add($classes); /** * Prepare for resize by setting the correct styles. * * @private * @param {string} classes CSS */ var before = function (classes) { $classes.addClass(classes); if ($iframe !== undefined) { // Set iframe to its default size(100%). $iframe.css('height', ''); } }; /** * Gets called when fullscreen mode has been entered. * Resizes and sets focus on content. * * @private */ var entered = function () { // Do not rely on window resize events. H5P.trigger(instance, 'resize'); H5P.trigger(instance, 'focus'); H5P.trigger(instance, 'enterFullScreen'); }; /** * Gets called when fullscreen mode has been exited. * Resizes and sets focus on content. * * @private * @param {string} classes CSS */ var done = function (classes) { H5P.isFullscreen = false; $classes.removeClass(classes); // Do not rely on window resize events. H5P.trigger(instance, 'resize'); H5P.trigger(instance, 'focus'); H5P.exitFullScreen = undefined; if (exitCallback !== undefined) { exitCallback(); } H5P.trigger(instance, 'exitFullScreen'); }; H5P.isFullscreen = true; if (H5P.fullScreenBrowserPrefix === undefined || forceSemiFullScreen === true) { // Create semi fullscreen. if (H5P.isFramed) { return; // TODO: Should we support semi-fullscreen for IE9 & 10 ? } before('h5p-semi-fullscreen'); var $disable = H5P.jQuery('
    ').appendTo($container.find('.h5p-content-controls')); var keyup, disableSemiFullscreen = H5P.exitFullScreen = function () { if (prevViewportContent) { // Use content from the previous viewport tag h5pViewport.content = prevViewportContent; } else { // Remove viewport tag head.removeChild(h5pViewport); } $disable.remove(); $body.unbind('keyup', keyup); done('h5p-semi-fullscreen'); }; keyup = function (event) { if (event.keyCode === 27) { disableSemiFullscreen(); } }; $disable.click(disableSemiFullscreen); $body.keyup(keyup); // Disable zoom var prevViewportContent, h5pViewport; var metaTags = document.getElementsByTagName('meta'); for (var i = 0; i < metaTags.length; i++) { if (metaTags[i].name === 'viewport') { // Use the existing viewport tag h5pViewport = metaTags[i]; prevViewportContent = h5pViewport.content; break; } } if (!prevViewportContent) { // Create a new viewport tag h5pViewport = document.createElement('meta'); h5pViewport.name = 'viewport'; } h5pViewport.content = 'width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0'; if (!prevViewportContent) { // Insert the new viewport tag var head = document.getElementsByTagName('head')[0]; head.appendChild(h5pViewport); } entered(); } else { // Create real fullscreen. before('h5p-fullscreen'); var first, eventName = (H5P.fullScreenBrowserPrefix === 'ms' ? 'MSFullscreenChange' : H5P.fullScreenBrowserPrefix + 'fullscreenchange'); document.addEventListener(eventName, function fullscreenCallback() { if (first === undefined) { // We are entering fullscreen mode first = false; entered(); return; } // We are exiting fullscreen done('h5p-fullscreen'); document.removeEventListener(eventName, fullscreenCallback, false); }); if (H5P.fullScreenBrowserPrefix === '') { $element[0].requestFullscreen(); } else { var method = (H5P.fullScreenBrowserPrefix === 'ms' ? 'msRequestFullscreen' : H5P.fullScreenBrowserPrefix + 'RequestFullScreen'); var params = (H5P.fullScreenBrowserPrefix === 'webkit' && H5P.safariBrowser === 0 ? Element.ALLOW_KEYBOARD_INPUT : undefined); $element[0][method](params); } // Allows everone to exit H5P.exitFullScreen = function () { if (H5P.fullScreenBrowserPrefix === '') { document.exitFullscreen(); } else if (H5P.fullScreenBrowserPrefix === 'moz') { document.mozCancelFullScreen(); } else { document[H5P.fullScreenBrowserPrefix + 'ExitFullscreen'](); } }; } }; (function () { /** * Helper for adding a query parameter to an existing path that may already * contain one or a hash. * * @param {string} path * @param {string} parameter * @return {string} */ H5P.addQueryParameter = function (path, parameter) { let newPath, secondSplit; const firstSplit = path.split('?'); if (firstSplit[1]) { // There is already an existing query secondSplit = firstSplit[1].split('#'); newPath = firstSplit[0] + '?' + secondSplit[0] + '&'; } else { // No existing query, just need to take care of the hash secondSplit = firstSplit[0].split('#'); newPath = secondSplit[0] + '?'; } newPath += parameter; if (secondSplit[1]) { // Add back the hash newPath += '#' + secondSplit[1]; } return newPath; }; /** * Helper for setting the crossOrigin attribute + the complete correct source. * Note: This will start loading the resource. * * @param {Element} element DOM element, typically img, video or audio * @param {Object} source File object from parameters/json_content (created by H5PEditor) * @param {number} contentId Needed to determine the complete correct file path */ H5P.setSource = function (element, source, contentId) { let path = source.path; const crossOrigin = H5P.getCrossOrigin(source); if (crossOrigin) { element.crossOrigin = crossOrigin; if (H5PIntegration.crossoriginCacheBuster) { // Some sites may want to add a cache buster in case the same resource // is used elsewhere without the crossOrigin attribute path = H5P.addQueryParameter(path, H5PIntegration.crossoriginCacheBuster); } } else { // In case this element has been used before. element.removeAttribute('crossorigin'); } element.src = H5P.getPath(path, contentId); }; /** * Check if the given path has a protocol. * * @private * @param {string} path * @return {string} */ var hasProtocol = function (path) { return path.match(/^[a-z0-9]+:\/\//i); }; /** * Get the crossOrigin policy to use for img, video and audio tags on the current site. * * @param {Object|string} source File object from parameters/json_content - Can also be URL(deprecated usage) * @returns {string|null} crossOrigin attribute value required by the source */ H5P.getCrossOrigin = function (source) { if (typeof source !== 'object') { // Deprecated usage. return H5PIntegration.crossorigin && H5PIntegration.crossoriginRegex && source.match(H5PIntegration.crossoriginRegex) ? H5PIntegration.crossorigin : null; } if (H5PIntegration.crossorigin && !hasProtocol(source.path)) { // This is a local file, use the local crossOrigin policy. return H5PIntegration.crossorigin; // Note: We cannot use this for all external sources since we do not know // each server's individual policy. We could add support for a list of // external sources and their policy later on. } }; /** * Find the path to the content files based on the id of the content. * Also identifies and returns absolute paths. * * @param {string} path * Relative to content folder or absolute. * @param {number} contentId * ID of the content requesting the path. * @returns {string} * Complete URL to path. */ H5P.getPath = function (path, contentId) { if (hasProtocol(path)) { return path; } var prefix; var isTmpFile = (path.substr(-4,4) === '#tmp'); if (contentId !== undefined && !isTmpFile) { // Check for custom override URL if (H5PIntegration.contents !== undefined && H5PIntegration.contents['cid-' + contentId]) { prefix = H5PIntegration.contents['cid-' + contentId].contentUrl; } if (!prefix) { prefix = H5PIntegration.url + '/content/' + contentId; } } else if (window.H5PEditor !== undefined) { prefix = H5PEditor.filesPath; } else { return; } if (!hasProtocol(prefix)) { // Use absolute urls prefix = window.location.protocol + "//" + window.location.host + prefix; } return prefix + '/' + path; }; })(); /** * THIS FUNCTION IS DEPRECATED, USE getPath INSTEAD * Will be remove march 2016. * * Find the path to the content files folder based on the id of the content * * @deprecated * Will be removed march 2016. * @param contentId * Id of the content requesting the path * @returns {string} * URL */ H5P.getContentPath = function (contentId) { return H5PIntegration.url + '/content/' + contentId; }; /** * Get library class constructor from H5P by classname. * Note that this class will only work for resolve "H5P.NameWithoutDot". * Also check out {@link H5P.newRunnable} * * Used from libraries to construct instances of other libraries' objects by name. * * @param {string} name Name of library * @returns {Object} Class constructor */ H5P.classFromName = function (name) { var arr = name.split("."); return this[arr[arr.length - 1]]; }; /** * A safe way of creating a new instance of a runnable H5P. * * @param {Object} library * Library/action object form params. * @param {number} contentId * Identifies the content. * @param {H5P.jQuery} [$attachTo] * Element to attach the instance to. * @param {boolean} [skipResize] * Skip triggering of the resize event after attaching. * @param {Object} [extras] * Extra parameters for the H5P content constructor * @returns {Object} * Instance. */ H5P.newRunnable = function (library, contentId, $attachTo, skipResize, extras) { var nameSplit, versionSplit, machineName; try { nameSplit = library.library.split(' ', 2); machineName = nameSplit[0]; versionSplit = nameSplit[1].split('.', 2); } catch (err) { return H5P.error('Invalid library string: ' + library.library); } if ((library.params instanceof Object) !== true || (library.params instanceof Array) === true) { H5P.error('Invalid library params for: ' + library.library); return H5P.error(library.params); } // Find constructor function var constructor; try { nameSplit = nameSplit[0].split('.'); constructor = window; for (var i = 0; i < nameSplit.length; i++) { constructor = constructor[nameSplit[i]]; } if (typeof constructor !== 'function') { throw null; } } catch (err) { return H5P.error('Unable to find constructor for: ' + library.library); } if (extras === undefined) { extras = {}; } if (library.subContentId) { extras.subContentId = library.subContentId; } if (library.userDatas && library.userDatas.state && H5PIntegration.saveFreq) { extras.previousState = library.userDatas.state; } if (library.metadata) { extras.metadata = library.metadata; } // Makes all H5P libraries extend H5P.ContentType: var standalone = extras.standalone || false; // This order makes it possible for an H5P library to override H5P.ContentType functions! constructor.prototype = H5P.jQuery.extend({}, H5P.ContentType(standalone).prototype, constructor.prototype); var instance; // Some old library versions have their own custom third parameter. // Make sure we don't send them the extras. // (they will interpret it as something else) if (H5P.jQuery.inArray(library.library, ['H5P.CoursePresentation 1.0', 'H5P.CoursePresentation 1.1', 'H5P.CoursePresentation 1.2', 'H5P.CoursePresentation 1.3']) > -1) { instance = new constructor(library.params, contentId); } else { instance = new constructor(library.params, contentId, extras); } if (instance.$ === undefined) { instance.$ = H5P.jQuery(instance); } if (instance.contentId === undefined) { instance.contentId = contentId; } if (instance.subContentId === undefined && library.subContentId) { instance.subContentId = library.subContentId; } if (instance.parent === undefined && extras && extras.parent) { instance.parent = extras.parent; } if (instance.libraryInfo === undefined) { instance.libraryInfo = { versionedName: library.library, versionedNameNoSpaces: machineName + '-' + versionSplit[0] + '.' + versionSplit[1], machineName: machineName, majorVersion: versionSplit[0], minorVersion: versionSplit[1] }; } if ($attachTo !== undefined) { $attachTo.toggleClass('h5p-standalone', standalone); instance.attach($attachTo); H5P.trigger(instance, 'domChanged', { '$target': $attachTo, 'library': machineName, 'key': 'newLibrary' }, {'bubbles': true, 'external': true}); if (skipResize === undefined || !skipResize) { // Resize content. H5P.trigger(instance, 'resize'); } } return instance; }; /** * Used to print useful error messages. (to JavaScript error console) * * @param {*} err Error to print. */ H5P.error = function (err) { if (window.console !== undefined && console.error !== undefined) { console.error(err.stack ? err.stack : err); } }; /** * Translate text strings. * * @param {string} key * Translation identifier, may only contain a-zA-Z0-9. No spaces or special chars. * @param {Object} [vars] * Data for placeholders. * @param {string} [ns] * Translation namespace. Defaults to H5P. * @returns {string} * Translated text */ H5P.t = function (key, vars, ns) { if (ns === undefined) { ns = 'H5P'; } if (H5PIntegration.l10n[ns] === undefined) { return '[Missing translation namespace "' + ns + '"]'; } if (H5PIntegration.l10n[ns][key] === undefined) { return '[Missing translation "' + key + '" in "' + ns + '"]'; } var translation = H5PIntegration.l10n[ns][key]; if (vars !== undefined) { // Replace placeholder with variables. for (var placeholder in vars) { translation = translation.replace(placeholder, vars[placeholder]); } } return translation; }; /** * Creates a new popup dialog over the H5P content. * * @class * @param {string} name * Used for html class. * @param {string} title * Used for header. * @param {string} content * Displayed inside the dialog. * @param {H5P.jQuery} $element * Which DOM element the dialog should be inserted after. * @param {H5P.jQuery} $returnElement * Which DOM element the focus should be moved to on close */ H5P.Dialog = function (name, title, content, $element, $returnElement) { /** @alias H5P.Dialog# */ var self = this; this.activeElement = document.activeElement; var $dialog = H5P.jQuery('') .insertAfter($element) .click(function (e) { if (e && e.originalEvent && e.originalEvent.preventClosing) { return; } self.close(); }) .children('.h5p-inner') .click(function (e) { e.originalEvent.preventClosing = true; }) .find('.h5p-close') .click(function () { self.close(); }) .keypress(function (e) { if (e.which === 13 || e.which === 32) { self.close(); return false; } }) .end() .find('a') .click(function (e) { e.stopPropagation(); }) .end() .end(); /** * Opens the dialog. */ self.open = function (scrollbar) { if (scrollbar) { $dialog.css('height', '100%'); } setTimeout(function () { $dialog.addClass('h5p-open'); // Fade in // Triggering an event, in case something has to be done after dialog has been opened. H5P.jQuery(self).trigger('dialog-opened', [$dialog]); $dialog.focus(); }, 1); }; /** * Closes the dialog. */ self.close = function () { $dialog.removeClass('h5p-open'); // Fade out setTimeout(function () { $dialog.remove(); H5P.jQuery(self).trigger('dialog-closed', [$dialog]); $element.attr('tabindex', '-1'); if ($returnElement) { $returnElement.focus(); } else if(self.activeElement) { self.activeElement.focus(); } else { $element.focus(); } }, 200); }; }; /** * Gather copyright information for the given content. * * @param {Object} instance * H5P instance to get copyright information for. * @param {Object} parameters * Parameters of the content instance. * @param {number} contentId * Identifies the H5P content * @param {Object} metadata * Metadata of the content instance. * @returns {string} Copyright information. */ H5P.getCopyrights = function (instance, parameters, contentId, metadata) { var copyrights; if (instance.getCopyrights !== undefined) { try { // Use the instance's own copyright generator copyrights = instance.getCopyrights(); } catch (err) { // Failed, prevent crashing page. } } if (copyrights === undefined) { // Create a generic flat copyright list copyrights = new H5P.ContentCopyrights(); H5P.findCopyrights(copyrights, parameters, contentId); } var metadataCopyrights = H5P.buildMetadataCopyrights(metadata, instance.libraryInfo.machineName); if (metadataCopyrights !== undefined) { copyrights.addMediaInFront(metadataCopyrights); } if (copyrights !== undefined) { // Convert to string copyrights = copyrights.toString(); } return copyrights; }; /** * Gather a flat list of copyright information from the given parameters. * * @param {H5P.ContentCopyrights} info * Used to collect all information in. * @param {(Object|Array)} parameters * To search for file objects in. * @param {number} contentId * Used to insert thumbnails for images. * @param {Object} extras - Extras. * @param {object} extras.metadata - Metadata * @param {object} extras.machineName - Library name of some kind. * Metadata of the content instance. */ H5P.findCopyrights = function (info, parameters, contentId, extras) { // If extras are if (extras) { extras.params = parameters; buildFromMetadata(extras, extras.machineName, contentId); } var lastContentTypeName; // Cycle through parameters for (var field in parameters) { if (!parameters.hasOwnProperty(field)) { continue; // Do not check } /** * @deprecated This hack should be removed after 2017-11-01 * The code that was using this was removed by HFP-574 * This note was seen on 2018-04-04, and consultation with * higher authorities lead to keeping the code for now ;-) */ if (field === 'overrideSettings') { console.warn("The semantics field 'overrideSettings' is DEPRECATED and should not be used."); console.warn(parameters); continue; } var value = parameters[field]; if (value && value.library && typeof value.library === 'string') { lastContentTypeName = value.library.split(' ')[0]; } else if (value && value.library && typeof value.library === 'object') { lastContentTypeName = (value.library.library && typeof value.library.library === 'string') ? value.library.library.split(' ')[0] : lastContentTypeName; } if (value instanceof Array) { // Cycle through array H5P.findCopyrights(info, value, contentId); } else if (value instanceof Object) { buildFromMetadata(value, lastContentTypeName, contentId); // Check if object is a file with copyrights (old core) if (value.copyright === undefined || value.copyright.license === undefined || value.path === undefined || value.mime === undefined) { // Nope, cycle throught object H5P.findCopyrights(info, value, contentId); } else { // Found file, add copyrights var copyrights = new H5P.MediaCopyright(value.copyright); if (value.width !== undefined && value.height !== undefined) { copyrights.setThumbnail(new H5P.Thumbnail(H5P.getPath(value.path, contentId), value.width, value.height)); } info.addMedia(copyrights); } } } function buildFromMetadata(data, name, contentId) { if (data.metadata) { const metadataCopyrights = H5P.buildMetadataCopyrights(data.metadata, name); if (metadataCopyrights !== undefined) { if (data.params && data.params.contentName === 'Image' && data.params.file) { const path = data.params.file.path; const width = data.params.file.width; const height = data.params.file.height; metadataCopyrights.setThumbnail(new H5P.Thumbnail(H5P.getPath(path, contentId), width, height, data.params.alt)); } info.addMedia(metadataCopyrights); } } } }; H5P.buildMetadataCopyrights = function (metadata) { if (metadata && metadata.license !== undefined && metadata.license !== 'U') { var dataset = { contentType: metadata.contentType, title: metadata.title, author: (metadata.authors && metadata.authors.length > 0) ? metadata.authors.map(function (author) { return (author.role) ? author.name + ' (' + author.role + ')' : author.name; }).join(', ') : undefined, source: metadata.source, year: (metadata.yearFrom) ? (metadata.yearFrom + ((metadata.yearTo) ? '-' + metadata.yearTo: '')) : undefined, license: metadata.license, version: metadata.licenseVersion, licenseExtras: metadata.licenseExtras, changes: (metadata.changes && metadata.changes.length > 0) ? metadata.changes.map(function (change) { return change.log + (change.author ? ', ' + change.author : '') + (change.date ? ', ' + change.date : ''); }).join(' / ') : undefined }; return new H5P.MediaCopyright(dataset); } }; /** * Display a dialog containing the download button and copy button. * * @param {H5P.jQuery} $element * @param {Object} contentData * @param {Object} library * @param {Object} instance * @param {number} contentId */ H5P.openReuseDialog = function ($element, contentData, library, instance, contentId) { let html = ''; if (contentData.displayOptions.export) { html += ''; } if (contentData.displayOptions.export && contentData.displayOptions.copy) { html += '
    or
    '; } if (contentData.displayOptions.copy) { html += ''; } const dialog = new H5P.Dialog('reuse', H5P.t('reuseContent'), html, $element); // Selecting embed code when dialog is opened H5P.jQuery(dialog).on('dialog-opened', function (e, $dialog) { H5P.jQuery('More Info').click(function (e) { e.stopPropagation(); }).appendTo($dialog.find('h2')); $dialog.find('.h5p-download-button').click(function () { window.location.href = contentData.exportUrl; instance.triggerXAPI('downloaded'); dialog.close(); }); $dialog.find('.h5p-copy-button').click(function () { const item = new H5P.ClipboardItem(library); item.contentId = contentId; H5P.setClipboard(item); instance.triggerXAPI('copied'); dialog.close(); H5P.attachToastTo( H5P.jQuery('.h5p-content:first')[0], H5P.t('contentCopied'), { position: { horizontal: 'centered', vertical: 'centered', noOverflowX: true } } ); }); H5P.trigger(instance, 'resize'); }).on('dialog-closed', function () { H5P.trigger(instance, 'resize'); }); dialog.open(); }; /** * Display a dialog containing the embed code. * * @param {H5P.jQuery} $element * Element to insert dialog after. * @param {string} embedCode * The embed code. * @param {string} resizeCode * The advanced resize code * @param {Object} size * The content's size. * @param {number} size.width * @param {number} size.height */ H5P.openEmbedDialog = function ($element, embedCode, resizeCode, size, instance) { var fullEmbedCode = embedCode + resizeCode; var dialog = new H5P.Dialog('embed', H5P.t('embed'), '' + H5P.t('size') + ': × px
    ' + H5P.t('showAdvanced') + '

    ' + H5P.t('advancedHelp') + '

    ', $element); // Selecting embed code when dialog is opened H5P.jQuery(dialog).on('dialog-opened', function (event, $dialog) { var $inner = $dialog.find('.h5p-inner'); var $scroll = $inner.find('.h5p-scroll-content'); var diff = $scroll.outerHeight() - $scroll.innerHeight(); var positionInner = function () { H5P.trigger(instance, 'resize'); }; // Handle changing of width/height var $w = $dialog.find('.h5p-embed-size:eq(0)'); var $h = $dialog.find('.h5p-embed-size:eq(1)'); var getNum = function ($e, d) { var num = parseFloat($e.val()); if (isNaN(num)) { return d; } return Math.ceil(num); }; var updateEmbed = function () { $dialog.find('.h5p-embed-code-container:first').val(fullEmbedCode.replace(':w', getNum($w, size.width)).replace(':h', getNum($h, size.height))); }; $w.change(updateEmbed); $h.change(updateEmbed); updateEmbed(); // Select text and expand textareas $dialog.find('.h5p-embed-code-container').each(function () { H5P.jQuery(this).css('height', this.scrollHeight + 'px').focus(function () { H5P.jQuery(this).select(); }); }); $dialog.find('.h5p-embed-code-container').eq(0).select(); positionInner(); // Expand advanced embed var expand = function () { var $expander = H5P.jQuery(this); var $content = $expander.next(); if ($content.is(':visible')) { $expander.removeClass('h5p-open').text(H5P.t('showAdvanced')).attr('aria-expanded', 'true'); $content.hide(); } else { $expander.addClass('h5p-open').text(H5P.t('hideAdvanced')).attr('aria-expanded', 'false'); $content.show(); } $dialog.find('.h5p-embed-code-container').each(function () { H5P.jQuery(this).css('height', this.scrollHeight + 'px'); }); positionInner(); }; $dialog.find('.h5p-expander').click(expand).keypress(function (event) { if (event.keyCode === 32) { expand.apply(this); return false; } }); }).on('dialog-closed', function () { H5P.trigger(instance, 'resize'); }); dialog.open(); }; /** * Show a toast message. * * The reference element could be dom elements the toast should be attached to, * or e.g. the document body for general toast messages. * * @param {DOM} element Reference element to show toast message for. * @param {string} message Message to show. * @param {object} [config] Configuration. * @param {string} [config.style=h5p-toast] Style name for the tooltip. * @param {number} [config.duration=3000] Toast message length in ms. * @param {object} [config.position] Relative positioning of the toast. * @param {string} [config.position.horizontal=centered] [before|left|centered|right|after]. * @param {string} [config.position.vertical=below] [above|top|centered|bottom|below]. * @param {number} [config.position.offsetHorizontal=0] Extra horizontal offset. * @param {number} [config.position.offsetVertical=0] Extra vetical offset. * @param {boolean} [config.position.noOverflowLeft=false] True to prevent overflow left. * @param {boolean} [config.position.noOverflowRight=false] True to prevent overflow right. * @param {boolean} [config.position.noOverflowTop=false] True to prevent overflow top. * @param {boolean} [config.position.noOverflowBottom=false] True to prevent overflow bottom. * @param {boolean} [config.position.noOverflowX=false] True to prevent overflow left and right. * @param {boolean} [config.position.noOverflowY=false] True to prevent overflow top and bottom. * @param {object} [config.position.overflowReference=document.body] DOM reference for overflow. */ H5P.attachToastTo = function (element, message, config) { if (element === undefined || message === undefined) { return; } const eventPath = function (evt) { var path = (evt.composedPath && evt.composedPath()) || evt.path; var target = evt.target; if (path != null) { // Safari doesn't include Window, but it should. return (path.indexOf(window) < 0) ? path.concat(window) : path; } if (target === window) { return [window]; } function getParents(node, memo) { memo = memo || []; var parentNode = node.parentNode; if (!parentNode) { return memo; } else { return getParents(parentNode, memo.concat(parentNode)); } } return [target].concat(getParents(target), window); }; /** * Handle click while toast is showing. */ const clickHandler = function (event) { /* * A common use case will be to attach toasts to buttons that are clicked. * The click would remove the toast message instantly without this check. * Children of the clicked element are also ignored. */ var path = eventPath(event); if (path.indexOf(element) !== -1) { return; } clearTimeout(timer); removeToast(); }; /** * Remove the toast message. */ const removeToast = function () { document.removeEventListener('click', clickHandler); if (toast.parentNode) { toast.parentNode.removeChild(toast); } }; /** * Get absolute coordinates for the toast. * * @param {DOM} element Reference element to show toast message for. * @param {DOM} toast Toast element. * @param {object} [position={}] Relative positioning of the toast message. * @param {string} [position.horizontal=centered] [before|left|centered|right|after]. * @param {string} [position.vertical=below] [above|top|centered|bottom|below]. * @param {number} [position.offsetHorizontal=0] Extra horizontal offset. * @param {number} [position.offsetVertical=0] Extra vetical offset. * @param {boolean} [position.noOverflowLeft=false] True to prevent overflow left. * @param {boolean} [position.noOverflowRight=false] True to prevent overflow right. * @param {boolean} [position.noOverflowTop=false] True to prevent overflow top. * @param {boolean} [position.noOverflowBottom=false] True to prevent overflow bottom. * @param {boolean} [position.noOverflowX=false] True to prevent overflow left and right. * @param {boolean} [position.noOverflowY=false] True to prevent overflow top and bottom. * @return {object} */ const getToastCoordinates = function (element, toast, position) { position = position || {}; position.offsetHorizontal = position.offsetHorizontal || 0; position.offsetVertical = position.offsetVertical || 0; const toastRect = toast.getBoundingClientRect(); const elementRect = element.getBoundingClientRect(); let left = 0; let top = 0; // Compute horizontal position switch (position.horizontal) { case 'before': left = elementRect.left - toastRect.width - position.offsetHorizontal; break; case 'after': left = elementRect.left + elementRect.width + position.offsetHorizontal; break; case 'left': left = elementRect.left + position.offsetHorizontal; break; case 'right': left = elementRect.left + elementRect.width - toastRect.width - position.offsetHorizontal; break; case 'centered': left = elementRect.left + elementRect.width / 2 - toastRect.width / 2 + position.offsetHorizontal; break; default: left = elementRect.left + elementRect.width / 2 - toastRect.width / 2 + position.offsetHorizontal; } // Compute vertical position switch (position.vertical) { case 'above': top = elementRect.top - toastRect.height - position.offsetVertical; break; case 'below': top = elementRect.top + elementRect.height + position.offsetVertical; break; case 'top': top = elementRect.top + position.offsetVertical; break; case 'bottom': top = elementRect.top + elementRect.height - toastRect.height - position.offsetVertical; break; case 'centered': top = elementRect.top + elementRect.height / 2 - toastRect.height / 2 + position.offsetVertical; break; default: top = elementRect.top + elementRect.height + position.offsetVertical; } // Prevent overflow const overflowElement = document.body; const bounds = overflowElement.getBoundingClientRect(); if ((position.noOverflowLeft || position.noOverflowX) && (left < bounds.x)) { left = bounds.x; } if ((position.noOverflowRight || position.noOverflowX) && ((left + toastRect.width) > (bounds.x + bounds.width))) { left = bounds.x + bounds.width - toastRect.width; } if ((position.noOverflowTop || position.noOverflowY) && (top < bounds.y)) { top = bounds.y; } if ((position.noOverflowBottom || position.noOverflowY) && ((top + toastRect.height) > (bounds.y + bounds.height))) { left = bounds.y + bounds.height - toastRect.height; } return {left: left, top: top}; }; // Sanitization config = config || {}; config.style = config.style || 'h5p-toast'; config.duration = config.duration || 3000; // Build toast const toast = document.createElement('div'); toast.setAttribute('id', config.style); toast.classList.add('h5p-toast-disabled'); toast.classList.add(config.style); const msg = document.createElement('span'); msg.innerHTML = message; toast.appendChild(msg); document.body.appendChild(toast); // The message has to be set before getting the coordinates const coordinates = getToastCoordinates(element, toast, config.position); toast.style.left = Math.round(coordinates.left) + 'px'; toast.style.top = Math.round(coordinates.top) + 'px'; toast.classList.remove('h5p-toast-disabled'); const timer = setTimeout(removeToast, config.duration); // The toast can also be removed by clicking somewhere document.addEventListener('click', clickHandler); }; /** * Copyrights for a H5P Content Library. * * @class */ H5P.ContentCopyrights = function () { var label; var media = []; var content = []; /** * Set label. * * @param {string} newLabel */ this.setLabel = function (newLabel) { label = newLabel; }; /** * Add sub content. * * @param {H5P.MediaCopyright} newMedia */ this.addMedia = function (newMedia) { if (newMedia !== undefined) { media.push(newMedia); } }; /** * Add sub content in front. * * @param {H5P.MediaCopyright} newMedia */ this.addMediaInFront = function (newMedia) { if (newMedia !== undefined) { media.unshift(newMedia); } }; /** * Add sub content. * * @param {H5P.ContentCopyrights} newContent */ this.addContent = function (newContent) { if (newContent !== undefined) { content.push(newContent); } }; /** * Print content copyright. * * @returns {string} HTML. */ this.toString = function () { var html = ''; // Add media rights for (var i = 0; i < media.length; i++) { html += media[i]; } // Add sub content rights for (i = 0; i < content.length; i++) { html += content[i]; } if (html !== '') { // Add a label to this info if (label !== undefined) { html = '

    ' + label + '

    ' + html; } // Add wrapper html = '
    ' + html + '
    '; } return html; }; }; /** * A ordered list of copyright fields for media. * * @class * @param {Object} copyright * Copyright information fields. * @param {Object} [labels] * Translation of labels. * @param {Array} [order] * Order of the fields. * @param {Object} [extraFields] * Add extra copyright fields. */ H5P.MediaCopyright = function (copyright, labels, order, extraFields) { var thumbnail; var list = new H5P.DefinitionList(); /** * Get translated label for field. * * @private * @param {string} fieldName * @returns {string} */ var getLabel = function (fieldName) { if (labels === undefined || labels[fieldName] === undefined) { return H5P.t(fieldName); } return labels[fieldName]; }; /** * Get humanized value for the license field. * * @private * @param {string} license * @param {string} [version] * @returns {string} */ var humanizeLicense = function (license, version) { var copyrightLicense = H5P.copyrightLicenses[license]; // Build license string var value = ''; if (!(license === 'PD' && version)) { // Add license label value += (copyrightLicense.hasOwnProperty('label') ? copyrightLicense.label : copyrightLicense); } // Check for version info var versionInfo; if (copyrightLicense.versions) { if (copyrightLicense.versions.default && (!version || !copyrightLicense.versions[version])) { version = copyrightLicense.versions.default; } if (version && copyrightLicense.versions[version]) { versionInfo = copyrightLicense.versions[version]; } } if (versionInfo) { // Add license version if (value) { value += ' '; } value += (versionInfo.hasOwnProperty('label') ? versionInfo.label : versionInfo); } // Add link if specified var link; if (copyrightLicense.hasOwnProperty('link')) { link = copyrightLicense.link.replace(':version', copyrightLicense.linkVersions ? copyrightLicense.linkVersions[version] : version); } else if (versionInfo && copyrightLicense.hasOwnProperty('link')) { link = versionInfo.link; } if (link) { value = '' + value + ''; } // Generate parenthesis var parenthesis = ''; if (license !== 'PD' && license !== 'C') { parenthesis += license; } if (version && version !== 'CC0 1.0') { if (parenthesis && license !== 'GNU GPL') { parenthesis += ' '; } parenthesis += version; } if (parenthesis) { value += ' (' + parenthesis + ')'; } if (license === 'C') { value += ' ©'; } return value; }; if (copyright !== undefined) { // Add the extra fields for (var field in extraFields) { if (extraFields.hasOwnProperty(field)) { copyright[field] = extraFields[field]; } } if (order === undefined) { // Set default order order = ['contentType', 'title', 'license', 'author', 'year', 'source', 'licenseExtras', 'changes']; } for (var i = 0; i < order.length; i++) { var fieldName = order[i]; if (copyright[fieldName] !== undefined && copyright[fieldName] !== '') { var humanValue = copyright[fieldName]; if (fieldName === 'license') { humanValue = humanizeLicense(copyright.license, copyright.version); } if (fieldName === 'source') { humanValue = (humanValue) ? '' + humanValue + '' : undefined; } list.add(new H5P.Field(getLabel(fieldName), humanValue)); } } } /** * Set thumbnail. * * @param {H5P.Thumbnail} newThumbnail */ this.setThumbnail = function (newThumbnail) { thumbnail = newThumbnail; }; /** * Checks if this copyright is undisclosed. * I.e. only has the license attribute set, and it's undisclosed. * * @returns {boolean} */ this.undisclosed = function () { if (list.size() === 1) { var field = list.get(0); if (field.getLabel() === getLabel('license') && field.getValue() === humanizeLicense('U')) { return true; } } return false; }; /** * Print media copyright. * * @returns {string} HTML. */ this.toString = function () { var html = ''; if (this.undisclosed()) { return html; // No need to print a copyright with a single undisclosed license. } if (thumbnail !== undefined) { html += thumbnail; } html += list; if (html !== '') { html = ''; } return html; }; }; /** * A simple and elegant class for creating thumbnails of images. * * @class * @param {string} source * @param {number} width * @param {number} height * @param {string} alt * alternative text for the thumbnail */ H5P.Thumbnail = function (source, width, height, alt) { var thumbWidth, thumbHeight = 100; if (width !== undefined) { thumbWidth = Math.round(thumbHeight * (width / height)); } /** * Print thumbnail. * * @returns {string} HTML. */ this.toString = function () { return '' + (alt ? alt : '') + ''; }; }; /** * Simple data structure class for storing a single field. * * @class * @param {string} label * @param {string} value */ H5P.Field = function (label, value) { /** * Public. Get field label. * * @returns {String} */ this.getLabel = function () { return label; }; /** * Public. Get field value. * * @returns {String} */ this.getValue = function () { return value; }; }; /** * Simple class for creating a definition list. * * @class */ H5P.DefinitionList = function () { var fields = []; /** * Add field to list. * * @param {H5P.Field} field */ this.add = function (field) { fields.push(field); }; /** * Get Number of fields. * * @returns {number} */ this.size = function () { return fields.length; }; /** * Get field at given index. * * @param {number} index * @returns {H5P.Field} */ this.get = function (index) { return fields[index]; }; /** * Print definition list. * * @returns {string} HTML. */ this.toString = function () { var html = ''; for (var i = 0; i < fields.length; i++) { var field = fields[i]; html += '
    ' + field.getLabel() + '
    ' + field.getValue() + '
    '; } return (html === '' ? html : '
    ' + html + '
    '); }; }; /** * THIS FUNCTION/CLASS IS DEPRECATED AND WILL BE REMOVED. * * Helper object for keeping coordinates in the same format all over. * * @deprecated * Will be removed march 2016. * @class * @param {number} x * @param {number} y * @param {number} w * @param {number} h */ H5P.Coords = function (x, y, w, h) { if ( !(this instanceof H5P.Coords) ) return new H5P.Coords(x, y, w, h); /** @member {number} */ this.x = 0; /** @member {number} */ this.y = 0; /** @member {number} */ this.w = 1; /** @member {number} */ this.h = 1; if (typeof(x) === 'object') { this.x = x.x; this.y = x.y; this.w = x.w; this.h = x.h; } else { if (x !== undefined) { this.x = x; } if (y !== undefined) { this.y = y; } if (w !== undefined) { this.w = w; } if (h !== undefined) { this.h = h; } } return this; }; /** * Parse library string into values. * * @param {string} library * library in the format "machineName majorVersion.minorVersion" * @returns {Object} * library as an object with machineName, majorVersion and minorVersion properties * return false if the library parameter is invalid */ H5P.libraryFromString = function (library) { var regExp = /(.+)\s(\d+)\.(\d+)$/g; var res = regExp.exec(library); if (res !== null) { return { 'machineName': res[1], 'majorVersion': parseInt(res[2]), 'minorVersion': parseInt(res[3]) }; } else { return false; } }; /** * Get the path to the library * * @param {string} library * The library identifier in the format "machineName-majorVersion.minorVersion". * @returns {string} * The full path to the library. */ H5P.getLibraryPath = function (library) { if (H5PIntegration.urlLibraries !== undefined) { // This is an override for those implementations that has a different libraries URL, e.g. Moodle return H5PIntegration.urlLibraries + '/' + library; } else { return H5PIntegration.url + '/libraries/' + library; } }; /** * Recursivly clone the given object. * * @param {Object|Array} object * Object to clone. * @param {boolean} [recursive] * @returns {Object|Array} * A clone of object. */ H5P.cloneObject = function (object, recursive) { // TODO: Consider if this needs to be in core. Doesn't $.extend do the same? var clone = object instanceof Array ? [] : {}; for (var i in object) { if (object.hasOwnProperty(i)) { if (recursive !== undefined && recursive && typeof object[i] === 'object') { clone[i] = H5P.cloneObject(object[i], recursive); } else { clone[i] = object[i]; } } } return clone; }; /** * Remove all empty spaces before and after the value. * * @param {string} value * @returns {string} */ H5P.trim = function (value) { return value.replace(/^\s+|\s+$/g, ''); // TODO: Only include this or String.trim(). What is best? // I'm leaning towards implementing the missing ones: http://kangax.github.io/compat-table/es5/ // So should we make this function deprecated? }; /** * Recursive function that detects deep empty structures. * * @param {*} value * @returns {bool} */ H5P.isEmpty = value => { if (!value && value !== 0 && value !== false) { return true; // undefined, null, NaN and empty strings. } else if (Array.isArray(value)) { for (let i = 0; i < value.length; i++) { if (!H5P.isEmpty(value[i])) { return false; // Array contains a non-empty value } } return true; // Empty array } else if (typeof value === 'object') { for (let prop in value) { if (value.hasOwnProperty(prop) && !H5P.isEmpty(value[prop])) { return false; // Object contains a non-empty value } } return true; // Empty object } return false; }; /** * Check if JavaScript path/key is loaded. * * @param {string} path * @returns {boolean} */ H5P.jsLoaded = function (path) { H5PIntegration.loadedJs = H5PIntegration.loadedJs || []; return H5P.jQuery.inArray(path, H5PIntegration.loadedJs) !== -1; }; /** * Check if styles path/key is loaded. * * @param {string} path * @returns {boolean} */ H5P.cssLoaded = function (path) { H5PIntegration.loadedCss = H5PIntegration.loadedCss || []; return H5P.jQuery.inArray(path, H5PIntegration.loadedCss) !== -1; }; /** * Shuffle an array in place. * * @param {Array} array * Array to shuffle * @returns {Array} * The passed array is returned for chaining. */ H5P.shuffleArray = function (array) { // TODO: Consider if this should be a part of core. I'm guessing very few libraries are going to use it. if (!(array instanceof Array)) { return; } var i = array.length, j, tempi, tempj; if ( i === 0 ) return false; while ( --i ) { j = Math.floor( Math.random() * ( i + 1 ) ); tempi = array[i]; tempj = array[j]; array[i] = tempj; array[j] = tempi; } return array; }; /** * Post finished results for user. * * @deprecated * Do not use this function directly, trigger the finish event instead. * Will be removed march 2016 * @param {number} contentId * Identifies the content * @param {number} score * Achieved score/points * @param {number} maxScore * The maximum score/points that can be achieved * @param {number} [time] * Reported time consumption/usage */ H5P.setFinished = function (contentId, score, maxScore, time) { var validScore = typeof score === 'number' || score instanceof Number; if (validScore && H5PIntegration.postUserStatistics === true) { /** * Return unix timestamp for the given JS Date. * * @private * @param {Date} date * @returns {Number} */ var toUnix = function (date) { return Math.round(date.getTime() / 1000); }; // Post the results const data = { contentId: contentId, score: score, maxScore: maxScore, opened: toUnix(H5P.opened[contentId]), finished: toUnix(new Date()), time: time }; H5P.jQuery.post(H5PIntegration.ajax.setFinished, data) .fail(function () { H5P.offlineRequestQueue.add(H5PIntegration.ajax.setFinished, data); }); } }; // Add indexOf to browsers that lack them. (IEs) if (!Array.prototype.indexOf) { Array.prototype.indexOf = function (needle) { for (var i = 0; i < this.length; i++) { if (this[i] === needle) { return i; } } return -1; }; } // Need to define trim() since this is not available on older IEs, // and trim is used in several libs if (String.prototype.trim === undefined) { String.prototype.trim = function () { return H5P.trim(this); }; } /** * Trigger an event on an instance * * Helper function that triggers an event if the instance supports event handling * * @param {Object} instance * Instance of H5P content * @param {string} eventType * Type of event to trigger * @param {*} data * @param {Object} extras */ H5P.trigger = function (instance, eventType, data, extras) { // Try new event system first if (instance.trigger !== undefined) { instance.trigger(eventType, data, extras); } // Try deprecated event system else if (instance.$ !== undefined && instance.$.trigger !== undefined) { instance.$.trigger(eventType); } }; /** * Register an event handler * * Helper function that registers an event handler for an event type if * the instance supports event handling * * @param {Object} instance * Instance of H5P content * @param {string} eventType * Type of event to listen for * @param {H5P.EventCallback} handler * Callback that gets triggered for events of the specified type */ H5P.on = function (instance, eventType, handler) { // Try new event system first if (instance.on !== undefined) { instance.on(eventType, handler); } // Try deprecated event system else if (instance.$ !== undefined && instance.$.on !== undefined) { instance.$.on(eventType, handler); } }; /** * Generate random UUID * * @returns {string} UUID */ H5P.createUUID = function () { return 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function (char) { var random = Math.random()*16|0, newChar = char === 'x' ? random : (random&0x3|0x8); return newChar.toString(16); }); }; /** * Create title * * @param {string} rawTitle * @param {number} maxLength * @returns {string} */ H5P.createTitle = function (rawTitle, maxLength) { if (!rawTitle) { return ''; } if (maxLength === undefined) { maxLength = 60; } var title = H5P.jQuery('
    ') .text( // Strip tags rawTitle.replace(/(<([^>]+)>)/ig,"") // Escape ).text(); if (title.length > maxLength) { title = title.substr(0, maxLength - 3) + '...'; } return title; }; // Wrap in privates (function ($) { /** * Creates ajax requests for inserting, updateing and deleteing * content user data. * * @private * @param {number} contentId What content to store the data for. * @param {string} dataType Identifies the set of data for this content. * @param {string} subContentId Identifies sub content * @param {function} [done] Callback when ajax is done. * @param {object} [data] To be stored for future use. * @param {boolean} [preload=false] Data is loaded when content is loaded. * @param {boolean} [invalidate=false] Data is invalidated when content changes. * @param {boolean} [async=true] */ function contentUserDataAjax(contentId, dataType, subContentId, done, data, preload, invalidate, async) { if (H5PIntegration.user === undefined) { // Not logged in, no use in saving. done('Not signed in.'); return; } // Moodle patch to let override this method. if (H5P.contentUserDataAjax !== undefined) { return H5P.contentUserDataAjax(contentId, dataType, subContentId, done, data, preload, invalidate, async); } // End of Moodle patch. var options = { url: H5PIntegration.ajax.contentUserData.replace(':contentId', contentId).replace(':dataType', dataType).replace(':subContentId', subContentId ? subContentId : 0), dataType: 'json', async: async === undefined ? true : async }; if (data !== undefined) { options.type = 'POST'; options.data = { data: (data === null ? 0 : data), preload: (preload ? 1 : 0), invalidate: (invalidate ? 1 : 0) }; } else { options.type = 'GET'; } if (done !== undefined) { options.error = function (xhr, error) { done(error); }; options.success = function (response) { if (!response.success) { done(response.message); return; } if (response.data === false || response.data === undefined) { done(); return; } done(undefined, response.data); }; } $.ajax(options); } /** * Get user data for given content. * * @param {number} contentId * What content to get data for. * @param {string} dataId * Identifies the set of data for this content. * @param {function} done * Callback with error and data parameters. * @param {string} [subContentId] * Identifies which data belongs to sub content. */ H5P.getUserData = function (contentId, dataId, done, subContentId) { if (!subContentId) { subContentId = 0; // Default } H5PIntegration.contents = H5PIntegration.contents || {}; var content = H5PIntegration.contents['cid-' + contentId] || {}; var preloadedData = content.contentUserData; if (preloadedData && preloadedData[subContentId] && preloadedData[subContentId][dataId] !== undefined) { if (preloadedData[subContentId][dataId] === 'RESET') { done(undefined, null); return; } try { done(undefined, JSON.parse(preloadedData[subContentId][dataId])); } catch (err) { done(err); } } else { contentUserDataAjax(contentId, dataId, subContentId, function (err, data) { if (err || data === undefined) { done(err, data); return; // Error or no data } // Cache in preloaded if (content.contentUserData === undefined) { content.contentUserData = preloadedData = {}; } if (preloadedData[subContentId] === undefined) { preloadedData[subContentId] = {}; } preloadedData[subContentId][dataId] = data; // Done. Try to decode JSON try { done(undefined, JSON.parse(data)); } catch (e) { done(e); } }); } }; /** * Async error handling. * * @callback H5P.ErrorCallback * @param {*} error */ /** * Set user data for given content. * * @param {number} contentId * What content to get data for. * @param {string} dataId * Identifies the set of data for this content. * @param {Object} data * The data that is to be stored. * @param {Object} [extras] * Extra properties * @param {string} [extras.subContentId] * Identifies which data belongs to sub content. * @param {boolean} [extras.preloaded=true] * If the data should be loaded when content is loaded. * @param {boolean} [extras.deleteOnChange=false] * If the data should be invalidated when the content changes. * @param {H5P.ErrorCallback} [extras.errorCallback] * Callback with error as parameters. * @param {boolean} [extras.async=true] */ H5P.setUserData = function (contentId, dataId, data, extras) { var options = H5P.jQuery.extend(true, {}, { subContentId: 0, preloaded: true, deleteOnChange: false, async: true }, extras); try { data = JSON.stringify(data); } catch (err) { if (options.errorCallback) { options.errorCallback(err); } return; // Failed to serialize. } var content = H5PIntegration.contents['cid-' + contentId]; if (content === undefined) { content = H5PIntegration.contents['cid-' + contentId] = {}; } if (!content.contentUserData) { content.contentUserData = {}; } var preloadedData = content.contentUserData; if (preloadedData[options.subContentId] === undefined) { preloadedData[options.subContentId] = {}; } if (data === preloadedData[options.subContentId][dataId]) { return; // No need to save this twice. } preloadedData[options.subContentId][dataId] = data; contentUserDataAjax(contentId, dataId, options.subContentId, function (error) { if (options.errorCallback && error) { options.errorCallback(error); } }, data, options.preloaded, options.deleteOnChange, options.async); }; /** * Delete user data for given content. * * @param {number} contentId * What content to remove data for. * @param {string} dataId * Identifies the set of data for this content. * @param {string} [subContentId] * Identifies which data belongs to sub content. */ H5P.deleteUserData = function (contentId, dataId, subContentId) { if (!subContentId) { subContentId = 0; // Default } // Remove from preloaded/cache var preloadedData = H5PIntegration.contents['cid-' + contentId].contentUserData; if (preloadedData && preloadedData[subContentId] && preloadedData[subContentId][dataId]) { delete preloadedData[subContentId][dataId]; } contentUserDataAjax(contentId, dataId, subContentId, undefined, null); }; /** * Function for getting content for a certain ID * * @param {number} contentId * @return {Object} */ H5P.getContentForInstance = function (contentId) { var key = 'cid-' + contentId; var exists = H5PIntegration && H5PIntegration.contents && H5PIntegration.contents[key]; return exists ? H5PIntegration.contents[key] : undefined; }; /** * Prepares the content parameters for storing in the clipboard. * * @class * @param {Object} parameters The parameters for the content to store * @param {string} [genericProperty] If only part of the parameters are generic, which part * @param {string} [specificKey] If the parameters are specific, what content type does it fit * @returns {Object} Ready for the clipboard */ H5P.ClipboardItem = function (parameters, genericProperty, specificKey) { var self = this; /** * Set relative dimensions when params contains a file with a width and a height. * Very useful to be compatible with wysiwyg editors. * * @private */ var setDimensionsFromFile = function () { if (!self.generic) { return; } var params = self.specific[self.generic]; if (!params.params.file || !params.params.file.width || !params.params.file.height) { return; } self.width = 20; // % self.height = (params.params.file.height / params.params.file.width) * self.width; }; if (!genericProperty) { genericProperty = 'action'; parameters = { action: parameters }; } self.specific = parameters; if (genericProperty && parameters[genericProperty]) { self.generic = genericProperty; } if (specificKey) { self.from = specificKey; } if (window.H5PEditor && H5PEditor.contentId) { self.contentId = H5PEditor.contentId; } if (!self.specific.width && !self.specific.height) { setDimensionsFromFile(); } }; /** * Store item in the H5P Clipboard. * * @param {H5P.ClipboardItem|*} clipboardItem */ H5P.clipboardify = function (clipboardItem) { if (!(clipboardItem instanceof H5P.ClipboardItem)) { clipboardItem = new H5P.ClipboardItem(clipboardItem); } H5P.setClipboard(clipboardItem); }; /** * Retrieve parsed clipboard data. * * @return {Object} */ H5P.getClipboard = function () { return parseClipboard(); }; /** * Set item in the H5P Clipboard. * * @param {H5P.ClipboardItem|object} clipboardItem - Data to be set. */ H5P.setClipboard = function (clipboardItem) { localStorage.setItem('h5pClipboard', JSON.stringify(clipboardItem)); // Trigger an event so all 'Paste' buttons may be enabled. H5P.externalDispatcher.trigger('datainclipboard', {reset: false}); }; /** * Get config for a library * * @param string machineName * @return Object */ H5P.getLibraryConfig = function (machineName) { var hasConfig = H5PIntegration.libraryConfig && H5PIntegration.libraryConfig[machineName]; return hasConfig ? H5PIntegration.libraryConfig[machineName] : {}; }; /** * Get item from the H5P Clipboard. * * @private * @return {Object} */ var parseClipboard = function () { var clipboardData = localStorage.getItem('h5pClipboard'); if (!clipboardData) { return; } // Try to parse clipboard dat try { clipboardData = JSON.parse(clipboardData); } catch (err) { console.error('Unable to parse JSON from clipboard.', err); return; } // Update file URLs and reset content Ids recursiveUpdate(clipboardData.specific, function (path) { var isTmpFile = (path.substr(-4, 4) === '#tmp'); if (!isTmpFile && clipboardData.contentId && !path.match(/^https?:\/\//i)) { // Comes from existing content let prefix; if (H5PEditor.contentId) { // .. to existing content prefix = '../' + clipboardData.contentId + '/'; } else { // .. to new content prefix = (H5PEditor.contentRelUrl ? H5PEditor.contentRelUrl : '../content/') + clipboardData.contentId + '/'; } return path.substr(0, prefix.length) === prefix ? path : prefix + path; } return path; // Will automatically be looked for in tmp folder }); if (clipboardData.generic) { // Use reference instead of key clipboardData.generic = clipboardData.specific[clipboardData.generic]; } return clipboardData; }; /** * Update file URLs and reset content IDs. * Useful when copying content. * * @private * @param {object} params Reference * @param {function} handler Modifies the path to work when pasted */ var recursiveUpdate = function (params, handler) { for (var prop in params) { if (params.hasOwnProperty(prop) && params[prop] instanceof Object) { var obj = params[prop]; if (obj.path !== undefined && obj.mime !== undefined) { obj.path = handler(obj.path); } else { if (obj.library !== undefined && obj.subContentId !== undefined) { // Avoid multiple content with same ID delete obj.subContentId; } recursiveUpdate(obj, handler); } } } }; // Init H5P when page is fully loadded $(document).ready(function () { window.addEventListener('storage', function (event) { // Pick up clipboard changes from other tabs if (event.key === 'h5pClipboard') { // Trigger an event so all 'Paste' buttons may be enabled. H5P.externalDispatcher.trigger('datainclipboard', {reset: event.newValue === null}); } }); var ccVersions = { 'default': '4.0', '4.0': H5P.t('licenseCC40'), '3.0': H5P.t('licenseCC30'), '2.5': H5P.t('licenseCC25'), '2.0': H5P.t('licenseCC20'), '1.0': H5P.t('licenseCC10'), }; /** * Maps copyright license codes to their human readable counterpart. * * @type {Object} */ H5P.copyrightLicenses = { 'U': H5P.t('licenseU'), 'CC BY': { label: H5P.t('licenseCCBY'), link: 'http://creativecommons.org/licenses/by/:version', versions: ccVersions }, 'CC BY-SA': { label: H5P.t('licenseCCBYSA'), link: 'http://creativecommons.org/licenses/by-sa/:version', versions: ccVersions }, 'CC BY-ND': { label: H5P.t('licenseCCBYND'), link: 'http://creativecommons.org/licenses/by-nd/:version', versions: ccVersions }, 'CC BY-NC': { label: H5P.t('licenseCCBYNC'), link: 'http://creativecommons.org/licenses/by-nc/:version', versions: ccVersions }, 'CC BY-NC-SA': { label: H5P.t('licenseCCBYNCSA'), link: 'http://creativecommons.org/licenses/by-nc-sa/:version', versions: ccVersions }, 'CC BY-NC-ND': { label: H5P.t('licenseCCBYNCND'), link: 'http://creativecommons.org/licenses/by-nc-nd/:version', versions: ccVersions }, 'CC0 1.0': { label: H5P.t('licenseCC010'), link: 'https://creativecommons.org/publicdomain/zero/1.0/' }, 'GNU GPL': { label: H5P.t('licenseGPL'), link: 'http://www.gnu.org/licenses/gpl-:version-standalone.html', linkVersions: { 'v3': '3.0', 'v2': '2.0', 'v1': '1.0' }, versions: { 'default': 'v3', 'v3': H5P.t('licenseV3'), 'v2': H5P.t('licenseV2'), 'v1': H5P.t('licenseV1') } }, 'PD': { label: H5P.t('licensePD'), versions: { 'CC0 1.0': { label: H5P.t('licenseCC010'), link: 'https://creativecommons.org/publicdomain/zero/1.0/' }, 'CC PDM': { label: H5P.t('licensePDM'), link: 'https://creativecommons.org/publicdomain/mark/1.0/' } } }, 'ODC PDDL': 'Public Domain Dedication and Licence', 'CC PDM': { label: H5P.t('licensePDM'), link: 'https://creativecommons.org/publicdomain/mark/1.0/' }, 'C': H5P.t('licenseC'), }; /** * Indicates if H5P is embedded on an external page using iframe. * @member {boolean} H5P.externalEmbed */ // Relay events to top window. This must be done before H5P.init // since events may be fired on initialization. if (H5P.isFramed && H5P.externalEmbed === false) { H5P.externalDispatcher.on('*', function (event) { window.parent.H5P.externalDispatcher.trigger.call(this, event); }); } /** * Prevent H5P Core from initializing. Must be overriden before document ready. * @member {boolean} H5P.preventInit */ if (!H5P.preventInit) { // Note that this start script has to be an external resource for it to // load in correct order in IE9. H5P.init(document.body); } if (H5PIntegration.saveFreq !== false) { // When was the last state stored var lastStoredOn = 0; // Store the current state of the H5P when leaving the page. var storeCurrentState = function () { // Make sure at least 250 ms has passed since last save var currentTime = new Date().getTime(); if (currentTime - lastStoredOn > 250) { lastStoredOn = currentTime; for (var i = 0; i < H5P.instances.length; i++) { var instance = H5P.instances[i]; if (instance.getCurrentState instanceof Function || typeof instance.getCurrentState === 'function') { var state = instance.getCurrentState(); if (state !== undefined) { // Async is not used to prevent the request from being cancelled. H5P.setUserData(instance.contentId, 'state', state, {deleteOnChange: true, async: false}); } } } } }; // iPad does not support beforeunload, therefore using unload H5P.$window.one('beforeunload unload', function () { // Only want to do this once H5P.$window.off('pagehide beforeunload unload'); storeCurrentState(); }); // pagehide is used on iPad when tabs are switched H5P.$window.on('pagehide', storeCurrentState); } }); })(H5P.jQuery); PK*\{%{%9h5plib/v127/joubel/core/js/h5p-content-upgrade-process.jsnu[/*jshint -W083 */ var H5PUpgrades = H5PUpgrades || {}; H5P.ContentUpgradeProcess = (function (Version) { /** * @class * @namespace H5P */ function ContentUpgradeProcess(name, oldVersion, newVersion, params, id, loadLibrary, done) { var self = this; // Make params possible to work with try { params = JSON.parse(params); if (!(params instanceof Object)) { throw true; } } catch (event) { return done({ type: 'errorParamsBroken', id: id }); } self.loadLibrary = loadLibrary; self.upgrade(name, oldVersion, newVersion, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) { if (err) { err.id = id; return done(err); } done(null, JSON.stringify({params: upgradedParams, metadata: upgradedMetadata})); }); } /** * Run content upgrade. * * @public * @param {string} name * @param {Version} oldVersion * @param {Version} newVersion * @param {Object} params * @param {Object} metadata * @param {Function} done */ ContentUpgradeProcess.prototype.upgrade = function (name, oldVersion, newVersion, params, metadata, done) { var self = this; // Load library details and upgrade routines self.loadLibrary(name, newVersion, function (err, library) { if (err) { return done(err); } if (library.semantics === null) { return done({ type: 'libraryMissing', library: library.name + ' ' + library.version.major + '.' + library.version.minor }); } // Run upgrade routines on params self.processParams(library, oldVersion, newVersion, params, metadata, function (err, params, metadata) { if (err) { return done(err); } // Check if any of the sub-libraries need upgrading asyncSerial(library.semantics, function (index, field, next) { self.processField(field, params[field.name], function (err, upgradedParams) { if (upgradedParams) { params[field.name] = upgradedParams; } next(err); }); }, function (err) { done(err, params, metadata); }); }); }); }; /** * Run upgrade hooks on params. * * @public * @param {Object} library * @param {Version} oldVersion * @param {Version} newVersion * @param {Object} params * @param {Function} next */ ContentUpgradeProcess.prototype.processParams = function (library, oldVersion, newVersion, params, metadata, next) { if (H5PUpgrades[library.name] === undefined) { if (library.upgradesScript) { // Upgrades script should be loaded so the upgrades should be here. return next({ type: 'scriptMissing', library: library.name + ' ' + newVersion }); } // No upgrades script. Move on return next(null, params, metadata); } // Run upgrade hooks. Start by going through major versions asyncSerial(H5PUpgrades[library.name], function (major, minors, nextMajor) { if (major < oldVersion.major || major > newVersion.major) { // Older than the current version or newer than the selected nextMajor(); } else { // Go through the minor versions for this major version asyncSerial(minors, function (minor, upgrade, nextMinor) { minor =+ minor; if (minor <= oldVersion.minor || minor > newVersion.minor) { // Older than or equal to the current version or newer than the selected nextMinor(); } else { // We found an upgrade hook, run it var unnecessaryWrapper = (upgrade.contentUpgrade !== undefined ? upgrade.contentUpgrade : upgrade); try { unnecessaryWrapper(params, function (err, upgradedParams, upgradedExtras) { params = upgradedParams; if (upgradedExtras && upgradedExtras.metadata) { // Optional metadata = upgradedExtras.metadata; } nextMinor(err); }, {metadata: metadata}); } catch (err) { if (console && console.error) { console.error("Error", err.stack); console.error("Error", err.name); console.error("Error", err.message); } next(err); } } }, nextMajor); } }, function (err) { next(err, params, metadata); }); }; /** * Process parameter fields to find and upgrade sub-libraries. * * @public * @param {Object} field * @param {Object} params * @param {Function} done */ ContentUpgradeProcess.prototype.processField = function (field, params, done) { var self = this; if (params === undefined || params === null) { return done(); } switch (field.type) { case 'library': if (params.library === undefined || params.params === undefined) { return done(); } // Look for available upgrades var usedLib = params.library.split(' ', 2); for (var i = 0; i < field.options.length; i++) { var availableLib = (typeof field.options[i] === 'string') ? field.options[i].split(' ', 2) : field.options[i].name.split(' ', 2); if (availableLib[0] === usedLib[0]) { if (availableLib[1] === usedLib[1]) { return done(); // Same version } // We have different versions var usedVer = new Version(usedLib[1]); var availableVer = new Version(availableLib[1]); if (usedVer.major > availableVer.major || (usedVer.major === availableVer.major && usedVer.minor >= availableVer.minor)) { return done({ type: 'errorTooHighVersion', used: usedLib[0] + ' ' + usedVer, supported: availableLib[0] + ' ' + availableVer }); // Larger or same version that's available } // A newer version is available, upgrade params return self.upgrade(availableLib[0], usedVer, availableVer, params.params, params.metadata, function (err, upgradedParams, upgradedMetadata) { if (!err) { params.library = availableLib[0] + ' ' + availableVer.major + '.' + availableVer.minor; params.params = upgradedParams; if (upgradedMetadata) { params.metadata = upgradedMetadata; } } done(err, params); }); } } // Content type was not supporte by the higher version done({ type: 'errorNotSupported', used: usedLib[0] + ' ' + usedVer }); break; case 'group': if (field.fields.length === 1 && field.isSubContent !== true) { // Single field to process, wrapper will be skipped self.processField(field.fields[0], params, function (err, upgradedParams) { if (upgradedParams) { params = upgradedParams; } done(err, params); }); } else { // Go through all fields in the group asyncSerial(field.fields, function (index, subField, next) { var paramsToProcess = params ? params[subField.name] : null; self.processField(subField, paramsToProcess, function (err, upgradedParams) { if (upgradedParams) { params[subField.name] = upgradedParams; } next(err); }); }, function (err) { done(err, params); }); } break; case 'list': // Go trough all params in the list asyncSerial(params, function (index, subParams, next) { self.processField(field.field, subParams, function (err, upgradedParams) { if (upgradedParams) { params[index] = upgradedParams; } next(err); }); }, function (err) { done(err, params); }); break; default: done(); } }; /** * Helps process each property on the given object asynchronously in serial order. * * @private * @param {Object} obj * @param {Function} process * @param {Function} finished */ var asyncSerial = function (obj, process, finished) { var id, isArray = obj instanceof Array; // Keep track of each property that belongs to this object. if (!isArray) { var ids = []; for (id in obj) { if (obj.hasOwnProperty(id)) { ids.push(id); } } } var i = -1; // Keeps track of the current property /** * Private. Process the next property */ var next = function () { id = isArray ? i : ids[i]; process(id, obj[id], check); }; /** * Private. Check if we're done or have an error. * * @param {String} err */ var check = function (err) { // We need to use a real async function in order for the stack to clear. setTimeout(function () { i++; if (i === (isArray ? obj.length : ids.length) || (err !== undefined && err !== null)) { finished(err); } else { next(); } }, 0); }; check(); // Start }; return ContentUpgradeProcess; })(H5P.Version); PK*\d)h5plib/v127/joubel/core/js/h5p-tooltip.jsnu[/*global H5P*/ H5P.Tooltip = (function () { 'use strict'; /** * Create an accessible tooltip * * @param {HTMLElement} triggeringElement The element that should trigger the tooltip * @param {Object} options Options for tooltip * @param {String} options.text The text to be displayed in the tooltip * If not set, will attempt to set text = aria-label of triggeringElement * @param {String[]} options.classes Extra css classes for the tooltip * @param {Boolean} options.ariaHidden Whether the hover should be read by screen readers or not (default: true) * @param {String} options.position Where the tooltip should appear in relation to the * triggeringElement. Accepted positions are "top" (default), "left", "right" and "bottom" * * @constructor */ function Tooltip(triggeringElement, options) { // Make sure tooltips have unique id H5P.Tooltip.uniqueId += 1; const tooltipId = 'h5p-tooltip-' + H5P.Tooltip.uniqueId; // Default options options = options || {}; options.classes = options.classes || []; options.ariaHidden = options.ariaHidden || true; // Initiate state let hover = false; let focus = false; // Function used by the escape listener const escapeFunction = function (e) { if (e.key === 'Escape') { tooltip.classList.remove('h5p-tooltip-visible'); } } // Create element const tooltip = document.createElement('div'); tooltip.classList.add('h5p-tooltip'); tooltip.id = tooltipId; tooltip.role = 'tooltip'; tooltip.innerHTML = options.text || triggeringElement.getAttribute('aria-label') || ''; tooltip.setAttribute('aria-hidden', options.ariaHidden); tooltip.classList.add(...options.classes); triggeringElement.appendChild(tooltip); // Set the initial position based on options.position switch (options.position) { case 'left': tooltip.classList.add('h5p-tooltip-left'); break; case 'right': tooltip.classList.add('h5p-tooltip-right'); break; case 'bottom': tooltip.classList.add('h5p-tooltip-bottom'); break; default: options.position = 'top'; } // Aria-describedby will override aria-hidden if (!options.ariaHidden) { triggeringElement.setAttribute('aria-describedby', tooltipId); } // Add event listeners to triggeringElement triggeringElement.addEventListener('mouseenter', function () { showTooltip(true); }); triggeringElement.addEventListener('mouseleave', function () { hideTooltip(true); }); triggeringElement.addEventListener('focusin', function () { showTooltip(false); }); triggeringElement.addEventListener('focusout', function () { hideTooltip(false); }); // Prevent clicks on the tooltip from triggering onClick listeners on the triggeringElement tooltip.addEventListener('click', function (event) { event.stopPropagation(); }); // Use a mutation observer to listen for aria-label being // changed for the triggering element. If so, update the tooltip. // Mutation observer will be used even if the original elements // doesn't have any aria-label. new MutationObserver(function (mutations) { const ariaLabel = mutations[0].target.getAttribute('aria-label'); if (ariaLabel) { tooltip.innerHTML = options.text || ariaLabel; } }).observe(triggeringElement, { attributes: true, attributeFilter: ['aria-label'], }); // Use intersection observer to adjust the tooltip if it is not completely visible new IntersectionObserver(function (entries) { entries.forEach((entry) => { const target = entry.target; const positionClass = 'h5p-tooltip-' + options.position; // Stop adjusting when hidden (to prevent a false positive next time) if (entry.intersectionRatio === 0) { ['h5p-tooltip-down', 'h5p-tooltip-left', 'h5p-tooltip-right'] .forEach(function (adjustmentClass) { if (adjustmentClass !== positionClass) { target.classList.remove(adjustmentClass); } }); } // Adjust if not completely visible when meant to be else if (entry.intersectionRatio < 1 && (hover || focus)) { const targetRect = entry.boundingClientRect; const intersectionRect = entry.intersectionRect; // Going out of screen on left side if (intersectionRect.left > targetRect.left) { target.classList.add('h5p-tooltip-right'); target.classList.remove(positionClass); } // Going out of screen on right side else if (intersectionRect.right < targetRect.right) { target.classList.add('h5p-tooltip-left'); target.classList.remove(positionClass); } // going out of top of screen if (intersectionRect.top > targetRect.top) { target.classList.add('h5p-tooltip-down'); target.classList.remove(positionClass); } // going out of bottom of screen else if (intersectionRect.bottom < targetRect.bottom) { target.classList.add('h5p-tooltip-up'); target.classList.remove(positionClass); } } }); }).observe(tooltip); /** * Makes the tooltip visible and activates it's functionality * * @param {Boolean} triggeredByHover True if triggered by mouse, false if triggered by focus */ const showTooltip = function (triggeredByHover) { if (triggeredByHover) { hover = true; } else { focus = true; } tooltip.classList.add('h5p-tooltip-visible'); // Add listener to iframe body, as esc keypress would not be detected otherwise document.body.addEventListener('keydown', escapeFunction, true); } /** * Hides the tooltip and removes listeners * * @param {Boolean} triggeredByHover True if triggered by mouse, false if triggered by focus */ const hideTooltip = function (triggeredByHover) { if (triggeredByHover) { hover = false; } else { focus = false; } // Only hide tooltip if neither hovered nor focused if (!hover && !focus) { tooltip.classList.remove('h5p-tooltip-visible'); // Remove iframe body listener document.body.removeEventListener('keydown', escapeFunction, true); } } /** * Change the text displayed by the tooltip * * @param {String} text The new text to be displayed * Set to null to use aria-label of triggeringElement instead */ this.setText = function (text) { options.text = text; tooltip.innerHTML = options.text || triggeringElement.getAttribute('aria-label') || ''; }; /** * Retrieve tooltip * * @return {HTMLElement} */ this.getElement = function () { return tooltip; }; } return Tooltip; })(); H5P.Tooltip.uniqueId = -1; PK*\hV`V`$h5plib/v127/joubel/core/js/jquery.jsnu[/*! jQuery v3.5.1 | (c) JS Foundation and other contributors | jquery.org/license */ !function(e,t){"use strict";"object"==typeof module&&"object"==typeof module.exports?module.exports=e.document?t(e,!0):function(e){if(!e.document)throw new Error("jQuery requires a window with a document");return t(e)}:t(e)}("undefined"!=typeof window?window:this,function(C,e){"use strict";var t=[],r=Object.getPrototypeOf,s=t.slice,g=t.flat?function(e){return t.flat.call(e)}:function(e){return t.concat.apply([],e)},u=t.push,i=t.indexOf,n={},o=n.toString,v=n.hasOwnProperty,a=v.toString,l=a.call(Object),y={},m=function(e){return"function"==typeof e&&"number"!=typeof e.nodeType},x=function(e){return null!=e&&e===e.window},E=C.document,c={type:!0,src:!0,nonce:!0,noModule:!0};function b(e,t,n){var r,i,o=(n=n||E).createElement("script");if(o.text=e,t)for(r in c)(i=t[r]||t.getAttribute&&t.getAttribute(r))&&o.setAttribute(r,i);n.head.appendChild(o).parentNode.removeChild(o)}function w(e){return null==e?e+"":"object"==typeof e||"function"==typeof e?n[o.call(e)]||"object":typeof e}var f="3.5.1",S=function(e,t){return new S.fn.init(e,t)};function p(e){var t=!!e&&"length"in e&&e.length,n=w(e);return!m(e)&&!x(e)&&("array"===n||0===t||"number"==typeof t&&0+~]|"+M+")"+M+"*"),U=new RegExp(M+"|>"),X=new RegExp(F),V=new RegExp("^"+I+"$"),G={ID:new RegExp("^#("+I+")"),CLASS:new RegExp("^\\.("+I+")"),TAG:new RegExp("^("+I+"|[*])"),ATTR:new RegExp("^"+W),PSEUDO:new RegExp("^"+F),CHILD:new RegExp("^:(only|first|last|nth|nth-last)-(child|of-type)(?:\\("+M+"*(even|odd|(([+-]|)(\\d*)n|)"+M+"*(?:([+-]|)"+M+"*(\\d+)|))"+M+"*\\)|)","i"),bool:new RegExp("^(?:"+R+")$","i"),needsContext:new RegExp("^"+M+"*[>+~]|:(even|odd|eq|gt|lt|nth|first|last)(?:\\("+M+"*((?:-\\d)?\\d*)"+M+"*\\)|)(?=[^-]|$)","i")},Y=/HTML$/i,Q=/^(?:input|select|textarea|button)$/i,J=/^h\d$/i,K=/^[^{]+\{\s*\[native \w/,Z=/^(?:#([\w-]+)|(\w+)|\.([\w-]+))$/,ee=/[+~]/,te=new RegExp("\\\\[\\da-fA-F]{1,6}"+M+"?|\\\\([^\\r\\n\\f])","g"),ne=function(e,t){var n="0x"+e.slice(1)-65536;return t||(n<0?String.fromCharCode(n+65536):String.fromCharCode(n>>10|55296,1023&n|56320))},re=/([\0-\x1f\x7f]|^-?\d)|^-$|[^\0-\x1f\x7f-\uFFFF\w-]/g,ie=function(e,t){return t?"\0"===e?"\ufffd":e.slice(0,-1)+"\\"+e.charCodeAt(e.length-1).toString(16)+" ":"\\"+e},oe=function(){T()},ae=be(function(e){return!0===e.disabled&&"fieldset"===e.nodeName.toLowerCase()},{dir:"parentNode",next:"legend"});try{H.apply(t=O.call(p.childNodes),p.childNodes),t[p.childNodes.length].nodeType}catch(e){H={apply:t.length?function(e,t){L.apply(e,O.call(t))}:function(e,t){var n=e.length,r=0;while(e[n++]=t[r++]);e.length=n-1}}}function se(t,e,n,r){var i,o,a,s,u,l,c,f=e&&e.ownerDocument,p=e?e.nodeType:9;if(n=n||[],"string"!=typeof t||!t||1!==p&&9!==p&&11!==p)return n;if(!r&&(T(e),e=e||C,E)){if(11!==p&&(u=Z.exec(t)))if(i=u[1]){if(9===p){if(!(a=e.getElementById(i)))return n;if(a.id===i)return n.push(a),n}else if(f&&(a=f.getElementById(i))&&y(e,a)&&a.id===i)return n.push(a),n}else{if(u[2])return H.apply(n,e.getElementsByTagName(t)),n;if((i=u[3])&&d.getElementsByClassName&&e.getElementsByClassName)return H.apply(n,e.getElementsByClassName(i)),n}if(d.qsa&&!N[t+" "]&&(!v||!v.test(t))&&(1!==p||"object"!==e.nodeName.toLowerCase())){if(c=t,f=e,1===p&&(U.test(t)||z.test(t))){(f=ee.test(t)&&ye(e.parentNode)||e)===e&&d.scope||((s=e.getAttribute("id"))?s=s.replace(re,ie):e.setAttribute("id",s=S)),o=(l=h(t)).length;while(o--)l[o]=(s?"#"+s:":scope")+" "+xe(l[o]);c=l.join(",")}try{return H.apply(n,f.querySelectorAll(c)),n}catch(e){N(t,!0)}finally{s===S&&e.removeAttribute("id")}}}return g(t.replace($,"$1"),e,n,r)}function ue(){var r=[];return function e(t,n){return r.push(t+" ")>b.cacheLength&&delete e[r.shift()],e[t+" "]=n}}function le(e){return e[S]=!0,e}function ce(e){var t=C.createElement("fieldset");try{return!!e(t)}catch(e){return!1}finally{t.parentNode&&t.parentNode.removeChild(t),t=null}}function fe(e,t){var n=e.split("|"),r=n.length;while(r--)b.attrHandle[n[r]]=t}function pe(e,t){var n=t&&e,r=n&&1===e.nodeType&&1===t.nodeType&&e.sourceIndex-t.sourceIndex;if(r)return r;if(n)while(n=n.nextSibling)if(n===t)return-1;return e?1:-1}function de(t){return function(e){return"input"===e.nodeName.toLowerCase()&&e.type===t}}function he(n){return function(e){var t=e.nodeName.toLowerCase();return("input"===t||"button"===t)&&e.type===n}}function ge(t){return function(e){return"form"in e?e.parentNode&&!1===e.disabled?"label"in e?"label"in e.parentNode?e.parentNode.disabled===t:e.disabled===t:e.isDisabled===t||e.isDisabled!==!t&&ae(e)===t:e.disabled===t:"label"in e&&e.disabled===t}}function ve(a){return le(function(o){return o=+o,le(function(e,t){var n,r=a([],e.length,o),i=r.length;while(i--)e[n=r[i]]&&(e[n]=!(t[n]=e[n]))})})}function ye(e){return e&&"undefined"!=typeof e.getElementsByTagName&&e}for(e in d=se.support={},i=se.isXML=function(e){var t=e.namespaceURI,n=(e.ownerDocument||e).documentElement;return!Y.test(t||n&&n.nodeName||"HTML")},T=se.setDocument=function(e){var t,n,r=e?e.ownerDocument||e:p;return r!=C&&9===r.nodeType&&r.documentElement&&(a=(C=r).documentElement,E=!i(C),p!=C&&(n=C.defaultView)&&n.top!==n&&(n.addEventListener?n.addEventListener("unload",oe,!1):n.attachEvent&&n.attachEvent("onunload",oe)),d.scope=ce(function(e){return a.appendChild(e).appendChild(C.createElement("div")),"undefined"!=typeof e.querySelectorAll&&!e.querySelectorAll(":scope fieldset div").length}),d.attributes=ce(function(e){return e.className="i",!e.getAttribute("className")}),d.getElementsByTagName=ce(function(e){return e.appendChild(C.createComment("")),!e.getElementsByTagName("*").length}),d.getElementsByClassName=K.test(C.getElementsByClassName),d.getById=ce(function(e){return a.appendChild(e).id=S,!C.getElementsByName||!C.getElementsByName(S).length}),d.getById?(b.filter.ID=function(e){var t=e.replace(te,ne);return function(e){return e.getAttribute("id")===t}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n=t.getElementById(e);return n?[n]:[]}}):(b.filter.ID=function(e){var n=e.replace(te,ne);return function(e){var t="undefined"!=typeof e.getAttributeNode&&e.getAttributeNode("id");return t&&t.value===n}},b.find.ID=function(e,t){if("undefined"!=typeof t.getElementById&&E){var n,r,i,o=t.getElementById(e);if(o){if((n=o.getAttributeNode("id"))&&n.value===e)return[o];i=t.getElementsByName(e),r=0;while(o=i[r++])if((n=o.getAttributeNode("id"))&&n.value===e)return[o]}return[]}}),b.find.TAG=d.getElementsByTagName?function(e,t){return"undefined"!=typeof t.getElementsByTagName?t.getElementsByTagName(e):d.qsa?t.querySelectorAll(e):void 0}:function(e,t){var n,r=[],i=0,o=t.getElementsByTagName(e);if("*"===e){while(n=o[i++])1===n.nodeType&&r.push(n);return r}return o},b.find.CLASS=d.getElementsByClassName&&function(e,t){if("undefined"!=typeof t.getElementsByClassName&&E)return t.getElementsByClassName(e)},s=[],v=[],(d.qsa=K.test(C.querySelectorAll))&&(ce(function(e){var t;a.appendChild(e).innerHTML="",e.querySelectorAll("[msallowcapture^='']").length&&v.push("[*^$]="+M+"*(?:''|\"\")"),e.querySelectorAll("[selected]").length||v.push("\\["+M+"*(?:value|"+R+")"),e.querySelectorAll("[id~="+S+"-]").length||v.push("~="),(t=C.createElement("input")).setAttribute("name",""),e.appendChild(t),e.querySelectorAll("[name='']").length||v.push("\\["+M+"*name"+M+"*="+M+"*(?:''|\"\")"),e.querySelectorAll(":checked").length||v.push(":checked"),e.querySelectorAll("a#"+S+"+*").length||v.push(".#.+[+~]"),e.querySelectorAll("\\\f"),v.push("[\\r\\n\\f]")}),ce(function(e){e.innerHTML="";var t=C.createElement("input");t.setAttribute("type","hidden"),e.appendChild(t).setAttribute("name","D"),e.querySelectorAll("[name=d]").length&&v.push("name"+M+"*[*^$|!~]?="),2!==e.querySelectorAll(":enabled").length&&v.push(":enabled",":disabled"),a.appendChild(e).disabled=!0,2!==e.querySelectorAll(":disabled").length&&v.push(":enabled",":disabled"),e.querySelectorAll("*,:x"),v.push(",.*:")})),(d.matchesSelector=K.test(c=a.matches||a.webkitMatchesSelector||a.mozMatchesSelector||a.oMatchesSelector||a.msMatchesSelector))&&ce(function(e){d.disconnectedMatch=c.call(e,"*"),c.call(e,"[s!='']:x"),s.push("!=",F)}),v=v.length&&new RegExp(v.join("|")),s=s.length&&new RegExp(s.join("|")),t=K.test(a.compareDocumentPosition),y=t||K.test(a.contains)?function(e,t){var n=9===e.nodeType?e.documentElement:e,r=t&&t.parentNode;return e===r||!(!r||1!==r.nodeType||!(n.contains?n.contains(r):e.compareDocumentPosition&&16&e.compareDocumentPosition(r)))}:function(e,t){if(t)while(t=t.parentNode)if(t===e)return!0;return!1},D=t?function(e,t){if(e===t)return l=!0,0;var n=!e.compareDocumentPosition-!t.compareDocumentPosition;return n||(1&(n=(e.ownerDocument||e)==(t.ownerDocument||t)?e.compareDocumentPosition(t):1)||!d.sortDetached&&t.compareDocumentPosition(e)===n?e==C||e.ownerDocument==p&&y(p,e)?-1:t==C||t.ownerDocument==p&&y(p,t)?1:u?P(u,e)-P(u,t):0:4&n?-1:1)}:function(e,t){if(e===t)return l=!0,0;var n,r=0,i=e.parentNode,o=t.parentNode,a=[e],s=[t];if(!i||!o)return e==C?-1:t==C?1:i?-1:o?1:u?P(u,e)-P(u,t):0;if(i===o)return pe(e,t);n=e;while(n=n.parentNode)a.unshift(n);n=t;while(n=n.parentNode)s.unshift(n);while(a[r]===s[r])r++;return r?pe(a[r],s[r]):a[r]==p?-1:s[r]==p?1:0}),C},se.matches=function(e,t){return se(e,null,null,t)},se.matchesSelector=function(e,t){if(T(e),d.matchesSelector&&E&&!N[t+" "]&&(!s||!s.test(t))&&(!v||!v.test(t)))try{var n=c.call(e,t);if(n||d.disconnectedMatch||e.document&&11!==e.document.nodeType)return n}catch(e){N(t,!0)}return 0":{dir:"parentNode",first:!0}," ":{dir:"parentNode"},"+":{dir:"previousSibling",first:!0},"~":{dir:"previousSibling"}},preFilter:{ATTR:function(e){return e[1]=e[1].replace(te,ne),e[3]=(e[3]||e[4]||e[5]||"").replace(te,ne),"~="===e[2]&&(e[3]=" "+e[3]+" "),e.slice(0,4)},CHILD:function(e){return e[1]=e[1].toLowerCase(),"nth"===e[1].slice(0,3)?(e[3]||se.error(e[0]),e[4]=+(e[4]?e[5]+(e[6]||1):2*("even"===e[3]||"odd"===e[3])),e[5]=+(e[7]+e[8]||"odd"===e[3])):e[3]&&se.error(e[0]),e},PSEUDO:function(e){var t,n=!e[6]&&e[2];return G.CHILD.test(e[0])?null:(e[3]?e[2]=e[4]||e[5]||"":n&&X.test(n)&&(t=h(n,!0))&&(t=n.indexOf(")",n.length-t)-n.length)&&(e[0]=e[0].slice(0,t),e[2]=n.slice(0,t)),e.slice(0,3))}},filter:{TAG:function(e){var t=e.replace(te,ne).toLowerCase();return"*"===e?function(){return!0}:function(e){return e.nodeName&&e.nodeName.toLowerCase()===t}},CLASS:function(e){var t=m[e+" "];return t||(t=new RegExp("(^|"+M+")"+e+"("+M+"|$)"))&&m(e,function(e){return t.test("string"==typeof e.className&&e.className||"undefined"!=typeof e.getAttribute&&e.getAttribute("class")||"")})},ATTR:function(n,r,i){return function(e){var t=se.attr(e,n);return null==t?"!="===r:!r||(t+="","="===r?t===i:"!="===r?t!==i:"^="===r?i&&0===t.indexOf(i):"*="===r?i&&-1:\x20\t\r\n\f]*)[\x20\t\r\n\f]*\/?>(?:<\/\1>|)$/i;function D(e,n,r){return m(n)?S.grep(e,function(e,t){return!!n.call(e,t,e)!==r}):n.nodeType?S.grep(e,function(e){return e===n!==r}):"string"!=typeof n?S.grep(e,function(e){return-1)[^>]*|#([\w-]+))$/;(S.fn.init=function(e,t,n){var r,i;if(!e)return this;if(n=n||j,"string"==typeof e){if(!(r="<"===e[0]&&">"===e[e.length-1]&&3<=e.length?[null,e,null]:q.exec(e))||!r[1]&&t)return!t||t.jquery?(t||n).find(e):this.constructor(t).find(e);if(r[1]){if(t=t instanceof S?t[0]:t,S.merge(this,S.parseHTML(r[1],t&&t.nodeType?t.ownerDocument||t:E,!0)),N.test(r[1])&&S.isPlainObject(t))for(r in t)m(this[r])?this[r](t[r]):this.attr(r,t[r]);return this}return(i=E.getElementById(r[2]))&&(this[0]=i,this.length=1),this}return e.nodeType?(this[0]=e,this.length=1,this):m(e)?void 0!==n.ready?n.ready(e):e(S):S.makeArray(e,this)}).prototype=S.fn,j=S(E);var L=/^(?:parents|prev(?:Until|All))/,H={children:!0,contents:!0,next:!0,prev:!0};function O(e,t){while((e=e[t])&&1!==e.nodeType);return e}S.fn.extend({has:function(e){var t=S(e,this),n=t.length;return this.filter(function(){for(var e=0;e\x20\t\r\n\f]*)/i,he=/^$|^module$|\/(?:java|ecma)script/i;ce=E.createDocumentFragment().appendChild(E.createElement("div")),(fe=E.createElement("input")).setAttribute("type","radio"),fe.setAttribute("checked","checked"),fe.setAttribute("name","t"),ce.appendChild(fe),y.checkClone=ce.cloneNode(!0).cloneNode(!0).lastChild.checked,ce.innerHTML="",y.noCloneChecked=!!ce.cloneNode(!0).lastChild.defaultValue,ce.innerHTML="",y.option=!!ce.lastChild;var ge={thead:[1,"","
    "],col:[2,"","
    "],tr:[2,"","
    "],td:[3,"","
    "],_default:[0,"",""]};function ve(e,t){var n;return n="undefined"!=typeof e.getElementsByTagName?e.getElementsByTagName(t||"*"):"undefined"!=typeof e.querySelectorAll?e.querySelectorAll(t||"*"):[],void 0===t||t&&A(e,t)?S.merge([e],n):n}function ye(e,t){for(var n=0,r=e.length;n",""]);var me=/<|&#?\w+;/;function xe(e,t,n,r,i){for(var o,a,s,u,l,c,f=t.createDocumentFragment(),p=[],d=0,h=e.length;d\s*$/g;function qe(e,t){return A(e,"table")&&A(11!==t.nodeType?t:t.firstChild,"tr")&&S(e).children("tbody")[0]||e}function Le(e){return e.type=(null!==e.getAttribute("type"))+"/"+e.type,e}function He(e){return"true/"===(e.type||"").slice(0,5)?e.type=e.type.slice(5):e.removeAttribute("type"),e}function Oe(e,t){var n,r,i,o,a,s;if(1===t.nodeType){if(Y.hasData(e)&&(s=Y.get(e).events))for(i in Y.remove(t,"handle events"),s)for(n=0,r=s[i].length;n").attr(n.scriptAttrs||{}).prop({charset:n.scriptCharset,src:n.url}).on("load error",i=function(e){r.remove(),i=null,e&&t("error"===e.type?404:200,e.type)}),E.head.appendChild(r[0])},abort:function(){i&&i()}}});var Ut,Xt=[],Vt=/(=)\?(?=&|$)|\?\?/;S.ajaxSetup({jsonp:"callback",jsonpCallback:function(){var e=Xt.pop()||S.expando+"_"+Ct.guid++;return this[e]=!0,e}}),S.ajaxPrefilter("json jsonp",function(e,t,n){var r,i,o,a=!1!==e.jsonp&&(Vt.test(e.url)?"url":"string"==typeof e.data&&0===(e.contentType||"").indexOf("application/x-www-form-urlencoded")&&Vt.test(e.data)&&"data");if(a||"jsonp"===e.dataTypes[0])return r=e.jsonpCallback=m(e.jsonpCallback)?e.jsonpCallback():e.jsonpCallback,a?e[a]=e[a].replace(Vt,"$1"+r):!1!==e.jsonp&&(e.url+=(Et.test(e.url)?"&":"?")+e.jsonp+"="+r),e.converters["script json"]=function(){return o||S.error(r+" was not called"),o[0]},e.dataTypes[0]="json",i=C[r],C[r]=function(){o=arguments},n.always(function(){void 0===i?S(C).removeProp(r):C[r]=i,e[r]&&(e.jsonpCallback=t.jsonpCallback,Xt.push(r)),o&&m(i)&&i(o[0]),o=i=void 0}),"script"}),y.createHTMLDocument=((Ut=E.implementation.createHTMLDocument("").body).innerHTML="
    ",2===Ut.childNodes.length),S.parseHTML=function(e,t,n){return"string"!=typeof e?[]:("boolean"==typeof t&&(n=t,t=!1),t||(y.createHTMLDocument?((r=(t=E.implementation.createHTMLDocument("")).createElement("base")).href=E.location.href,t.head.appendChild(r)):t=E),o=!n&&[],(i=N.exec(e))?[t.createElement(i[1])]:(i=xe([e],t,o),o&&o.length&&S(o).remove(),S.merge([],i.childNodes)));var r,i,o},S.fn.load=function(e,t,n){var r,i,o,a=this,s=e.indexOf(" ");return-1").append(S.parseHTML(e)).find(r):e)}).always(n&&function(e,t){a.each(function(){n.apply(this,o||[e.responseText,t,e])})}),this},S.expr.pseudos.animated=function(t){return S.grep(S.timers,function(e){return t===e.elem}).length},S.offset={setOffset:function(e,t,n){var r,i,o,a,s,u,l=S.css(e,"position"),c=S(e),f={};"static"===l&&(e.style.position="relative"),s=c.offset(),o=S.css(e,"top"),u=S.css(e,"left"),("absolute"===l||"fixed"===l)&&-1<(o+u).indexOf("auto")?(a=(r=c.position()).top,i=r.left):(a=parseFloat(o)||0,i=parseFloat(u)||0),m(t)&&(t=t.call(e,n,S.extend({},s))),null!=t.top&&(f.top=t.top-s.top+a),null!=t.left&&(f.left=t.left-s.left+i),"using"in t?t.using.call(e,f):("number"==typeof f.top&&(f.top+="px"),"number"==typeof f.left&&(f.left+="px"),c.css(f))}},S.fn.extend({offset:function(t){if(arguments.length)return void 0===t?this:this.each(function(e){S.offset.setOffset(this,t,e)});var e,n,r=this[0];return r?r.getClientRects().length?(e=r.getBoundingClientRect(),n=r.ownerDocument.defaultView,{top:e.top+n.pageYOffset,left:e.left+n.pageXOffset}):{top:0,left:0}:void 0},position:function(){if(this[0]){var e,t,n,r=this[0],i={top:0,left:0};if("fixed"===S.css(r,"position"))t=r.getBoundingClientRect();else{t=this.offset(),n=r.ownerDocument,e=r.offsetParent||n.documentElement;while(e&&(e===n.body||e===n.documentElement)&&"static"===S.css(e,"position"))e=e.parentNode;e&&e!==r&&1===e.nodeType&&((i=S(e).offset()).top+=S.css(e,"borderTopWidth",!0),i.left+=S.css(e,"borderLeftWidth",!0))}return{top:t.top-i.top-S.css(r,"marginTop",!0),left:t.left-i.left-S.css(r,"marginLeft",!0)}}},offsetParent:function(){return this.map(function(){var e=this.offsetParent;while(e&&"static"===S.css(e,"position"))e=e.offsetParent;return e||re})}}),S.each({scrollLeft:"pageXOffset",scrollTop:"pageYOffset"},function(t,i){var o="pageYOffset"===i;S.fn[t]=function(e){return $(this,function(e,t,n){var r;if(x(e)?r=e:9===e.nodeType&&(r=e.defaultView),void 0===n)return r?r[i]:e[t];r?r.scrollTo(o?r.pageXOffset:n,o?n:r.pageYOffset):e[t]=n},t,e,arguments.length)}}),S.each(["top","left"],function(e,n){S.cssHooks[n]=$e(y.pixelPosition,function(e,t){if(t)return t=Be(e,n),Me.test(t)?S(e).position()[n]+"px":t})}),S.each({Height:"height",Width:"width"},function(a,s){S.each({padding:"inner"+a,content:s,"":"outer"+a},function(r,o){S.fn[o]=function(e,t){var n=arguments.length&&(r||"boolean"!=typeof e),i=r||(!0===e||!0===t?"margin":"border");return $(this,function(e,t,n){var r;return x(e)?0===o.indexOf("outer")?e["inner"+a]:e.document.documentElement["client"+a]:9===e.nodeType?(r=e.documentElement,Math.max(e.body["scroll"+a],r["scroll"+a],e.body["offset"+a],r["offset"+a],r["client"+a])):void 0===n?S.css(e,t,i):S.style(e,t,n,i)},s,n?e:void 0,n)}})}),S.each(["ajaxStart","ajaxStop","ajaxComplete","ajaxError","ajaxSuccess","ajaxSend"],function(e,t){S.fn[t]=function(e){return this.on(t,e)}}),S.fn.extend({bind:function(e,t,n){return this.on(e,null,t,n)},unbind:function(e,t){return this.off(e,null,t)},delegate:function(e,t,n,r){return this.on(t,e,n,r)},undelegate:function(e,t,n){return 1===arguments.length?this.off(e,"**"):this.off(t,e||"**",n)},hover:function(e,t){return this.mouseenter(e).mouseleave(t||e)}}),S.each("blur focus focusin focusout resize scroll click dblclick mousedown mouseup mousemove mouseover mouseout mouseenter mouseleave change select submit keydown keypress keyup contextmenu".split(" "),function(e,n){S.fn[n]=function(e,t){return 0'); if (headers) { var $thead = $(''); var $tr = $(''); $.each(headers, function (index, value) { if (!(value instanceof Object)) { value = { html: value }; } $('', value).appendTo($tr); }); $table.append($thead.append($tr)); } return $table; }; /** * Generic function for creating a table row * * @param {array} rows Value list. Object name is used as class name in */ H5PUtils.createTableRow = function (rows) { var $tr = $(''); $.each(rows, function (index, value) { if (!(value instanceof Object)) { value = { html: value }; } $('', value).appendTo($tr); }); return $tr; }; /** * Generic function for creating a field containing label and value * * @param {string} label The label displayed in front of the value * @param {string} value The value */ H5PUtils.createLabeledField = function (label, value) { var $field = $('
    '); $field.append('
    ' + label + '
    '); $field.append('
    ' + value + '
    '); return $field; }; /** * Replaces placeholder fields in translation strings * * @param {string} template The translation template string in the following format: "$name is a $sex" * @param {array} replacors An js object with key and values. Eg: {'$name': 'Frode', '$sex': 'male'} */ H5PUtils.translateReplace = function (template, replacors) { $.each(replacors, function (key, value) { template = template.replace(new RegExp('\\'+key, 'g'), value); }); return template; }; /** * Get throbber with given text. * * @param {String} text * @returns {$} */ H5PUtils.throbber = function (text) { return $('
    ', { class: 'h5p-throbber', text: text }); }; /** * Makes it possbile to rebuild all content caches from admin UI. * @param {Object} notCached * @returns {$} */ H5PUtils.getRebuildCache = function (notCached) { var $container = $('

    ' + notCached.message + '

    ' + notCached.progress + '

    '); var $button = $('').appendTo($container).click(function () { var $spinner = $('
    ', {class: 'h5p-spinner'}).replaceAll($button); var parts = ['|', '/', '-', '\\']; var current = 0; var spinning = setInterval(function () { $spinner.text(parts[current]); current++; if (current === parts.length) current = 0; }, 100); var $counter = $container.find('.progress'); var build = function () { $.post(notCached.url, function (left) { if (left === '0') { clearInterval(spinning); $container.remove(); location.reload(); } else { var counter = $counter.text().split(' '); counter[0] = left; $counter.text(counter.join(' ')); build(); } }); }; build(); }); return $container; }; /** * Generic table class with useful helpers. * * @class * @param {Object} classes * Custom html classes to use on elements. * e.g. {tableClass: 'fixed'}. */ H5PUtils.Table = function (classes) { var numCols; var sortByCol; var $sortCol; var sortCol; var sortDir; // Create basic table var tableOptions = {}; if (classes.table !== undefined) { tableOptions['class'] = classes.table; } var $table = $('', tableOptions); var $thead = $('').appendTo($table); var $tfoot = $('').appendTo($table); var $tbody = $('').appendTo($table); /** * Add columns to given table row. * * @private * @param {jQuery} $tr Table row * @param {(String|Object)} col Column properties * @param {Number} id Used to seperate the columns */ var addCol = function ($tr, col, id) { var options = { on: {} }; if (!(col instanceof Object)) { options.text = col; } else { if (col.text !== undefined) { options.text = col.text; } if (col.class !== undefined) { options.class = col.class; } if (sortByCol !== undefined && col.sortable === true) { // Make sortable options.role = 'button'; options.tabIndex = 0; // This is the first sortable column, use as default sort if (sortCol === undefined) { sortCol = id; sortDir = 0; } // This is the sort column if (sortCol === id) { options['class'] = 'h5p-sort'; if (sortDir === 1) { options['class'] += ' h5p-reverse'; } } options.on.click = function () { sort($th, id); }; options.on.keypress = function (event) { if ((event.charCode || event.keyCode) === 32) { // Space sort($th, id); } }; } } // Append var $th = $(''); var $tr = $('').appendTo($newThead); for (var i = 0; i < cols.length; i++) { addCol($tr, cols[i], i); } // Update DOM $thead.replaceWith($newThead); $thead = $newThead; }; /** * Set table rows. * * @public * @param {Array} rows Table rows with cols: [[1,'hello',3],[2,'asd',6]] */ this.setRows = function (rows) { var $newTbody = $(''); for (var i = 0; i < rows.length; i++) { var $tr = $('').appendTo($newTbody); for (var j = 0; j < rows[i].length; j++) { $(''); var $tr = $('').appendTo($newTbody); $(''); var $tr = $('').appendTo($newTfoot); $('
    ', options).appendTo($tr); if (sortCol === id) { $sortCol = $th; // Default sort column } }; /** * Updates the UI when a column header has been clicked. * Triggers sorting callback. * * @private * @param {jQuery} $th Table header * @param {Number} id Used to seperate the columns */ var sort = function ($th, id) { if (id === sortCol) { // Change sorting direction if (sortDir === 0) { sortDir = 1; $th.addClass('h5p-reverse'); } else { sortDir = 0; $th.removeClass('h5p-reverse'); } } else { // Change sorting column $sortCol.removeClass('h5p-sort').removeClass('h5p-reverse'); $sortCol = $th.addClass('h5p-sort'); sortCol = id; sortDir = 0; } sortByCol({ by: sortCol, dir: sortDir }); }; /** * Set table headers. * * @public * @param {Array} cols * Table header data. Can be strings or objects with options like * "text" and "sortable". E.g. * [{text: 'Col 1', sortable: true}, 'Col 2', 'Col 3'] * @param {Function} sort Callback which is runned when sorting changes * @param {Object} [order] */ this.setHeaders = function (cols, sort, order) { numCols = cols.length; sortByCol = sort; if (order) { sortCol = order.by; sortDir = order.dir; } // Create new head var $newThead = $('
    ', { html: rows[i][j] }).appendTo($tr); } } $tbody.replaceWith($newTbody); $tbody = $newTbody; return $tbody; }; /** * Set custom table body content. This can be a message or a throbber. * Will cover all table columns. * * @public * @param {jQuery} $content Custom content */ this.setBody = function ($content) { var $newTbody = $('
    ', { colspan: numCols }).append($content).appendTo($tr); $tbody.replaceWith($newTbody); $tbody = $newTbody; }; /** * Set custom table foot content. This can be a pagination widget. * Will cover all table columns. * * @public * @param {jQuery} $content Custom content */ this.setFoot = function ($content) { var $newTfoot = $('
    ', { colspan: numCols }).append($content).appendTo($tr); $tfoot.replaceWith($newTfoot); }; /** * Appends the table to the given container. * * @public * @param {jQuery} $container */ this.appendTo = function ($container) { $table.appendTo($container); }; }; /** * Generic pagination class. Creates a useful pagination widget. * * @class * @param {Number} num Total number of items to pagiate. * @param {Number} limit Number of items to dispaly per page. * @param {Function} goneTo * Callback which is fired when the user wants to go to another page. * @param {Object} l10n * Localization / translations. e.g. * { * currentPage: 'Page $current of $total', * nextPage: 'Next page', * previousPage: 'Previous page' * } */ H5PUtils.Pagination = function (num, limit, goneTo, l10n) { var current = 0; var pages = Math.ceil(num / limit); // Create components // Previous button var $left = $(''); H5PLibraryDetails.$next = $(''); H5PLibraryDetails.$previous.on('click', function () { if (H5PLibraryDetails.$previous.hasClass('disabled')) { return; } H5PLibraryDetails.currentPage--; H5PLibraryDetails.updatePager(); H5PLibraryDetails.createContentTable(); }); H5PLibraryDetails.$next.on('click', function () { if (H5PLibraryDetails.$next.hasClass('disabled')) { return; } H5PLibraryDetails.currentPage++; H5PLibraryDetails.updatePager(); H5PLibraryDetails.createContentTable(); }); // This is the Page x of y widget: H5PLibraryDetails.$pagerInfo = $(''); H5PLibraryDetails.$pager = $('
    ').append(H5PLibraryDetails.$previous, H5PLibraryDetails.$pagerInfo, H5PLibraryDetails.$next); H5PLibraryDetails.$content.append(H5PLibraryDetails.$pager); H5PLibraryDetails.$pagerInfo.on('click', function () { var width = H5PLibraryDetails.$pagerInfo.innerWidth(); H5PLibraryDetails.$pagerInfo.hide(); // User has updated the pageNumber var pageNumerUpdated = function () { var newPageNum = $gotoInput.val()-1; var intRegex = /^\d+$/; $goto.remove(); H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'}); // Check if input value is valid, and that it has actually changed if (!(intRegex.test(newPageNum) && newPageNum >= 0 && newPageNum < H5PLibraryDetails.getNumPages() && newPageNum != H5PLibraryDetails.currentPage)) { return; } H5PLibraryDetails.currentPage = newPageNum; H5PLibraryDetails.updatePager(); H5PLibraryDetails.createContentTable(); }; // We create an input box where the user may type in the page number // he wants to be displayed. // Reson for doing this is when user has ten-thousands of elements in list, // this is the easiest way of getting to a specified page var $gotoInput = $('', { type: 'number', min : 1, max: H5PLibraryDetails.getNumPages(), on: { // Listen to blur, and the enter-key: 'blur': pageNumerUpdated, 'keyup': function (event) { if (event.keyCode === 13) { pageNumerUpdated(); } } } }).css({width: width}); var $goto = $('', { 'class': 'h5p-pager-goto' }).css({width: width}).append($gotoInput).insertAfter(H5PLibraryDetails.$pagerInfo); $gotoInput.focus(); }); H5PLibraryDetails.updatePager(); }; /** * Calculates number of pages */ H5PLibraryDetails.getNumPages = function () { return Math.ceil(H5PLibraryDetails.currentContent.length / H5PLibraryDetails.PAGER_SIZE); }; /** * Update the pager text, and enables/disables the next and previous buttons as needed */ H5PLibraryDetails.updatePager = function () { H5PLibraryDetails.$pagerInfo.css({display: 'inline-block'}); if (H5PLibraryDetails.getNumPages() > 0) { var message = H5PUtils.translateReplace(H5PLibraryDetails.library.translations.pageXOfY, { '$x': (H5PLibraryDetails.currentPage+1), '$y': H5PLibraryDetails.getNumPages() }); H5PLibraryDetails.$pagerInfo.html(message); } else { H5PLibraryDetails.$pagerInfo.html(''); } H5PLibraryDetails.$previous.toggleClass('disabled', H5PLibraryDetails.currentPage <= 0); H5PLibraryDetails.$next.toggleClass('disabled', H5PLibraryDetails.currentContent.length < (H5PLibraryDetails.currentPage+1)*H5PLibraryDetails.PAGER_SIZE); }; /** * Creates the search element */ H5PLibraryDetails.createSearchElement = function () { H5PLibraryDetails.$search = $(''); var performSeach = function () { var searchString = $('.h5p-content-search > input').val(); // If search string same as previous, just do nothing if (H5PLibraryDetails.currentFilter === searchString) { return; } if (searchString.trim().length === 0) { // If empty search, use the complete list H5PLibraryDetails.currentContent = H5PLibraryDetails.library.content; } else if (H5PLibraryDetails.filterCache[searchString]) { // If search is cached, no need to filter H5PLibraryDetails.currentContent = H5PLibraryDetails.filterCache[searchString]; } else { var listToFilter = H5PLibraryDetails.library.content; // Check if we can filter the already filtered results (for performance) if (searchString.length > 1 && H5PLibraryDetails.currentFilter === searchString.substr(0, H5PLibraryDetails.currentFilter.length)) { listToFilter = H5PLibraryDetails.currentContent; } H5PLibraryDetails.currentContent = $.grep(listToFilter, function (content) { return content.title && content.title.match(new RegExp(searchString, 'i')); }); } H5PLibraryDetails.currentFilter = searchString; // Cache the current result H5PLibraryDetails.filterCache[searchString] = H5PLibraryDetails.currentContent; H5PLibraryDetails.currentPage = 0; H5PLibraryDetails.createContentTable(); // Display search results: if (H5PLibraryDetails.$searchResults) { H5PLibraryDetails.$searchResults.remove(); } if (searchString.trim().length > 0) { H5PLibraryDetails.$searchResults = $('' + H5PLibraryDetails.currentContent.length + ' hits on ' + H5PLibraryDetails.currentFilter + ''); H5PLibraryDetails.$search.append(H5PLibraryDetails.$searchResults); } H5PLibraryDetails.updatePager(); }; var inputTimer; $('input', H5PLibraryDetails.$search).on('change keypress paste input', function () { // Here we start the filtering // We wait at least 500 ms after last input to perform search if (inputTimer) { clearTimeout(inputTimer); } inputTimer = setTimeout( function () { performSeach(); }, 500); }); H5PLibraryDetails.$content.append(H5PLibraryDetails.$search); }; /** * Creates the page size selector */ H5PLibraryDetails.createPageSizeSelector = function () { H5PLibraryDetails.$search.append('
    ' + H5PLibraryDetails.library.translations.pageSizeSelectorLabel + ':102050100200
    '); // Listen to clicks on the page size selector: $('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).on('click', function () { H5PLibraryDetails.PAGER_SIZE = $(this).data('page-size'); $('.h5p-admin-pager-size-selector > span', H5PLibraryDetails.$search).removeClass('selected'); $(this).addClass('selected'); H5PLibraryDetails.currentPage = 0; H5PLibraryDetails.createContentTable(); H5PLibraryDetails.updatePager(); }); }; // Initialize me: $(document).ready(function () { if (!H5PLibraryDetails.initialized) { H5PLibraryDetails.initialized = true; H5PLibraryDetails.init(); } }); })(H5P.jQuery); PK*\W7@/  .h5plib/v127/joubel/core/js/h5p-content-type.jsnu[/** * H5P.ContentType is a base class for all content types. Used by newRunnable() * * Functions here may be overridable by the libraries. In special cases, * it is also possible to override H5P.ContentType on a global level. * * NOTE that this doesn't actually 'extend' the event dispatcher but instead * it creates a single instance which all content types shares as their base * prototype. (in some cases this may be the root of strange event behavior) * * @class * @augments H5P.EventDispatcher */ H5P.ContentType = function (isRootLibrary) { function ContentType() {} // Inherit from EventDispatcher. ContentType.prototype = new H5P.EventDispatcher(); /** * Is library standalone or not? Not beeing standalone, means it is * included in another library * * @return {Boolean} */ ContentType.prototype.isRoot = function () { return isRootLibrary; }; /** * Returns the file path of a file in the current library * @param {string} filePath The path to the file relative to the library folder * @return {string} The full path to the file */ ContentType.prototype.getLibraryFilePath = function (filePath) { return H5P.getLibraryPath(this.libraryInfo.versionedNameNoSpaces) + '/' + filePath; }; return ContentType; }; PK*\f%w8h5plib/v127/joubel/core/js/h5p-content-upgrade-worker.jsnu[/* global importScripts */ var H5P = H5P || {}; importScripts('h5p-version.js', 'h5p-content-upgrade-process.js'); var libraryLoadedCallback; /** * Register message handlers */ var messageHandlers = { newJob: function (job) { // Start new job new H5P.ContentUpgradeProcess(job.name, new H5P.Version(job.oldVersion), new H5P.Version(job.newVersion), job.params, job.id, function loadLibrary(name, version, next) { // TODO: Cache? postMessage({ action: 'loadLibrary', name: name, version: version.toString() }); libraryLoadedCallback = next; }, function done(err, result) { if (err) { // Return error postMessage({ action: 'error', id: job.id, err: err.message ? err.message : err }); return; } // Return upgraded content postMessage({ action: 'done', id: job.id, params: result }); }); }, libraryLoaded: function (data) { var library = data.library; if (library.upgradesScript) { try { importScripts(library.upgradesScript); } catch (err) { libraryLoadedCallback(err); return; } } libraryLoadedCallback(null, data.library); } }; /** * Handle messages from our master */ onmessage = function (event) { if (event.data.action !== undefined && messageHandlers[event.data.action]) { messageHandlers[event.data.action].call(this, event.data); } }; PK*\@1h5plib/v127/joubel/core/js/h5p-display-options.jsnu[/** * Utility that makes it possible to hide fields when a checkbox is unchecked */ (function ($) { function setupHiding() { var $toggler = $(this); // Getting the field which should be hidden: var $subject = $($toggler.data('h5p-visibility-subject-selector')); var toggle = function () { $subject.toggle($toggler.is(':checked')); }; $toggler.change(toggle); toggle(); } function setupRevealing() { var $button = $(this); // Getting the field which should have the value: var $input = $('#' + $button.data('control')); if (!$input.data('value')) { $button.remove(); return; } // Setup button action var revealed = false; var text = $button.html(); $button.click(function () { if (revealed) { $input.val(''); $button.html(text); revealed = false; } else { $input.val($input.data('value')); $button.html($button.data('hide')); revealed = true; } }); } $(document).ready(function () { // Get the checkboxes making other fields being hidden: $('.h5p-visibility-toggler').each(setupHiding); // Get the buttons making other fields have hidden values: $('.h5p-reveal-value').each(setupRevealing); }); })(H5P.jQuery); PK*\bA"h5plib/v127/joubel/core/README.txtnu[This folder contains the general H5P library. The files within this folder are not specific to any framework. Any interaction with an LMS, CMS or other frameworks is done through interfaces. Platforms need to implement the H5PFrameworkInterface(in h5p.classes.php) and also do the following: - Provide a form for uploading H5P packages. - Place the uploaded H5P packages in a temporary directory +++ See existing implementations for details. For instance the Drupal H5P module located at drupal.org/project/h5p We will make available documentation and tutorials for creating platform integrations in the future. The H5P PHP library is GPL licensed due to GPL code being used for purifying HTML provided by authors. ## License Open Sans font is licensed under Apache license, Version 2.0PK*\ihh1h5plib/v127/joubel/core/h5p-development.class.phpnu[h5pF = $H5PFramework; $this->language = $language; $this->filesPath = $filesPath; if ($libraries !== NULL) { $this->libraries = $libraries; } else { $this->findLibraries($filesPath . '/development'); } } /** * Get contents of file. * * @param string $file File path. * @return mixed String on success or NULL on failure. */ private function getFileContents($file) { if (file_exists($file) === FALSE) { return NULL; } $contents = file_get_contents($file); if ($contents === FALSE) { return NULL; } return $contents; } /** * Scans development directory and find all libraries. * * @param string $path Libraries development folder */ private function findLibraries($path) { $this->libraries = array(); if (is_dir($path) === FALSE) { return; } $contents = scandir($path); for ($i = 0, $s = count($contents); $i < $s; $i++) { if ($contents[$i][0] === '.') { continue; // Skip hidden stuff. } $libraryPath = $path . '/' . $contents[$i]; $libraryJSON = $this->getFileContents($libraryPath . '/library.json'); if ($libraryJSON === NULL) { continue; // No JSON file, skip. } $library = json_decode($libraryJSON, TRUE); if ($library === NULL) { continue; // Invalid JSON. } // TODO: Validate props? Not really needed, is it? this is a dev site. $library['libraryId'] = $this->h5pF->getLibraryId($library['machineName'], $library['majorVersion'], $library['minorVersion']); // Convert metadataSettings values to boolean & json_encode it before saving $library['metadataSettings'] = isset($library['metadataSettings']) ? H5PMetadata::boolifyAndEncodeSettings($library['metadataSettings']) : NULL; // Save/update library. $this->h5pF->saveLibraryData($library, $library['libraryId'] === FALSE); // Need to decode it again, since it is served from here. $library['metadataSettings'] = isset($library['metadataSettings']) ? json_decode($library['metadataSettings']) : NULL; $library['path'] = 'development/' . $contents[$i]; $this->libraries[H5PDevelopment::libraryToString($library['machineName'], $library['majorVersion'], $library['minorVersion'])] = $library; } // TODO: Should we remove libraries without files? Not really needed, but must be cleaned up some time, right? // Go trough libraries and insert dependencies. Missing deps. will just be ignored and not available. (I guess?!) $this->h5pF->lockDependencyStorage(); foreach ($this->libraries as $library) { $this->h5pF->deleteLibraryDependencies($library['libraryId']); // This isn't optimal, but without it we would get duplicate warnings. // TODO: You might get PDOExceptions if two or more requests does this at the same time!! $types = array('preloaded', 'dynamic', 'editor'); foreach ($types as $type) { if (isset($library[$type . 'Dependencies'])) { $this->h5pF->saveLibraryDependencies($library['libraryId'], $library[$type . 'Dependencies'], $type); } } } $this->h5pF->unlockDependencyStorage(); // TODO: Deps must be inserted into h5p_nodes_libraries as well... ? But only if they are used?! } /** * @return array Libraries in development folder. */ public function getLibraries() { return $this->libraries; } /** * Get library * * @param string $name of the library. * @param int $majorVersion of the library. * @param int $minorVersion of the library. * @return array library. */ public function getLibrary($name, $majorVersion, $minorVersion) { $library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion); return isset($this->libraries[$library]) === TRUE ? $this->libraries[$library] : NULL; } /** * Get semantics for the given library. * * @param string $name of the library. * @param int $majorVersion of the library. * @param int $minorVersion of the library. * @return string Semantics */ public function getSemantics($name, $majorVersion, $minorVersion) { $library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion); if (isset($this->libraries[$library]) === FALSE) { return NULL; } return $this->getFileContents($this->filesPath . $this->libraries[$library]['path'] . '/semantics.json'); } /** * Get translations for the given library. * * @param string $name of the library. * @param int $majorVersion of the library. * @param int $minorVersion of the library. * @param $language * @return string Translation */ public function getLanguage($name, $majorVersion, $minorVersion, $language) { $library = H5PDevelopment::libraryToString($name, $majorVersion, $minorVersion); if (isset($this->libraries[$library]) === FALSE) { return NULL; } return $this->getFileContents($this->filesPath . $this->libraries[$library]['path'] . '/language/' . $language . '.json'); } /** * Writes library as string on the form "name majorVersion.minorVersion" * * @param string $name Machine readable library name * @param integer $majorVersion * @param $minorVersion * @return string Library identifier. */ public static function libraryToString($name, $majorVersion, $minorVersion) { return $name . ' ' . $majorVersion . '.' . $minorVersion; } } PK*\Rnpp#h5plib/v127/joubel/editor/README.mdnu[H5P Editor PHP Library ========== A general library that is supposed to be used in most PHP implementations of H5P. ## License All code is licensed under MIT License Open Sans font is licensed under Apache license, Version 2.0 ## Compiling scss to css You first need to install ruby and compass: - `sudo apt update` - `sudo apt install ruby-full` - `sudo apt install build-essential` - `sudo gem install compass` Then cd to `h5p-editor-php-library/styles` and compile the scss files: - `compass watch` to continuely compile changes - or `compass clean && compass compile` to delete the css files and compile new ones PK*\tZ"l"l-h5plib/v127/joubel/editor/h5peditor.class.phpnu[h5p = $h5p; $this->storage = $storage; $this->ajaxInterface = $ajaxInterface; $this->ajax = new H5PEditorAjax($h5p, $this, $storage); } /** * Get list of libraries. * * @return array */ public function getLibraries() { if (isset($_POST['libraries'])) { // Get details for the specified libraries. $libraries = array(); foreach ($_POST['libraries'] as $libraryName) { $matches = array(); preg_match_all('/(.+)\s(\d+)\.(\d+)$/', $libraryName, $matches); if ($matches && $matches[1] && $matches[2] && $matches[3]) { $libraries[] = (object) array( 'uberName' => $libraryName, 'name' => $matches[1][0], 'majorVersion' => $matches[2][0], 'minorVersion' => $matches[3][0] ); } } } $libraries = $this->storage->getLibraries(!isset($libraries) ? NULL : $libraries); if ($this->h5p->development_mode & H5PDevelopment::MODE_LIBRARY) { $devLibs = $this->h5p->h5pD->getLibraries(); } for ($i = 0, $s = count($libraries); $i < $s; $i++) { if (!empty($devLibs)) { $lid = $libraries[$i]->name . ' ' . $libraries[$i]->majorVersion . '.' . $libraries[$i]->minorVersion; if (isset($devLibs[$lid])) { // Replace library with devlib $isOld = !empty($libraries[$i]->isOld) && $libraries[$i]->isOld === TRUE; $libraries[$i] = (object) array( 'uberName' => $lid, 'name' => $devLibs[$lid]['machineName'], 'title' => $devLibs[$lid]['title'], 'majorVersion' => $devLibs[$lid]['majorVersion'], 'minorVersion' => $devLibs[$lid]['minorVersion'], 'runnable' => $devLibs[$lid]['runnable'], 'restricted' => $libraries[$i]->restricted, 'tutorialUrl' => $libraries[$i]->tutorialUrl, 'metadataSettings' => $devLibs[$lid]['metadataSettings'], ); if ($isOld) { $libraries[$i]->isOld = TRUE; } } } // Some libraries rely on an LRS to work and must be enabled manually if (in_array($libraries[$i]->name, array('H5P.Questionnaire', 'H5P.FreeTextQuestion')) && !$this->h5p->h5pF->getOption('enable_lrs_content_types')) { $libraries[$i]->restricted = TRUE; } } return $libraries; } /** * Get translations for a language for a list of libraries * * @param array $libraries An array of libraries, in the form " . * @param string $language_code * @return array */ public function getTranslations($libraries, $language_code) { return $this->ajaxInterface->getTranslations($libraries, $language_code); } /** * Move uploaded files, remove old files and update library usage. * * @param stdClass $content * @param array $newLibrary * @param array $newParameters * @param array $oldLibrary * @param array $oldParameters */ public function processParameters($content, $newLibrary, $newParameters, $oldLibrary = NULL, $oldParameters = NULL) { $newFiles = array(); $oldFiles = array(); // Keep track of current content ID (used when processing files) $this->content = $content; // Find new libraries/content dependencies and files. // Start by creating a fake library field to process. This way we get all the dependencies of the main library as well. $field = (object) array( 'type' => 'library' ); $libraryParams = (object) array( 'library' => H5PCore::libraryToString($newLibrary), 'params' => $newParameters ); $this->processField($field, $libraryParams, $newFiles); if ($oldLibrary !== NULL) { // Find old files and libraries. $this->processSemantics($oldFiles, $this->h5p->loadLibrarySemantics($oldLibrary['name'], $oldLibrary['majorVersion'], $oldLibrary['minorVersion']), $oldParameters); // Remove old files. for ($i = 0, $s = count($oldFiles); $i < $s; $i++) { if (!in_array($oldFiles[$i], $newFiles) && preg_match('/^(\w+:\/\/|\.\.\/)/i', $oldFiles[$i]) === 0) { $this->h5p->fs->removeContentFile($oldFiles[$i], $content); // (optionally we could just have marked them as tmp files) } } } } /** * Recursive function that moves the new files in to the h5p content folder and generates a list over the old files. * Also locates all the librares. * * @param array $files * @param array $libraries * @param array $semantics * @param array $params */ private function processSemantics(&$files, $semantics, &$params) { for ($i = 0, $s = count($semantics); $i < $s; $i++) { $field = $semantics[$i]; if (!isset($params->{$field->name})) { continue; } $this->processField($field, $params->{$field->name}, $files); } } /** * Process a single field. * * @staticvar string $h5peditor_path * @param object $field * @param mixed $params * @param array $files */ private function processField(&$field, &$params, &$files) { switch ($field->type) { case 'file': case 'image': if (isset($params->path)) { $this->processFile($params, $files); // Process original image if (isset($params->originalImage) && isset($params->originalImage->path)) { $this->processFile($params->originalImage, $files); } } break; case 'video': case 'audio': if (is_array($params)) { for ($i = 0, $s = count($params); $i < $s; $i++) { $this->processFile($params[$i], $files); } } break; case 'library': if (isset($params->library) && isset($params->params)) { $library = H5PCore::libraryFromString($params->library); $semantics = $this->h5p->loadLibrarySemantics($library['machineName'], $library['majorVersion'], $library['minorVersion']); // Process parameters for the library. $this->processSemantics($files, $semantics, $params->params); } break; case 'group': if (isset($params)) { $isSubContent = isset($field->isSubContent) && $field->isSubContent == TRUE; if (count($field->fields) == 1 && !$isSubContent) { $params = (object) array($field->fields[0]->name => $params); } $this->processSemantics($files, $field->fields, $params); } break; case 'list': if (is_array($params)) { for ($j = 0, $t = count($params); $j < $t; $j++) { $this->processField($field->field, $params[$j], $files); } } break; } } /** * @param mixed $params * @param array $files */ private function processFile(&$params, &$files) { if (preg_match('/^https?:\/\//', $params->path)) { return; // Skip external files } // Remove temporary files suffix if (substr($params->path, -4, 4) === '#tmp') { $params->path = substr($params->path, 0, strlen($params->path) - 4); } // File could be copied from another content folder. $matches = array(); if (preg_match($this->h5p->relativePathRegExp, $params->path, $matches)) { // Create a copy of the file $this->h5p->fs->cloneContentFile($matches[5], $matches[4], $this->content); // Update Params with correct filename $params->path = $matches[5]; } else { // Check if file exists in content folder $fileId = $this->h5p->fs->getContentFile($params->path, $this->content); if ($fileId) { // Mark the file as a keeper $this->storage->keepFile($fileId); } else { // File is not in content folder, try to copy it from the editor tmp dir // to content folder. $this->h5p->fs->cloneContentFile($params->path, 'editor', $this->content); // (not removed in case someone has copied it) // (will automatically be removed after 24 hours) } } $files[] = $params->path; } /** * TODO: Consider moving to core. */ public function getLibraryLanguage($machineName, $majorVersion, $minorVersion, $languageCode) { if ($this->h5p->development_mode & H5PDevelopment::MODE_LIBRARY) { // Try to get language development library first. $language = $this->h5p->h5pD->getLanguage($machineName, $majorVersion, $minorVersion, $languageCode); } if (isset($language) === FALSE) { $language = $this->storage->getLanguage($machineName, $majorVersion, $minorVersion, $languageCode); } return ($language === FALSE ? NULL : $language); } /** * Return all libraries used by the given editor library. * * @param string $machineName Library identfier part 1 * @param int $majorVersion Library identfier part 2 * @param int $minorVersion Library identfier part 3 */ public function findEditorLibraries($machineName, $majorVersion, $minorVersion) { $library = $this->h5p->loadLibrary($machineName, $majorVersion, $minorVersion); $dependencies = array(); $this->h5p->findLibraryDependencies($dependencies, $library); // Load addons for wysiwyg editors if (in_array($machineName, self::$hasWYSIWYGEditor)) { $addons = $this->h5p->h5pF->loadAddons(); foreach ($addons as $addon) { $key = 'editor-' . $addon['machineName']; $dependencies[$key]['weight'] = sizeof($dependencies)+1; $dependencies[$key]['type'] = 'editor'; $dependencies[$key]['library'] = $addon; } } // Order dependencies by weight $orderedDependencies = array(); for ($i = 1, $s = count($dependencies); $i <= $s; $i++) { foreach ($dependencies as $dependency) { if ($dependency['weight'] === $i && $dependency['type'] === 'editor') { // Only load editor libraries. $dependency['library']['id'] = $dependency['library']['libraryId']; $orderedDependencies[$dependency['library']['libraryId']] = $dependency['library']; break; } } } return $orderedDependencies; } /** * Get all scripts, css and semantics data for a library * * @param string $machineName Library name * @param int $majorVersion * @param int $minorVersion * @param string $prefix Optional part to add between URL and asset path * @param string $fileDir Optional file dir to read files from * * @return array Libraries that was requested */ public function getLibraryData($machineName, $majorVersion, $minorVersion, $languageCode, $prefix = '', $fileDir = '', $defaultLanguage = '') { $libraryData = new stdClass(); $library = $this->h5p->loadLibrary($machineName, $majorVersion, $minorVersion); // Include name and version in data object for convenience $libraryData->name = $library['machineName']; $libraryData->version = (object) array('major' => $library['majorVersion'], 'minor' => $library['minorVersion']); $libraryData->title = $library['title']; $libraryData->upgradesScript = $this->h5p->fs->getUpgradeScript($library['machineName'], $library['majorVersion'], $library['minorVersion']); if ($libraryData->upgradesScript !== NULL) { // If valid add URL prefix $libraryData->upgradesScript = $this->h5p->url . $prefix . $libraryData->upgradesScript; } $libraries = $this->findEditorLibraries($library['machineName'], $library['majorVersion'], $library['minorVersion']); $libraryData->semantics = $this->h5p->loadLibrarySemantics($library['machineName'], $library['majorVersion'], $library['minorVersion']); $libraryData->language = $this->getLibraryLanguage($library['machineName'], $library['majorVersion'], $library['minorVersion'], $languageCode); $libraryData->defaultLanguage = empty($defaultLanguage) ? NULL : $this->getLibraryLanguage($library['machineName'], $library['majorVersion'], $library['minorVersion'], $defaultLanguage); $libraryData->languages = $this->storage->getAvailableLanguages($library['machineName'], $library['majorVersion'], $library['minorVersion']); // Temporarily disable asset aggregation $aggregateAssets = $this->h5p->aggregateAssets; $this->h5p->aggregateAssets = FALSE; // This is done to prevent files being loaded multiple times due to how // the editor works. // Get list of JS and CSS files that belongs to the dependencies $files = $this->h5p->getDependenciesFiles($libraries, $prefix); $libraryName = H5PCore::libraryToFolderName($library); if ($this->hasPresave($libraryName) === true) { $this->addPresaveFile($files, $library, $prefix); } $this->storage->alterLibraryFiles($files, $libraries); // Restore asset aggregation setting $this->h5p->aggregateAssets = $aggregateAssets; // Create base URL $url = $this->h5p->url; // Javascripts if (!empty($files['scripts'])) { foreach ($files['scripts'] as $script) { if (preg_match('/:\/\//', $script->path) === 1) { // External file $libraryData->javascript[] = $script->path . $script->version; } else { // Local file $path = $url . $script->path; if (!isset($this->h5p->h5pD)) { $path .= $script->version; } $libraryData->javascript[] = $path; } } } // Stylesheets if (!empty($files['styles'])) { foreach ($files['styles'] as $css) { if (preg_match('/:\/\//', $css->path) === 1) { // External file $libraryData->css[] = $css->path . $css->version; } else { // Local file $path = $url . $css->path; if (!isset($this->h5p->h5pD)) { $path .= $css->version; } $libraryData->css[] = $path; } } } $translations = array(); // Add translations for libraries. foreach ($libraries as $library) { if (empty($library['semantics'])) { $translation = $this->getLibraryLanguage($library['machineName'], $library['majorVersion'], $library['minorVersion'], $languageCode); // If translation was not found, and this is not the English one, try to load // the English translation if ($translation === NULL && $languageCode !== 'en') { $translation = $this->getLibraryLanguage($library['machineName'], $library['majorVersion'], $library['minorVersion'], 'en'); } if ($translation !== NULL) { $translations[$library['machineName']] = json_decode($translation); } } } $libraryData->translations = $translations; return $libraryData; } /** * This function will prefix all paths within a CSS file. * Copied from Drupal 6. * * @staticvar type $_base * @param type $matches * @param type $base * @return type */ public static function buildCssPath($matches, $base = NULL) { static $_base; // Store base path for preg_replace_callback. if (isset($base)) { $_base = $base; } // Prefix with base and remove '../' segments where possible. $path = $_base . $matches[1]; $last = ''; while ($path != $last) { $last = $path; $path = preg_replace('`(^|/)(?!\.\./)([^/]+)/\.\./`', '$1', $path); } return 'url('. $path .')'; } /** * Gets content type cache, applies user specific properties and formats * as camelCase. * * @return array $libraries Cached libraries from the H5P Hub with user specific * permission properties */ public function getUserSpecificContentTypeCache() { $cached_libraries = $this->ajaxInterface->getContentTypeCache(); // Check if user has access to install libraries $libraries = array(); foreach ($cached_libraries as &$result) { // Check if user can install content type $result->restricted = !$this->canInstallContentType($result); // Formats json $libraries[] = $this->getCachedLibsMap($result); } return $libraries; } public function canInstallContentType($contentType) { $canInstallAll = $this->h5p->h5pF->hasPermission(H5PPermission::UPDATE_LIBRARIES); $canInstallRecommended = $this->h5p->h5pF->hasPermission(H5PPermission::INSTALL_RECOMMENDED); return $canInstallAll || $contentType->is_recommended && $canInstallRecommended; } /** * Gets local and external libraries data with metadata to display * all libraries that are currently available for the user. * * @return array $libraries Latest local and external libraries data with * user specific permissions */ public function getLatestGlobalLibrariesData() { $latest_local_libraries = $this->ajaxInterface->getLatestLibraryVersions(); $cached_libraries = $this->getUserSpecificContentTypeCache(); $this->mergeLocalLibsIntoCachedLibs($latest_local_libraries, $cached_libraries); return $cached_libraries; } /** * Extract library properties from cached library so they are ready to be * returned as JSON * * @param object $cached_library A single library from the content type cache * * @return array A map containing the necessary properties for a cached * library to send to the front-end */ public function getCachedLibsMap($cached_library) { $restricted = isset($cached_library->restricted) ? $cached_library->restricted : FALSE; // Add mandatory fields $lib = array( 'id' => intval($cached_library->id), 'machineName' => $cached_library->machine_name, 'majorVersion' => intval( $cached_library->major_version), 'minorVersion' => intval($cached_library->minor_version), 'patchVersion' => intval($cached_library->patch_version), 'h5pMajorVersion' => intval($cached_library->h5p_major_version), 'h5pMinorVersion' => intval($cached_library->h5p_minor_version), 'title' => $cached_library->title, 'summary' => $cached_library->summary, 'description' => $cached_library->description, 'icon' => $cached_library->icon, 'createdAt' => intval($cached_library->created_at), 'updatedAt' => intval($cached_library->updated_at), 'isRecommended' => $cached_library->is_recommended != 0, 'popularity' => intval($cached_library->popularity), 'screenshots' => json_decode($cached_library->screenshots), 'license' => json_decode($cached_library->license), 'owner' => $cached_library->owner, 'installed' => FALSE, 'isUpToDate' => FALSE, 'restricted' => $restricted, 'canInstall' => !$restricted ); // Add optional fields if (!empty($cached_library->categories)) { $lib['categories'] = json_decode($cached_library->categories); } if (!empty($cached_library->keywords)) { $lib['keywords'] = json_decode($cached_library->keywords); } if (!empty($cached_library->tutorial)) { $lib['tutorial'] = $cached_library->tutorial; } if (!empty($cached_library->example)) { $lib['example'] = $cached_library->example; } if (!empty($cached_library->icons)) { $lib['icons'] = json_decode($cached_library->icons); } return $lib; } /** * Merge local libraries into cached libraries so that local libraries will * get supplemented with the additional info from externally cached libraries. * * Also sets whether a given cached library is installed and up to date with * the locally installed libraries * * @param array $local_libraries Locally installed libraries * @param array $cached_libraries Cached libraries from the H5P hub */ public function mergeLocalLibsIntoCachedLibs($local_libraries, &$cached_libraries) { $can_create_restricted = $this->h5p->h5pF->hasPermission(H5PPermission::CREATE_RESTRICTED); // Add local libraries to supplement content type cache foreach ($local_libraries as $local_lib) { $is_local_only = TRUE; $icon_path = NULL; // Check if icon is available locally: if ($local_lib->has_icon) { // Create path to icon: $library_folder = H5PCore::libraryToFolderName([ 'machineName' => $local_lib->machine_name, 'majorVersion' => $local_lib->major_version, 'minorVersion' => $local_lib->minor_version, 'patchVersion' => $local_lib->patch_version, 'patchVersionInFolderName' => $local_lib->patch_version_in_folder_name ]); $icon_path = $this->h5p->h5pF->getLibraryFileUrl($library_folder, 'icon.svg'); } foreach ($cached_libraries as &$cached_lib) { // Determine if library is local $is_matching_library = $cached_lib['machineName'] === $local_lib->machine_name; if ($is_matching_library) { $is_local_only = FALSE; // Set icon if it exists locally if (isset($icon_path)) { $cached_lib['icon'] = $icon_path; } // Set local properties $cached_lib['installed'] = TRUE; $cached_lib['restricted'] = $can_create_restricted ? FALSE : ($local_lib->restricted ? TRUE : FALSE); // Set local version $cached_lib['localMajorVersion'] = (int) $local_lib->major_version; $cached_lib['localMinorVersion'] = (int) $local_lib->minor_version; $cached_lib['localPatchVersion'] = (int) $local_lib->patch_version; // Determine if library is newer or same as cache $major_is_updated = $cached_lib['majorVersion'] < $cached_lib['localMajorVersion']; $minor_is_updated = $cached_lib['majorVersion'] === $cached_lib['localMajorVersion'] && $cached_lib['minorVersion'] < $cached_lib['localMinorVersion']; $patch_is_updated = $cached_lib['majorVersion'] === $cached_lib['localMajorVersion'] && $cached_lib['minorVersion'] === $cached_lib['localMinorVersion'] && $cached_lib['patchVersion'] <= $cached_lib['localPatchVersion']; $is_updated_library = $major_is_updated || $minor_is_updated || $patch_is_updated; if ($is_updated_library) { $cached_lib['isUpToDate'] = TRUE; } } } // Add minimal data to display local only libraries if ($is_local_only) { $local_only_lib = array( 'id' => (int) $local_lib->id, 'machineName' => $local_lib->machine_name, 'title' => $local_lib->title, 'description' => '', 'majorVersion' => (int) $local_lib->major_version, 'minorVersion' => (int) $local_lib->minor_version, 'patchVersion' => (int) $local_lib->patch_version, 'localMajorVersion' => (int) $local_lib->major_version, 'localMinorVersion' => (int) $local_lib->minor_version, 'localPatchVersion' => (int) $local_lib->patch_version, 'canInstall' => FALSE, 'installed' => TRUE, 'isUpToDate' => TRUE, 'owner' => '', 'restricted' => $can_create_restricted ? FALSE : ($local_lib->restricted ? TRUE : FALSE) ); if (isset($icon_path)) { $local_only_lib['icon'] = $icon_path; } $cached_libraries[] = $local_only_lib; } } // Restrict LRS dependent content if (!$this->h5p->h5pF->getOption('enable_lrs_content_types')) { foreach ($cached_libraries as &$lib) { if (in_array($lib['machineName'], array('H5P.Questionnaire', 'H5P.FreeTextQuestion'))) { $lib['restricted'] = TRUE; } } } } /** * Determine if a library has a presave.js file in the root folder * * @param string $libraryName * @return bool */ public function hasPresave($libraryName){ if( isset($this->h5p->h5pD) ){ $parsedLibrary = H5PCore::libraryFromString($libraryName); if($parsedLibrary !== false){ $machineName = $parsedLibrary['machineName']; $majorVersion = $parsedLibrary['majorVersion']; $minorVersion = $parsedLibrary['minorVersion']; $library = $this->h5p->h5pD->getLibrary($machineName, $majorVersion, $minorVersion); if( !is_null($library)){ return $this->h5p->fs->hasPresave($libraryName, $library['path']); } } } return $this->h5p->fs->hasPresave($libraryName); } /** * Adds the path to the presave.js file to the list of dependency assets for the library * * @param array $assets * @param array $library * @param string $prefix */ public function addPresaveFile(&$assets, $library, $prefix = ''){ $path = 'libraries' . '/' . H5PCore::libraryToFolderName($library); if( array_key_exists('path', $library)){ $path = $library['path']; } $version = "?ver={$library['majorVersion']}.{$library['minorVersion']}.{$library['patchVersion']}"; if( array_key_exists('version', $library) ){ $version = $library['version']; } $assets['scripts'][] = (object) array( 'path' => $prefix . '/' . $path . '/' . 'presave.js', 'version' => $version, ); } } PK*\|$$.h5plib/v127/joubel/editor/styles/css/fonts.cssnu[@font-face { font-family: 'h5p-hub'; src: url('fonts/h5p-hub.eot?626d03'); src: url('fonts/h5p-hub.eot?626d03#iefix') format('embedded-opentype'), url('fonts/h5p-hub.ttf?626d03') format('truetype'), url('fonts/h5p-hub.woff?626d03') format('woff'), url('fonts/h5p-hub.svg?626d03#h5p-hub') format('svg'); font-weight: normal; font-style: normal; } @font-face { font-family: 'h5p-metadata-icons'; src: url('fonts/h5p-metadata-icons.eot?qj7uq5'); src: url('fonts/h5p-metadata-icons.eot?qj7uq5#iefix') format('embedded-opentype'), url('fonts/h5p-metadata-icons.ttf?qj7uq5') format('truetype'), url('fonts/h5p-metadata-icons.woff?qj7uq5') format('woff'), url('fonts/h5p-metadata-icons.svg?qj7uq5#h5p-metadata-icons') format('svg'); font-weight: normal; font-style: normal; } PK*\-26h5plib/v127/joubel/editor/styles/css/fonts/h5p-hub.eotnu[LP h5p-hubRegularVersion 1.2h5p-hub 0OS/2`cmap騥$tgaspglyf1xhead z(6hhea +`$hmtxjOlloca@0El8maxp#( name:RHpost C3 @$@@ X !$ #797979 ,,<^{.#!!676!327>767676&'&'+532"%#!!!!!&'.'&'%32654&##7>'.#"#33>733267>?3#7#'.7%2#"&'##37>7"767>'&#(wPB#077n33(+ >&#Z/00U## #<*\h"E &'>uO[-%&< >&6MM6Y)   YaY  L%%sX(   YFDJ*.4-  1 + DaY,# S&" %'33n771%; O%.*11c--   'k) }_P >&&,$ (M66L3 % J+W+R" & J="+a'N*) 0 +U-G! K J<%#"&/#"&/.546?.546?>327>32v " "   v" " "v   Qv   v " "v   v "8t#"'.'&'#"&5463!2327>767>7>;27#!"&546?.#"+0"1"&'167>76320327>32..QR[310Z(("U *[-zD.++K  | [-xC.+*K   ..QRZ301Y()"V QWIJk % U* [,3 +%&  [+1 *$& VIIj % U8k{"'.'&547>7632327>7654'.'&#"+"&=467>54&#"#"&/.7>32+"&=46;2j\]((((]\jj]]())(]]!"sNMXXNMt!!!!tMNXXMNs"!+ j F##51 Z4P4YG4:   ZOY4:  !!Ze ZZZ?c"'.'&547>7632#81"327>7650454'.'&'#"&/.546?>327>32j]]((((^]jj]^(()(^]jKBBccBBKKBBccBBK  D a D@)(]]jj]^((((^]jj]^((icBBKKBBccBBKKBBc DaD 8!#0"1"&'.581467>32!, 1 1  R   1  - .  2     1  .  s/?#!"&=463!2#!"&=463!2%#!"&=463!2#!"&=463!2.!!..!;!..!!..!;!.&.!!..!;!..!!..!;!.4!..!!..!8!..! // !..!!..!8!..! // o7So1#.504=041467300+"&5<1504546;2101#.504=<1467301!.504=041467!00#!"&5<15045463!2101!.504=<1467!0%         %  %  % !!v!!Q!!v!!P!!u!!!!v!!Q!!v!!P!!u!!,=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5  /?>/  4FE4L  6GG5  2CB2C2  +99*  2ECb  b L32L  MO56N_  S78R  Q55Q 4M  I//H  M41g47>76321#8#.'.'"#*#"'.'&5'67>76;4654&54'.'&#"1383>7>7&K239923K9+  (H  812J*)qDEKlIHSRHHkQ? (   9f+)$$55$$)3R. &5#$)`8..A:43MM44;Jw(A  6&$n#"&'.'.5467>7>3250414&#"01#0414�"1#8#"010132013#8#"01013201!832658550414�"1#8#"0101320138126585!$%!!]99GG99]!!%%!!]99GG99]! B  @@ + W   7GF98]"!%%!"]89FG98]!!%%!!]8j \ j j Qj j 7T"'.'&547>7632"327>7654'.'&#"'.'&547>7632j]^((((^]jj]^((((^]jWMMs!!!!sMMWWMMs!!!!sMM}9'&,,&'99'&,,&'9@((^]jj]^((((^]jj]^((!!sMMWWMMs!!!!sMMWWMMs!!Z,&'99'&,,&'99'&,!"3!2654& 7/CC//CCOOC//CC//CPO7"'.'&547>7632"327>7654'.'&j]^((((^]jj]^((((^]jWMMs!!!!sMMWWMMs!!!!sMM@((^]jj]^((((^]jj]^((!!sMMWWMMs!!!!sMMWWMMs!!!%!"3!2654&/CC//CCNrC//CC//C  #"&'>32 @  %%   @ %% @   )F81"&/#"'.'&547>7632#"327>7654'.'&# 3}EYONu""""uNOYZONu""(% -!932JJ239832JJ238@ $)""vNOYZNOu""""uONZD~4 !.^J329922JJ229923Ja/#!"&=463!2#!"&=463!2#!"&=463!2a v    v    v   'effD"'.'&'&'.'&5467>7327>7654&'.'7#1/0X(("#$ &%$d<)1Q lHIRRIHl Q1)54&', ## ## -   "#   +  1  - ## a   ## 33 _< ڗhڗh , O , O, FFPhJh~"$Hp   c      n  4/h5p-hubh5p-hubFont generated by IcoMoon.Font generated by IcoMoon.Version 1.2Version 1.2h5p-hubh5p-hubh5p-hubh5p-hubRegularRegularh5p-hubh5p-hubPK*\ş=HHAh5plib/v127/joubel/editor/styles/css/fonts/h5p-metadata-icons.svgnu[ { "fontFamily": "h5p-metadata-icons", "description": "Font generated by IcoMoon.", "majorVersion": 1, "minorVersion": 1, "copyright": "H5P", "fontURL": "", "version": "Version 1.1", "fontId": "h5p-metadata-icons", "psName": "h5p-metadata-icons", "subFamily": "Regular", "fullName": "h5p-metadata-icons" } PK*\ i¢NN6h5plib/v127/joubel/editor/styles/css/fonts/h5p-hub.svgnu[ { "fontFamily": "h5p-hub", "description": "Font generated by IcoMoon.", "majorVersion": 1, "minorVersion": 2, "version": "Version 1.2", "fontId": "h5p-hub", "psName": "h5p-hub", "subFamily": "Regular", "fullName": "h5p-hub" } PK*\/ӘAh5plib/v127/joubel/editor/styles/css/fonts/h5p-metadata-icons.eotnu[LP>t-$h5p-metadata-iconsRegularVersion 1.1$h5p-metadata-icons 0OS/2`cmapVҌTgasppglyfx`headj6hhea$hmtx(4(loca \maxpt name?T+post 3 @@@ 8   797979;#!+"&'.5!"&'.=467>3!467>;2!2    ; ; T   ; <   7' 'rmrr#`"'.'.'&47>7>7627>54&/7>54&/.#"'.#"326?3267k1BB11tBBBBt11BB11tBBBCsQQ  RR  1sBBCBs11BB11sBCBBs11BBiR  RR  R -3X'\x"&"##"&'.'.#.'.'.'.5.'.'.'.#24'.'"&'.'.'&474&1.#.#&"1*5.54&5.'.'0252034&'.7.'.'.'.'.'"&'.7&'.7'<5467463"&'&4743>'.'.16&'5"4'4&#"&'>7623236&'>762.'&0#"#>7*:762;6'64'&47267267>16&'"&#.#.'.7467>22>317>7>1.7>2##"&'.#"'0#6#662?>1>1>504'.'&47>7>76&'.5467>'4&5.546762#2627261267>3023:3267>7>3023027:32>13#"1.0#267>3>"#*#'2"#"'031#"#>32.'.'.#".5>77*10&'.#.'.'&'1'&"'0210'0"1"##3:3>74&1.'818#"&'.'.5467>7>3254&'.+54&'.+";#";267>54&'.+";267>"&'.'.5467>7>321"3267>7>54&'1.'.#"&'.=467>;5#"&'.=467>;232#'";267>=4&'.+54&'.+";#7#"&'.=467>;2'";267>=4&'.#  @(             1wB<L00i89i00KK0>!N%X>0B$$B/0B$$B0!n!!,BB,$B00B$$B00B$#C00B$$B00B) n "n""nBBEBv    &=   $* 0[*0LL00i89i00L!5c+w *B$$B00B$$B0077n7577l0B$$B00B$$B00B$$B00B$#C0I7l77M777p77L669V>32&'.?5#75'3267>54&'.#">54&/.#"326?8   , yH@  3  x""\ \ ,   x`@H4    ""x\ \8"'.'&547>7672&'.'&#"327>765'.#"&'.'&67>7>78176&'.'.'467>7>''2654&'"3k]])((']]kj^]()((^]l%&VVa`VU%%&%VV`aVU%% 0,,/  ?! $    $  @ )'*)@((]]kj^]((((^]jj^]((aVU%%&%UVaaVU%%&&VV`     ;l5"! 7 7 !"5l;  ))'*-t>_< mR4mR4  xP  /  6  $ ! $ $A  $ 4Ph5p-metadata-iconsh5p-metadata-iconsFont generated by IcoMoon.Font generated by IcoMoon.H5PH5PVersion 1.1Version 1.1h5p-metadata-iconsh5p-metadata-iconsh5p-metadata-iconsh5p-metadata-iconsRegularRegularh5p-metadata-iconsh5p-metadata-iconsPK*\!Ah5plib/v127/joubel/editor/styles/css/fonts/h5p-metadata-icons.ttfnu[ 0OS/2`cmapVҌTgasppglyfx`headj6hhea$hmtx(4(loca \maxpt name?T+post 3 @@@ 8   797979;#!+"&'.5!"&'.=467>3!467>;2!2    ; ; T   ; <   7' 'rmrr#`"'.'.'&47>7>7627>54&/7>54&/.#"'.#"326?3267k1BB11tBBBBt11BB11tBBBCsQQ  RR  1sBBCBs11BB11sBCBBs11BBiR  RR  R -3X'\x"&"##"&'.'.#.'.'.'.5.'.'.'.#24'.'"&'.'.'&474&1.#.#&"1*5.54&5.'.'0252034&'.7.'.'.'.'.'"&'.7&'.7'<5467463"&'&4743>'.'.16&'5"4'4&#"&'>7623236&'>762.'&0#"#>7*:762;6'64'&47267267>16&'"&#.#.'.7467>22>317>7>1.7>2##"&'.#"'0#6#662?>1>1>504'.'&47>7>76&'.5467>'4&5.546762#2627261267>3023:3267>7>3023027:32>13#"1.0#267>3>"#*#'2"#"'031#"#>32.'.'.#".5>77*10&'.#.'.'&'1'&"'0210'0"1"##3:3>74&1.'818#"&'.'.5467>7>3254&'.+54&'.+";#";267>54&'.+";267>"&'.'.5467>7>321"3267>7>54&'1.'.#"&'.=467>;5#"&'.=467>;232#'";267>=4&'.+54&'.+";#7#"&'.=467>;2'";267>=4&'.#  @(             1wB<L00i89i00KK0>!N%X>0B$$B/0B$$B0!n!!,BB,$B00B$$B00B$#C00B$$B00B) n "n""nBBEBv    &=   $* 0[*0LL00i89i00L!5c+w *B$$B00B$$B0077n7577l0B$$B00B$$B00B$$B00B$#C0I7l77M777p77L669V>32&'.?5#75'3267>54&'.#">54&/.#"326?8   , yH@  3  x""\ \ ,   x`@H4    ""x\ \8"'.'&547>7672&'.'&#"327>765'.#"&'.'&67>7>78176&'.'.'467>7>''2654&'"3k]])((']]kj^]()((^]l%&VVa`VU%%&%VV`aVU%% 0,,/  ?! $    $  @ )'*)@((]]kj^]((((^]jj^]((aVU%%&%UVaaVU%%&&VV`     ;l5"! 7 7 !"5l;  ))'*-t>_< mR4mR4  xP  /  6  $ ! $ $A  $ 4Ph5p-metadata-iconsh5p-metadata-iconsFont generated by IcoMoon.Font generated by IcoMoon.H5PH5PVersion 1.1Version 1.1h5p-metadata-iconsh5p-metadata-iconsh5p-metadata-iconsh5p-metadata-iconsRegularRegularh5p-metadata-iconsh5p-metadata-iconsPK*\Vl<<7h5plib/v127/joubel/editor/styles/css/fonts/h5p-hub.woffnu[wOFF< OS/2``cmaphtt騥$gaspglyf1xheadt66 zhhea$$ +hmtxlljOloca<88@0Elmaxpt #name:Rpost C3 @$@@ X !$ #797979 ,,<^{.#!!676!327>767676&'&'+532"%#!!!!!&'.'&'%32654&##7>'.#"#33>733267>?3#7#'.7%2#"&'##37>7"767>'&#(wPB#077n33(+ >&#Z/00U## #<*\h"E &'>uO[-%&< >&6MM6Y)   YaY  L%%sX(   YFDJ*.4-  1 + DaY,# S&" %'33n771%; O%.*11c--   'k) }_P >&&,$ (M66L3 % J+W+R" & J="+a'N*) 0 +U-G! K J<%#"&/#"&/.546?.546?>327>32v " "   v" " "v   Qv   v " "v   v "8t#"'.'&'#"&5463!2327>767>7>;27#!"&546?.#"+0"1"&'167>76320327>32..QR[310Z(("U *[-zD.++K  | [-xC.+*K   ..QRZ301Y()"V QWIJk % U* [,3 +%&  [+1 *$& VIIj % U8k{"'.'&547>7632327>7654'.'&#"+"&=467>54&#"#"&/.7>32+"&=46;2j\]((((]\jj]]())(]]!"sNMXXNMt!!!!tMNXXMNs"!+ j F##51 Z4P4YG4:   ZOY4:  !!Ze ZZZ?c"'.'&547>7632#81"327>7650454'.'&'#"&/.546?>327>32j]]((((^]jj]^(()(^]jKBBccBBKKBBccBBK  D a D@)(]]jj]^((((^]jj]^((icBBKKBBccBBKKBBc DaD 8!#0"1"&'.581467>32!, 1 1  R   1  - .  2     1  .  s/?#!"&=463!2#!"&=463!2%#!"&=463!2#!"&=463!2.!!..!;!..!!..!;!.&.!!..!;!..!!..!;!.4!..!!..!8!..! // !..!!..!8!..! // o7So1#.504=041467300+"&5<1504546;2101#.504=<1467301!.504=041467!00#!"&5<15045463!2101!.504=<1467!0%         %  %  % !!v!!Q!!v!!P!!u!!!!v!!Q!!v!!P!!u!!,=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5  /?>/  4FE4L  6GG5  2CB2C2  +99*  2ECb  b L32L  MO56N_  S78R  Q55Q 4M  I//H  M41g47>76321#8#.'.'"#*#"'.'&5'67>76;4654&54'.'&#"1383>7>7&K239923K9+  (H  812J*)qDEKlIHSRHHkQ? (   9f+)$$55$$)3R. &5#$)`8..A:43MM44;Jw(A  6&$n#"&'.'.5467>7>3250414&#"01#0414�"1#8#"010132013#8#"01013201!832658550414�"1#8#"0101320138126585!$%!!]99GG99]!!%%!!]99GG99]! B  @@ + W   7GF98]"!%%!"]89FG98]!!%%!!]8j \ j j Qj j 7T"'.'&547>7632"327>7654'.'&#"'.'&547>7632j]^((((^]jj]^((((^]jWMMs!!!!sMMWWMMs!!!!sMM}9'&,,&'99'&,,&'9@((^]jj]^((((^]jj]^((!!sMMWWMMs!!!!sMMWWMMs!!Z,&'99'&,,&'99'&,!"3!2654& 7/CC//CCOOC//CC//CPO7"'.'&547>7632"327>7654'.'&j]^((((^]jj]^((((^]jWMMs!!!!sMMWWMMs!!!!sMM@((^]jj]^((((^]jj]^((!!sMMWWMMs!!!!sMMWWMMs!!!%!"3!2654&/CC//CCNrC//CC//C  #"&'>32 @  %%   @ %% @   )F81"&/#"'.'&547>7632#"327>7654'.'&# 3}EYONu""""uNOYZONu""(% -!932JJ239832JJ238@ $)""vNOYZNOu""""uONZD~4 !.^J329922JJ229923Ja/#!"&=463!2#!"&=463!2#!"&=463!2a v    v    v   'effD"'.'&'&'.'&5467>7327>7654&'.'7#1/0X(("#$ &%$d<)1Q lHIRRIHl Q1)54&', ## ## -   "#   +  1  - ## a   ## 33 _< ڗhڗh , O , O, FFPhJh~"$Hp   c      n  4/h5p-hubh5p-hubFont generated by IcoMoon.Font generated by IcoMoon.Version 1.2Version 1.2h5p-hubh5p-hubh5p-hubh5p-hubRegularRegularh5p-hubh5p-hubPK*\Bh5plib/v127/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.woffnu[wOFF OS/2``cmaph||'gaspglyfahead660hhea$$hmtxPPFlocaP**3.maxp| 'nameVV post 3 @@@ ` #* #(797979E5\.#"#6&=#3733267>54&'#"&'.=467>32267>7#"&5467>32.'.#"3%.#">32"3267>73354&'#"&5467>73%2#!"&5463!5!"3!2654#53#"&=33'#535#53#53%#546;#%#532#5+53#53#53#53 2)  '       '(     !          nntBBv$  !! !!l  s  NBBBBBBBB 3 !! g  (,+! $}   r^    " %"!! !iAAB7B6 !! !!!!!!!S*Gn"3267>54&'.#7#";2654&##"&'##33>32%267>7#"&5467>32.'.#"3%.#">323267>73354&'#"&5467>73   s // -- %   0@     22 '!   ) #"       . :-  . )B **167*- ! '     v   ;`$a#"&/.546?>327>32#"&/#"&/.546?'.546?>327>32#"&/#"&/.546?'.546?>327>32#!"&=463!2#!"&=463!2#!"&=463!2J,a#................EEEɀJ,b....--..........+ (D%&7%64'4'.'&#"327>76%47>7632#"'.'&--M%$UVaaVU$%%$UVaaVU$%gEENNEEggEENNEEg w 6 "aUV%%%%VUabUV%%%%VUbNEEggEENOEEffEE31$;Sl#";654&%&767>7654'.'&'4&'&7>'&7>54&'00v  ( + + (   0%&55&%02I@  0550 @I "(("ӏQ  ""Q--/0--P#"   *)b66:967a)*L)  b89b  )  B'&B;AK\"/&4?6276201"'81'"'81'&4?'&4?628176281212764'1&" T L  DEEEEDEE  ;  c L  EEDEEEED   R  j}!Ck%&320616&'4&#!"3!265#81"&'467>7.54632#"&'#"&'.'#"&'23267>54&'sw($5] F12FF2    *2 64$B("? #$33$$3 "  )  $# 2"3$9'.#"'.#"3267>54&'!3.5467#!5#"&'4q4IHr'4q4I |   l 59!";!532654&#!!z 11 L 1-$ 1  1GG1  1]7W47>7632>54'.'&#"3:3'&'.'&576>7>54'.'&#"'&67.'.'&#"&&&'.'&#01006767>7>'R78>?77R3 nIJTSJIn nIJS+801G7o6  =*)//))=VCE/6     + ' -d  )(q<<)(,  )?77RR77? *SJIn nIJSSJIn iP34:.7/))>=))/Ju7o     AJ)(e-- &. I/>a*. (67364/&"7'&3!26/#2?'654&#!"j],d 53%#53%#535#53'*+532rv00 0/ v    uEEFF55o 0A000000E66./  00 $+   ////050 ,PEEEEKE%0+~\/?O_o!"3!26=4&!"3!26=4&!"3!26=4&!"3!26=4&#";26=4&#";26=4&#";26=4&g2     .   .   . X1  1  1  1  1  1  5  5  4  4  5  5  5  5  4  4  5  5  5  5 V`/;IUcp!"3!26=4&!"3!26=4&!"3!26=4&%2#"&5467"326542#"&5467"32654#"&546324a   >      %(('')99)(99((('')99)(99(h=++==++= :  :  :  :  ;  ; '(('9)(99()9''''9((99((9+==++==+ `i 0BRcs#";26=4&#%!"3!26=4&!2#!"&=463%!"3!26=42#!"&=463%!"3!26=4&#2+"&=4637#";26=4&#326=4&+"!326=4&+"326=4&+"3|         D%%D%%    && %%   &&&&.  c  Q  Q   =  =  =  =  =  = "&=%%=& =  = !%=&&=% <  < !%<%%<% <  <  <  < : =  = v$!_< x8x8ES;+3;j25]./~V` r`2nB p \x W     {  b  4#h5ph5pFont generated by IcoMoon.Font generated by IcoMoon.Version 1.1Version 1.1h5ph5ph5ph5pRegularRegularh5ph5pPK*\*F6h5plib/v127/joubel/editor/styles/css/fonts/h5p-hub.ttfnu[ 0OS/2`cmap騥$tgaspglyf1xhead z(6hhea +`$hmtxjOlloca@0El8maxp#( name:RHpost C3 @$@@ X !$ #797979 ,,<^{.#!!676!327>767676&'&'+532"%#!!!!!&'.'&'%32654&##7>'.#"#33>733267>?3#7#'.7%2#"&'##37>7"767>'&#(wPB#077n33(+ >&#Z/00U## #<*\h"E &'>uO[-%&< >&6MM6Y)   YaY  L%%sX(   YFDJ*.4-  1 + DaY,# S&" %'33n771%; O%.*11c--   'k) }_P >&&,$ (M66L3 % J+W+R" & J="+a'N*) 0 +U-G! K J<%#"&/#"&/.546?.546?>327>32v " "   v" " "v   Qv   v " "v   v "8t#"'.'&'#"&5463!2327>767>7>;27#!"&546?.#"+0"1"&'167>76320327>32..QR[310Z(("U *[-zD.++K  | [-xC.+*K   ..QRZ301Y()"V QWIJk % U* [,3 +%&  [+1 *$& VIIj % U8k{"'.'&547>7632327>7654'.'&#"+"&=467>54&#"#"&/.7>32+"&=46;2j\]((((]\jj]]())(]]!"sNMXXNMt!!!!tMNXXMNs"!+ j F##51 Z4P4YG4:   ZOY4:  !!Ze ZZZ?c"'.'&547>7632#81"327>7650454'.'&'#"&/.546?>327>32j]]((((^]jj]^(()(^]jKBBccBBKKBBccBBK  D a D@)(]]jj]^((((^]jj]^((icBBKKBBccBBKKBBc DaD 8!#0"1"&'.581467>32!, 1 1  R   1  - .  2     1  .  s/?#!"&=463!2#!"&=463!2%#!"&=463!2#!"&=463!2.!!..!;!..!!..!;!.&.!!..!;!..!!..!;!.4!..!!..!8!..! // !..!!..!8!..! // o7So1#.504=041467300+"&5<1504546;2101#.504=<1467301!.504=041467!00#!"&5<15045463!2101!.504=<1467!0%         %  %  % !!v!!Q!!v!!P!!u!!!!v!!Q!!v!!P!!u!!,=\54&+";265>54&'4&+";26=>54&'%4&/4&+";265>5  /?>/  4FE4L  6GG5  2CB2C2  +99*  2ECb  b L32L  MO56N_  S78R  Q55Q 4M  I//H  M41g47>76321#8#.'.'"#*#"'.'&5'67>76;4654&54'.'&#"1383>7>7&K239923K9+  (H  812J*)qDEKlIHSRHHkQ? (   9f+)$$55$$)3R. &5#$)`8..A:43MM44;Jw(A  6&$n#"&'.'.5467>7>3250414&#"01#0414�"1#8#"010132013#8#"01013201!832658550414�"1#8#"0101320138126585!$%!!]99GG99]!!%%!!]99GG99]! B  @@ + W   7GF98]"!%%!"]89FG98]!!%%!!]8j \ j j Qj j 7T"'.'&547>7632"327>7654'.'&#"'.'&547>7632j]^((((^]jj]^((((^]jWMMs!!!!sMMWWMMs!!!!sMM}9'&,,&'99'&,,&'9@((^]jj]^((((^]jj]^((!!sMMWWMMs!!!!sMMWWMMs!!Z,&'99'&,,&'99'&,!"3!2654& 7/CC//CCOOC//CC//CPO7"'.'&547>7632"327>7654'.'&j]^((((^]jj]^((((^]jWMMs!!!!sMMWWMMs!!!!sMM@((^]jj]^((((^]jj]^((!!sMMWWMMs!!!!sMMWWMMs!!!%!"3!2654&/CC//CCNrC//CC//C  #"&'>32 @  %%   @ %% @   )F81"&/#"'.'&547>7632#"327>7654'.'&# 3}EYONu""""uNOYZONu""(% -!932JJ239832JJ238@ $)""vNOYZNOu""""uONZD~4 !.^J329922JJ229923Ja/#!"&=463!2#!"&=463!2#!"&=463!2a v    v    v   'effD"'.'&'&'.'&5467>7327>7654&'.'7#1/0X(("#$ &%$d<)1Q lHIRRIHl Q1)54&', ## ## -   "#   +  1  - ## a   ## 33 _< ڗhڗh , O , O, FFPhJh~"$Hp   c      n  4/h5p-hubh5p-hubFont generated by IcoMoon.Font generated by IcoMoon.Version 1.2Version 1.2h5p-hubh5p-hubh5p-hubh5p-hubRegularRegularh5p-hubh5p-hubPK*\6/4Ah5plib/v127/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.ttfnu[ 0OS/2`cmap'|gaspglyfahead0X6hhea$hmtxFPloca3.*maxp'0 name PVpost 3 @@@ ` #* #(797979E5\.#"#6&=#3733267>54&'#"&'.=467>32267>7#"&5467>32.'.#"3%.#">32"3267>73354&'#"&5467>73%2#!"&5463!5!"3!2654#53#"&=33'#535#53#53%#546;#%#532#5+53#53#53#53 2)  '       '(     !          nntBBv$  !! !!l  s  NBBBBBBBB 3 !! g  (,+! $}   r^    " %"!! !iAAB7B6 !! !!!!!!!S*Gn"3267>54&'.#7#";2654&##"&'##33>32%267>7#"&5467>32.'.#"3%.#">323267>73354&'#"&5467>73   s // -- %   0@     22 '!   ) #"       . :-  . )B **167*- ! '     v   ;`$a#"&/.546?>327>32#"&/#"&/.546?'.546?>327>32#"&/#"&/.546?'.546?>327>32#!"&=463!2#!"&=463!2#!"&=463!2J,a#................EEEɀJ,b....--..........+ (D%&7%64'4'.'&#"327>76%47>7632#"'.'&--M%$UVaaVU$%%$UVaaVU$%gEENNEEggEENNEEg w 6 "aUV%%%%VUabUV%%%%VUbNEEggEENOEEffEE31$;Sl#";654&%&767>7654'.'&'4&'&7>'&7>54&'00v  ( + + (   0%&55&%02I@  0550 @I "(("ӏQ  ""Q--/0--P#"   *)b66:967a)*L)  b89b  )  B'&B;AK\"/&4?6276201"'81'"'81'&4?'&4?628176281212764'1&" T L  DEEEEDEE  ;  c L  EEDEEEED   R  j}!Ck%&320616&'4&#!"3!265#81"&'467>7.54632#"&'#"&'.'#"&'23267>54&'sw($5] F12FF2    *2 64$B("? #$33$$3 "  )  $# 2"3$9'.#"'.#"3267>54&'!3.5467#!5#"&'4q4IHr'4q4I |   l 59!";!532654&#!!z 11 L 1-$ 1  1GG1  1]7W47>7632>54'.'&#"3:3'&'.'&576>7>54'.'&#"'&67.'.'&#"&&&'.'&#01006767>7>'R78>?77R3 nIJTSJIn nIJS+801G7o6  =*)//))=VCE/6     + ' -d  )(q<<)(,  )?77RR77? *SJIn nIJSSJIn iP34:.7/))>=))/Ju7o     AJ)(e-- &. I/>a*. (67364/&"7'&3!26/#2?'654&#!"j],d 53%#53%#535#53'*+532rv00 0/ v    uEEFF55o 0A000000E66./  00 $+   ////050 ,PEEEEKE%0+~\/?O_o!"3!26=4&!"3!26=4&!"3!26=4&!"3!26=4&#";26=4&#";26=4&#";26=4&g2     .   .   . X1  1  1  1  1  1  5  5  4  4  5  5  5  5  4  4  5  5  5  5 V`/;IUcp!"3!26=4&!"3!26=4&!"3!26=4&%2#"&5467"326542#"&5467"32654#"&546324a   >      %(('')99)(99((('')99)(99(h=++==++= :  :  :  :  ;  ; '(('9)(99()9''''9((99((9+==++==+ `i 0BRcs#";26=4&#%!"3!26=4&!2#!"&=463%!"3!26=42#!"&=463%!"3!26=4&#2+"&=4637#";26=4&#326=4&+"!326=4&+"326=4&+"3|         D%%D%%    && %%   &&&&.  c  Q  Q   =  =  =  =  =  = "&=%%=& =  = !%=&&=% <  < !%<%%<% <  <  <  < : =  = v$!_< x8x8ES;+3;j25]./~V` r`2nB p \x W     {  b  4#h5ph5pFont generated by IcoMoon.Font generated by IcoMoon.Version 1.1Version 1.1h5ph5ph5ph5pRegularRegularh5ph5pPK*\\\Ah5plib/v127/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.eotnu[\LP!$vh5pRegularVersion 1.1h5p 0OS/2`cmap'|gaspglyfahead0X6hhea$hmtxFPloca3.*maxp'0 name PVpost 3 @@@ ` #* #(797979E5\.#"#6&=#3733267>54&'#"&'.=467>32267>7#"&5467>32.'.#"3%.#">32"3267>73354&'#"&5467>73%2#!"&5463!5!"3!2654#53#"&=33'#535#53#53%#546;#%#532#5+53#53#53#53 2)  '       '(     !          nntBBv$  !! !!l  s  NBBBBBBBB 3 !! g  (,+! $}   r^    " %"!! !iAAB7B6 !! !!!!!!!S*Gn"3267>54&'.#7#";2654&##"&'##33>32%267>7#"&5467>32.'.#"3%.#">323267>73354&'#"&5467>73   s // -- %   0@     22 '!   ) #"       . :-  . )B **167*- ! '     v   ;`$a#"&/.546?>327>32#"&/#"&/.546?'.546?>327>32#"&/#"&/.546?'.546?>327>32#!"&=463!2#!"&=463!2#!"&=463!2J,a#................EEEɀJ,b....--..........+ (D%&7%64'4'.'&#"327>76%47>7632#"'.'&--M%$UVaaVU$%%$UVaaVU$%gEENNEEggEENNEEg w 6 "aUV%%%%VUabUV%%%%VUbNEEggEENOEEffEE31$;Sl#";654&%&767>7654'.'&'4&'&7>'&7>54&'00v  ( + + (   0%&55&%02I@  0550 @I "(("ӏQ  ""Q--/0--P#"   *)b66:967a)*L)  b89b  )  B'&B;AK\"/&4?6276201"'81'"'81'&4?'&4?628176281212764'1&" T L  DEEEEDEE  ;  c L  EEDEEEED   R  j}!Ck%&320616&'4&#!"3!265#81"&'467>7.54632#"&'#"&'.'#"&'23267>54&'sw($5] F12FF2    *2 64$B("? #$33$$3 "  )  $# 2"3$9'.#"'.#"3267>54&'!3.5467#!5#"&'4q4IHr'4q4I |   l 59!";!532654&#!!z 11 L 1-$ 1  1GG1  1]7W47>7632>54'.'&#"3:3'&'.'&576>7>54'.'&#"'&67.'.'&#"&&&'.'&#01006767>7>'R78>?77R3 nIJTSJIn nIJS+801G7o6  =*)//))=VCE/6     + ' -d  )(q<<)(,  )?77RR77? *SJIn nIJSSJIn iP34:.7/))>=))/Ju7o     AJ)(e-- &. I/>a*. (67364/&"7'&3!26/#2?'654&#!"j],d 53%#53%#535#53'*+532rv00 0/ v    uEEFF55o 0A000000E66./  00 $+   ////050 ,PEEEEKE%0+~\/?O_o!"3!26=4&!"3!26=4&!"3!26=4&!"3!26=4&#";26=4&#";26=4&#";26=4&g2     .   .   . X1  1  1  1  1  1  5  5  4  4  5  5  5  5  4  4  5  5  5  5 V`/;IUcp!"3!26=4&!"3!26=4&!"3!26=4&%2#"&5467"326542#"&5467"32654#"&546324a   >      %(('')99)(99((('')99)(99(h=++==++= :  :  :  :  ;  ; '(('9)(99()9''''9((99((9+==++==+ `i 0BRcs#";26=4&#%!"3!26=4&!2#!"&=463%!"3!26=42#!"&=463%!"3!26=4&#2+"&=4637#";26=4&#326=4&+"!326=4&+"326=4&+"3|         D%%D%%    && %%   &&&&.  c  Q  Q   =  =  =  =  =  = "&=%%=& =  = !%=&&=% <  < !%<%%<% <  <  <  < : =  = v$!_< x8x8ES;+3;j25]./~V` r`2nB p \x W     {  b  4#h5ph5pFont generated by IcoMoon.Font generated by IcoMoon.Version 1.1Version 1.1h5ph5ph5ph5pRegularRegularh5ph5pPK*\_1,,Bh5plib/v127/joubel/editor/styles/css/fonts/h5p-metadata-icons.woffnu[wOFF, OS/2``cmaphTTVҌgaspglyf``head$66jhhea\$$hmtx(((loca maxp name++?Tpost 3 @@@ 8   797979;#!+"&'.5!"&'.=467>3!467>;2!2    ; ; T   ; <   7' 'rmrr#`"'.'.'&47>7>7627>54&/7>54&/.#"'.#"326?3267k1BB11tBBBBt11BB11tBBBCsQQ  RR  1sBBCBs11BB11sBCBBs11BBiR  RR  R -3X'\x"&"##"&'.'.#.'.'.'.5.'.'.'.#24'.'"&'.'.'&474&1.#.#&"1*5.54&5.'.'0252034&'.7.'.'.'.'.'"&'.7&'.7'<5467463"&'&4743>'.'.16&'5"4'4&#"&'>7623236&'>762.'&0#"#>7*:762;6'64'&47267267>16&'"&#.#.'.7467>22>317>7>1.7>2##"&'.#"'0#6#662?>1>1>504'.'&47>7>76&'.5467>'4&5.546762#2627261267>3023:3267>7>3023027:32>13#"1.0#267>3>"#*#'2"#"'031#"#>32.'.'.#".5>77*10&'.#.'.'&'1'&"'0210'0"1"##3:3>74&1.'818#"&'.'.5467>7>3254&'.+54&'.+";#";267>54&'.+";267>"&'.'.5467>7>321"3267>7>54&'1.'.#"&'.=467>;5#"&'.=467>;232#'";267>=4&'.+54&'.+";#7#"&'.=467>;2'";267>=4&'.#  @(             1wB<L00i89i00KK0>!N%X>0B$$B/0B$$B0!n!!,BB,$B00B$$B00B$#C00B$$B00B) n "n""nBBEBv    &=   $* 0[*0LL00i89i00L!5c+w *B$$B00B$$B0077n7577l0B$$B00B$$B00B$$B00B$#C0I7l77M777p77L669V>32&'.?5#75'3267>54&'.#">54&/.#"326?8   , yH@  3  x""\ \ ,   x`@H4    ""x\ \8"'.'&547>7672&'.'&#"327>765'.#"&'.'&67>7>78176&'.'.'467>7>''2654&'"3k]])((']]kj^]()((^]l%&VVa`VU%%&%VV`aVU%% 0,,/  ?! $    $  @ )'*)@((]]kj^]((((^]jj^]((aVU%%&%UVaaVU%%&&VV`     ;l5"! 7 7 !"5l;  ))'*-t>_< mR4mR4  xP  /  6  $ ! $ $A  $ 4Ph5p-metadata-iconsh5p-metadata-iconsFont generated by IcoMoon.Font generated by IcoMoon.H5PH5PVersion 1.1Version 1.1h5p-metadata-iconsh5p-metadata-iconsh5p-metadata-iconsh5p-metadata-iconsRegularRegularh5p-metadata-iconsh5p-metadata-iconsPK*\YYAh5plib/v127/joubel/editor/styles/css/fonts/h5p-fullscreen-bar.svgnu[ { "fontFamily": "h5p", "description": "Font generated by IcoMoon.", "majorVersion": 1, "minorVersion": 1, "version": "Version 1.1", "fontId": "h5p", "psName": "h5p", "subFamily": "Regular", "fullName": "h5p" } PK*\ȕjܺ=h5plib/v127/joubel/editor/styles/css/ae8568c2320881fd5899.pngnu[PNG  IHDRKm)tEXtSoftwareAdobe ImageReadyqe<(iTXtXML:com.adobe.xmp (IDATxbܶm L 8?s._L ; ڼ`rIENDB`PK*\&:=h5plib/v127/joubel/editor/styles/css/a1aff8c82bc779d09357.pngnu[PNG  IHDR zjbKGD pHYs  IDATӝѱ 0 ()H]#kE  Bp %7?˒MOb7mfs|vXRfđ.2 qEjgX7V]/lP+;% { ʉ`NIENDB`PK*\B4h5plib/v127/joubel/editor/styles/css/application.cssnu[ul.list-unstyled{list-style:none;padding-left:0;margin:0}.field{margin:20px 0;font-size:16px;padding:0}.field:first-child{margin-top:0}.field:last-child{margin-bottom:0}.tree>.field.group:last-child{margin-bottom:0}.fields>.field.group{margin:10px 0}.fields>.field.group:first-child{margin-top:0}.fields>.field.group:last-child{margin-bottom:0}.field.boolean .h5peditor-label{display:inline}.field .h5p-editor-image-buttons{float:left;clear:both}.field .library{border:0}.field.importance-high>.h5peditor-label-wrapper>.h5peditor-label{font-size:18px;color:#356593}.field .h5p-dialog-anchor{position:relative;margin:-16px}.common-fields-library-wrapper{margin:20px 0;border:none;margin:0;padding:0}.common-fields-library-wrapper:first-child{margin-top:0}.common-fields-library-wrapper:last-child{margin-bottom:0}.common-fields-library-wrapper .common-field-legend{display:none}.common>.h5peditor-label,.h5p-li>.list-item-title-bar,.group>.title{visibility:inherit;cursor:pointer}.h5p-li>.list-item-title-bar.importance-high,.group.importance-high>.title{background:#2579c6;border:1px solid #1f67a8;height:42px}.h5p-li>.list-item-title-bar.importance-high>.title,.h5p-li>.list-item-title-bar.importance-high>.h5peditor-label,.group.importance-high>.title{font-size:16px;font-weight:600;line-height:42px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.h5p-li>.list-item-title-bar,.group>.title{background:#747275;border:1px solid #636164;height:38px}.h5p-li>.list-item-title-bar.importance-medium>.h5peditor-label,.h5p-li>.list-item-title-bar>.h5peditor-label,.group>.title{font-size:16px;font-weight:600;color:#fff;line-height:38px;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.common>.h5peditor-label,.h5p-li>.list-item-title-bar.importance-low,.group.importance-low>.title{background:#f5f5f5;height:38px;border:1px solid #d0d0d1}.common>.h5peditor-label,.h5p-li>.list-item-title-bar.importance-low>.title,.h5p-li>.list-item-title-bar.importance-low>.h5peditor-label,.group.importance-low>.title{font-size:16px;font-weight:400;color:#212121;line-height:38px}.group{border:none}.group>.title{padding:0 10px;outline:none}.group>.content{position:relative;display:none;margin:0;padding:20px;border:1px solid #d0d0d1;border-top:none;background:#fff}.group.importance-high>.title{color:#fff}.group.importance-low>.title{color:#212121}.group.importance-low>.title:focus:before{outline:1px dashed}.common .content,.content .content{background-color:#fcfcfc}.common .content .content,.content .content .content{background-color:#fff}.common .content .content .content,.content .content .content .content{background-color:#fcfcfc}.common .content .content .content .content,.content .content .content .content .content{background-color:#fff}.common .content .content .content .content .content,.content .content .content .content .content .content{background-color:#fcfcfc}.common .content .content .content .content .content .content,.content .content .content .content .content .content .content{background-color:#fff}.h5p-li>.list-item-title-bar{color:#fff}.h5p-li>.list-item-title-bar>.h5peditor-label{overflow:hidden;margin:0 54px 0 0;padding:0 10px;white-space:nowrap;line-height:38px;outline:none;text-overflow:ellipsis}.h5p-li>.list-item-title-bar>.list-actions{height:100%;float:right;position:relative}.h5p-li>.list-item-title-bar .remove{cursor:pointer;width:1.25em;height:38px;font-size:1.75em;display:inline-block}.h5p-li>.list-item-title-bar .remove:hover{opacity:1;text-decoration:none}.h5p-li>.list-item-title-bar .remove:after{font-family:"H5P";content:"";opacity:.7;display:inline-block;line-height:38px}.h5p-li>.list-item-title-bar .remove:hover:after{opacity:1}.h5p-li>.list-item-title-bar .order-group{text-align:center;float:right;background:#636164;font-size:16px;cursor:pointer}.h5p-li>.list-item-title-bar .order-up,.h5p-li>.list-item-title-bar .order-down{width:19px;height:19px;line-height:19px}.h5p-li>.list-item-title-bar .order-up:hover,.h5p-li>.list-item-title-bar .order-down:hover{background:#636164}.h5p-li>.list-item-title-bar .order-up:after,.h5p-li>.list-item-title-bar .order-down:after{font-family:"H5P";content:"";display:inline-block}.h5p-li>.list-item-title-bar .order-down:after{content:""}.h5p-li>.list-item-title-bar.importance-high>.title{border:none;margin:0 74px 0 0}.h5p-li>.list-item-title-bar.importance-high .remove{height:42px;line-height:42px;font-size:40px}.h5p-li>.list-item-title-bar.importance-high .remove:after{line-height:42px;opacity:.7}.h5p-li>.list-item-title-bar.importance-high .remove:hover:after{opacity:1}.h5p-li>.list-item-title-bar.importance-high .order-group{background:#1f67a8;font-size:18px}.h5p-li>.list-item-title-bar.importance-high .order-up,.h5p-li>.list-item-title-bar.importance-high .order-down{width:21px;height:21px;line-height:21px}.h5p-li>.list-item-title-bar.importance-high .order-up:hover,.h5p-li>.list-item-title-bar.importance-high .order-down:hover{background:#1f67a8}.h5p-li>.list-item-title-bar.importance-low>.title{border:none;margin:0 54px 0 0}.h5p-li>.list-item-title-bar.importance-low>.title:before{color:#212121}.h5p-li>.list-item-title-bar.importance-low>.title:focus:before{outline:1px dashed #212121}.h5p-li>.list-item-title-bar.importance-low .remove{height:38px;line-height:38px;font-size:30px}.h5p-li>.list-item-title-bar.importance-low .remove:after{line-height:38px}.h5p-li>.list-item-title-bar.importance-low .remove:after{color:#212121;opacity:.7}.h5p-li>.list-item-title-bar.importance-low .remove:hover:after{opacity:1}.h5p-li>.list-item-title-bar.importance-low .order-up,.h5p-li>.list-item-title-bar.importance-low .order-down{width:19px;height:19px;background:#d0d0d1;font-size:16px;line-height:19px}.h5p-li>.list-item-title-bar.importance-low .order-up:hover,.h5p-li>.list-item-title-bar.importance-low .order-down:hover{background:#deddde}.h5p-li>.list-item-title-bar.importance-low .order-up:after,.h5p-li>.list-item-title-bar.importance-low .order-down:after{color:#212121}.group.expanded>.content,.listgroup.expanded>.content{display:block}.listgroup>.list-item-title-bar>.h5peditor-label{cursor:pointer}.list-item-title-bar>.title:before,.group>.title:before{content:"";font-family:"H5P";margin-right:5px}.list-item-title-bar>.title:focus:before,.group>.title:focus:before{outline:1px dashed #fff}.listgroup.expanded>.list-item-title-bar>.h5peditor-label:before,.expanded>.title:before{content:""}.listgroup>.group.field{margin:0;padding:0;min-width:0}.content{display:block;margin:0;padding:20px;border:1px solid #d0d0d1;border-top:none;background:#fff}.common{margin-top:20px}.common>.h5peditor-label{margin:0;padding:0 10px;cursor:pointer;font-size:1em}.common>.h5peditor-label>.icon:before{content:"";font-family:"H5P";margin-right:5px}.common>.h5peditor-label:hover>.icon{opacity:1}.common>.h5peditor-label:focus{outline:none}.common>.h5peditor-label:focus>.icon:before{outline:1px dashed}.common>.fields{min-height:2em;padding:20px;border:1px solid #d0d0d1;border-top:none;background:#fff;position:relative}.common>.fields>.desc{margin:0;font-size:.875em;color:#666;float:left}.common>.fields p:first-child{margin-bottom:20px}.common.collapsed>.h5peditor-label>.icon:before{content:""}.common.collapsed>.fields{display:none}.common.hidden{display:none}.h5peditor-button[aria-label]:before{content:attr(aria-label);visibility:hidden;position:absolute;top:115%;right:-10%;z-index:2;padding:.25em .75em;background:#212121;color:#fff;white-space:nowrap;font-size:14px;line-height:1.5;box-shadow:0 0 .5em #858585}.h5peditor-button[aria-label]:hover:before{visibility:visible}.h5peditor-button[aria-label][aria-disabled=true]:before{display:none}.h5peditor .h5p-editing-image-button{background:linear-gradient(to bottom, #fff 0, #f2f2f2 100%);font-size:14px;color:#212121;line-height:28px;padding-right:20px;margin-right:.5em;height:30px;padding-left:0;font-weight:normal}.h5peditor .h5p-editing-image-button:hover:not([disabled]){background:linear-gradient(to bottom, #fff 0, #d0d0d1 100%);border-color:#999}.h5peditor .h5p-editing-image-button:before{font-family:"H5P";content:"";color:#666;padding-right:.3em;padding-left:.45em;vertical-align:middle;font-size:1.5em;line-height:.9}.h5peditor .h5p-editing-image-button.loading:before{content:""}.h5peditor .h5p-editing-image-button.hidden,.h5peditor .h5p-copyright-button.hidden{display:none !important}.h5peditor .ui-dialog .h5p-editing-image-button,.h5peditor .ui-dialog .h5p-copyright-button{padding-left:.5em}body.h5p-editor-image-popup{position:relative}.h5p-editing-image-popup-background{position:fixed;top:0;left:0;width:100%;height:100%;background:rgba(0,0,0,.8);padding:3em 1em;box-sizing:border-box;z-index:102}#darkroom-icons{top:0;left:0}.h5p-editing-image-popup-background.hidden{display:none}.h5p-editing-image-popup{display:inline-block;position:relative;top:0;background:#fff;-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}.h5p-editing-image-header{padding:1em .75em}.h5p-editing-image{max-height:100%;max-width:100%}.h5p-editing-image.hidden{display:none}.h5p-editing-image-popup .darkroom-toolbar{position:relative;-webkit-border-radius:0;-moz-border-radius:0;border-radius:0;top:0}.h5p-editing-image-popup .darkroom-toolbar:before{content:initial}.h5p-editing-image-popup .darkroom-image-container{padding:32px 2em}.h5p-editing-image-popup .darkroom-image-container .canvas-container{box-shadow:0 0 8px 3px rgba(0,0,0,.6);margin:auto}.h5p-editing-image-header-title{display:inline-block;font-size:1.25em}.h5p-editing-image-header-buttons{display:inline-block;float:right}.h5p-editing-image-loading{padding:1em}.h5p-editing-image-loading.hidden{display:none}.h5p-editing-image-editing-container{background:#666}.h5p-editing-image-header-buttons button{padding:.5em 1.75em;margin:0 0 0 1em;border:1px solid #ccc;border-radius:.25em;color:#333;cursor:pointer;background:#f2f2f2;background:-webkit-linear-gradient(top, #fff 0, #f2f2f2 100%);background:-ms-linear-gradient(top, #fff 0, #f2f2f2 100%)}.h5p-editing-image-header-buttons button:hover{background:#ededed}.h5p-editing-image-header-buttons .h5p-done{color:#fff;border-color:#20588f;background:#3673b5;background:-webkit-linear-gradient(top, #5A94D3 0, #3673B5 100%);background:-ms-linear-gradient(top, #5A94D3 0, #3673B5 100%)}.h5p-editing-image-header-buttons .h5p-done:hover{background:#3275bc;background:-webkit-linear-gradient(top, #3275bc 0, #285585 100%);background:-ms-linear-gradient(top, #3275bc 0, #285585 100%)}.h5p-editing-image-header-buttons .h5p-remove{background:none;border:none;color:#a00;padding-right:0;padding-left:0;border-radius:0}.h5p-editing-image-header-buttons .h5p-remove:hover{background:none;color:#e40000}.h5p-vtab-wrapper>.h5p-vtab-forms .h5p-remove:after{color:#d0d0d1}html,body{margin:0;padding:0;color:#212121;font-family:"Open Sans",sans-serif;max-width:960px;position:relative}a{text-decoration:none}.offsite{left:-9999px;opacity:0;position:absolute;top:0}.h5peditor{font-size:16px}.h5peditor .h5p-more-libraries{font-size:.875em;margin-top:.4em}.h5peditor .h5peditor-single>.field.library{border:0;padding:0}.h5peditor .cke_dialog_background_cover{width:100% !important;height:100% !important}.h5peditor .errors p,.h5peditor .h5p-errors{color:#da0001;white-space:normal}.h5peditor textarea{resize:vertical}.h5peditor .h5p-editor-flex-wrapper{display:flex;flex-direction:row}.h5peditor .h5p-editor-flex-wrapper.has-button-collapse{align-items:flex-end;margin-bottom:.5rem;width:100%}.h5peditor .h5p-editor-flex-wrapper.has-button-collapse.has-label{justify-content:space-between;gap:.5rem}.h5peditor .h5p-editor-flex-wrapper.has-button-collapse:not(.has-label){justify-content:flex-end}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse{align-items:center;background-color:#228380;background-image:none;border:3px solid #228380;border-radius:.4rem;box-sizing:border-box;display:grid;font-size:.815rem;font-weight:bold;grid-template-columns:auto 1fr;height:2.6rem;line-height:1.2rem;margin:0;padding:0 .6rem 0 .2rem}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse .label{white-space:nowrap}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse.collapsed .icon::before{content:"";font-family:"H5P";font-size:1.2rem;font-weight:normal;padding:0 .2rem 0 .2rem;vertical-align:middle}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse:not(.collapsed) .icon::before{content:"";font-family:"H5P";font-size:1.2rem;font-weight:normal;padding:0 .2rem 0 .2rem;vertical-align:middle}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse:hover:not([disabled]){background-color:#228380;background-image:none;border:3px solid #4dc2bf}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse.no-label{grid-template-columns:auto;padding:0 .2rem;width:auto}.h5peditor .h5p-editor-flex-wrapper .h5peditor-button-collapse.no-label .label{display:none}.h5peditor .h5peditor-label-wrapper{display:flex;flex-direction:row}.h5peditor .has-important-description .h5peditor-field-description{display:none}.h5peditor .has-important-description .h5peditor-label-wrapper{float:left}.h5peditor .important-description-visible .h5peditor-field-important-description{display:block}.h5peditor .important-description-visible .h5peditor-label-wrapper{float:none}.h5peditor .important-description-visible .important-description-show{display:none}.h5peditor textarea,.h5peditor .h5peditor-text,.h5peditor .ckeditor{box-shadow:inset 0px 0px 5px rgba(0,0,0,.12);box-sizing:border-box;margin:0;padding:10px;min-height:40px;border:1px solid #d0d0d1;background:#fff;outline:none;font-size:16px;word-wrap:break-word}.h5peditor textarea a,.h5peditor .h5peditor-text a,.h5peditor .ckeditor a{text-decoration:underline}.h5peditor textarea figure.table,.h5peditor .h5peditor-text figure.table,.h5peditor .ckeditor figure.table{display:table;table-layout:fixed;margin:0 auto;padding:0;float:left}.h5peditor textarea figure.table table,.h5peditor .h5peditor-text figure.table table,.h5peditor .ckeditor figure.table table{border-collapse:collapse;height:100%;width:100%;border-spacing:0;border-width:1px;border-color:#494949}.h5peditor textarea figure.table table td,.h5peditor textarea figure.table table th,.h5peditor .h5peditor-text figure.table table td,.h5peditor .h5peditor-text figure.table table th,.h5peditor .ckeditor figure.table table td,.h5peditor .ckeditor figure.table table th{padding:1px;border-color:#494949;border-bottom-style:solid}.h5peditor textarea figure.table table td,.h5peditor .h5peditor-text figure.table table td,.h5peditor .ckeditor figure.table table td{border-width:.083em}.h5peditor textarea figure.table table th,.h5peditor .h5peditor-text figure.table table th,.h5peditor .ckeditor figure.table table th{border-width:.167em}.h5peditor textarea figure.table table tr:last-child>td,.h5peditor .h5peditor-text figure.table table tr:last-child>td,.h5peditor .ckeditor figure.table table tr:last-child>td{border-bottom-style:none}.h5peditor textarea figure.table figcaption,.h5peditor .h5peditor-text figure.table figcaption,.h5peditor .ckeditor figure.table figcaption{background-color:rgba(0,0,0,0);caption-side:top;color:#333;display:table-caption;font-size:.75em;outline-offset:-1px;padding:.6em;text-align:center;word-break:break-word}.h5peditor textarea .table-overflow-protection,.h5peditor .h5peditor-text .table-overflow-protection,.h5peditor .ckeditor .table-overflow-protection{clear:both}.h5peditor textarea.error,.h5peditor .h5peditor-text.error,.h5peditor .ckeditor.error{border-color:red}.h5peditor .ck-content figure.table{float:left}.h5peditor .ck-content figure.table table{border-width:1px;border-color:#494949;border-style:none}.h5peditor .ck-content figure.table table td,.h5peditor .ck-content figure.table table th{padding:1px;border-style:none;border-color:#494949;border-bottom-style:solid}.h5peditor .ck-content figure.table table td{border-width:.083em}.h5peditor .ck-content figure.table table th{border-width:.167em;background-color:rgba(0,0,0,0)}.h5peditor .ck-content figure.table table tr:last-child>td{border-bottom-style:none}.h5peditor .ck-content figure.table figcaption{background-color:rgba(0,0,0,0)}.h5peditor .h5peditor-text,.h5peditor textarea{width:100%;box-sizing:border-box}.h5peditor .h5peditor-text.error,.h5peditor textarea.error{border-color:red}.h5peditor .ck a{text-decoration:underline}.h5peditor .ck .ck-font-size-dropdown .ck-dropdown__panel,.h5peditor .ck .ck-text-fragment-language-dropdown .ck-dropdown__panel{max-height:20em;overflow-y:scroll}.h5peditor .ck .ck-fontsize-option .ck-button__label{line-height:normal !important}.h5peditor .ck .ck-content pre{background:initial;border:initial;border-radius:initial;padding:0}.h5peditor textarea:focus::-webkit-input-placeholder,.h5peditor input:focus::-webkit-input-placeholder{color:#fff}.h5peditor textarea:focus:-moz-placeholder,.h5peditor input:focus:-moz-placeholder{color:#fff}.h5peditor textarea:focus::-moz-placeholder,.h5peditor input:focus::-moz-placeholder{color:#fff}.h5peditor textarea:focus:-ms-input-placeholder,.h5peditor input:focus:-ms-input-placeholder{color:#fff}.h5peditor textarea:focus.h5peditor-ckeditor-placeholder,.h5peditor input:focus.h5peditor-ckeditor-placeholder{color:#fff}.h5peditor ::-webkit-input-placeholder{color:#858585}.h5peditor :-moz-placeholder{color:#858585}.h5peditor ::-moz-placeholder{color:#858585}.h5peditor :-ms-input-placeholder{color:#858585}.h5peditor .h5peditor-ckeditor-placeholder{color:#858585}.h5peditor>select,.h5peditor .h5peditor-language-switcher select,.h5peditor h5peditor-select,.h5peditor .field>select{padding:10px 30px 10px 8px;font-family:"Open Sans",sans-serif;font-size:16px;border:1px solid #d0d0d1;background:#fff url(a1aff8c82bc779d09357.png) no-repeat;background-position:calc(100% - 10px);box-shadow:inset 0px 0px 5px rgba(0,0,0,.12);-moz-appearance:none;-webkit-appearance:none}.h5peditor>select:disabled,.h5peditor .h5peditor-language-switcher select:disabled,.h5peditor h5peditor-select:disabled,.h5peditor .field>select:disabled{background-color:#efefef}.h5peditor>select{margin-bottom:13px;margin-right:20px}.h5peditor select::-ms-expand{display:none}.h5peditor a:focus{outline:none}.h5peditor textarea:focus,.h5peditor .h5peditor-text:focus{outline:none;background-color:#fff;border-color:#53a0ff}.h5peditor .h5p-ul{padding:0;margin:0;list-style:none}.h5peditor .h5p-ul .h5p-li{margin:10px 0;padding:0;list-style:none}.h5peditor .h5p-ul .h5p-li:first-child{margin-top:0}.h5peditor .h5p-ul .h5p-li:last-child{margin-bottom:0}.h5peditor .h5p-ul .h5p-li.placeholder{box-sizing:border-box;background:#e8f2fa;border:dashed 2px #2782d1}.h5peditor .h5p-ul .h5p-li:hover{text-decoration:none}.h5peditor .h5p-ul .h5p-li:nth-child(2).moving{margin-top:0}.h5peditor .h5p-ul .h5p-li:nth-last-child(2).placeholder{margin-bottom:0}.h5peditor .dimensions input,.h5peditor .coordinates input,.h5peditor .number input{width:75px}.h5peditor .number input[type=range]{width:300px;float:left;margin:7px 8px 0 0}.h5peditor .h5p-errors{clear:both}.h5peditor .h5p-add-file{float:left;position:relative;background:rgba(0,0,0,0);border:2px dashed #ddd;color:#ddd;margin:.5em;width:6em;height:4.5em;cursor:pointer;outline:none;box-sizing:border-box;-moz-box-sizing:border-box}.h5peditor .h5p-add-file:focus,.h5peditor .h5p-add-file:hover{color:#999;border-color:#999}.h5peditor .h5p-add-file.hidden{visibility:hidden}.h5peditor .h5p-add-file:after{position:absolute;content:"+";font-size:2em;line-height:2.2em;width:100%;height:100%;text-align:center}.h5peditor .h5p-add-dialog{position:absolute;z-index:1;visibility:hidden;opacity:0;background:#fff;left:1em;right:1em;top:1em;border:1px solid #cdcdcd;box-sizing:border-box;-moz-box-sizing:border-box;box-shadow:0 0 8px #666;transition:visibility 0s .2s,opacity .2s}.h5peditor .h5p-add-dialog.h5p-open{visibility:visible;opacity:1;transition:visibility 0s 0s,opacity .2s}.h5peditor .h5p-add-dialog .h5p-add-dialog-table{overflow:hidden}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tablist{overflow:hidden;margin:1em 1em 0 1em}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tab{cursor:pointer;float:left;padding:.5em .75em;border-top:1px solid #ccc;border-right:1px solid #ccc;font-weight:bold;font-size:15px;color:#666;background:#f5f5f5}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tab:first-child{border-left:1px solid #ccc}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tab.selected{color:#333;background:#fff}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tabpanel{border:1px solid #ccc;margin:0 1em 1em 1em;overflow:hidden;padding:1em}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tabpanel h3{margin:0 0 1em 0}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .av-tabpanel .h5p-file-drop-upload{width:90px;margin:0}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-dialog-box{float:left;padding:0;width:60%;margin-right:5%;margin-left:4%;text-align:left;margin-top:30px}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-dialog-box:first-child{width:22%;margin-left:3%;margin-right:1%}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-dialog-box:first-child h3{text-align:center}.h5peditor .h5p-add-dialog .h5p-add-dialog-table h3{color:#666;font-size:1em;margin:1.2em 0;line-height:1.1em}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5peditor-field-description{color:#bbb}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-url-wrapper{background-color:#f5f5f5;border:1px solid #bbb;padding:15px 15px 15px 60px;position:relative}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-url-wrapper:before{font-family:"H5P";position:absolute;left:0;top:.083em;font-size:3.8em;line-height:1}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-url-wrapper.video:before{content:"";color:#dd0505}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-url-wrapper.audio:before{content:"";color:#747275}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-url-wrapper input{border-color:#bbb;text-align:left;padding-left:20px}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload{position:relative;width:70%;height:90px;margin:0 15%;float:left;background-color:#f5f5f5;text-align:center;cursor:pointer;border:1px solid #bbb}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload .h5p-file-drop-upload-inner{border:2px dashed #bbb;background-color:#fff;position:absolute;top:3px;bottom:3px;left:3px;right:3px}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload .h5p-file-drop-upload-inner:after{font-family:"H5P";line-height:1.4em;font-size:3.5em;color:#bbb}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload .h5p-file-drop-upload-inner.video:after{content:""}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload .h5p-file-drop-upload-inner.audio:after{content:""}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload:hover .h5p-file-drop-upload-inner:after,.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-file-drop-upload.over .h5p-file-drop-upload-inner:after{color:#999}.h5peditor .h5p-add-dialog .h5p-add-dialog-table .h5p-or-vertical{float:left;position:relative;width:5%;height:250px}.h5peditor .h5p-add-dialog .h5p-dialog-box{text-align:center;padding:1em .5em}.h5peditor .h5p-add-dialog .h5p-buttons{padding:.5em;border-top:1px solid #cdcdcd;background:#ddd;text-align:right}.h5peditor .h5p-or{border-bottom:1px solid #cdcdcd;padding:0;margin:0 1em;text-align:center;height:.5em;line-height:1em}.h5peditor .h5p-or>span{background:#fff;padding:0 .5em}.h5peditor .h5p-or-vertical{float:left;position:relative;width:50px;height:80px}.h5peditor .h5p-or-vertical .h5p-or-vertical-line{position:absolute;margin:10px 0;left:49%;top:0;bottom:0;width:1px;background:#ccc;z-index:1}.h5peditor .h5p-or-vertical .h5p-or-vertical-word-wrapper{text-align:center;height:18px;position:absolute;left:0;right:0;top:22%;margin-top:-12px;z-index:2}.h5peditor .h5p-or-vertical .h5p-or-vertical-word-wrapper .h5p-or-vertical-word{color:#999;font-weight:bold;font-size:18px;padding:3px;background:#fff}.h5peditor .h5p-file-url{text-align:center}.h5peditor .h5p-thumbnail{margin:.5em;width:6em;height:4.5em;display:block;float:left;position:relative;box-shadow:0 0 10px 0 #666;border:1px solid #fff;box-sizing:border-box;-moz-box-sizing:border-box}.h5peditor .h5p-thumbnail .h5p-remove{position:absolute;top:0;right:0;cursor:pointer;outline:none;width:1.6em;height:1.6em;line-height:1.6em;overflow:hidden;text-indent:-0.4em;padding:.065em;opacity:.6}.h5peditor .h5p-thumbnail .h5p-remove:hover,.h5peditor .h5p-thumbnail .h5p-remove:focus{opacity:1}.h5peditor .h5p-thumbnail .h5p-remove:after{font-family:"H5P";font-size:2em;color:#fff;content:"";opacity:.6}.h5peditor .h5p-type{position:absolute;width:100%;height:100%;font-size:1.1em;line-height:4em;display:block;text-align:center;background:#000;color:#fff;cursor:pointer}.h5peditor .file{position:relative;float:left;margin-bottom:0;max-width:100%}.h5peditor .file.authorList{float:none}.h5peditor .file.field{float:none}.h5peditor .file .thumbnail{display:inline-block;margin:10px 10px 10px 0;box-shadow:0 0 10px 0 #666;border:1px solid #fff;cursor:pointer;max-width:100%;min-width:1em;min-height:1em;background:#fff url(ae8568c2320881fd5899.png) repeat}.h5peditor .file .thumbnail:focus{box-shadow:0 0 10px 0 #222}.h5peditor .file .add{display:inline-block;cursor:pointer;padding:.5em 1.5em .5em 3em;background:linear-gradient(to bottom, #fbfbfb 0, #f2f2f2 100%);border:1px solid #d0d0d1;border-radius:.25em;color:#222;font-weight:bold;line-height:normal}.h5peditor .file .add:hover{background:#ededed}.h5peditor .file .add:focus{box-shadow:0 0 16px 0 rgba(133,188,255,.84)}.h5peditor .file .add .h5peditor-field-file-upload-text:before{font-family:"H5P";content:"";line-height:1;color:#39c943;font-size:2em;position:absolute;left:.3em;top:.1em}.h5peditor .file .remove{display:block;position:absolute;top:7px;right:7px;cursor:pointer}.h5peditor .file .remove:focus:before{opacity:1}.h5peditor .file .remove:before{font-family:"H5P";font-size:1.4em;color:#fff;content:"";opacity:.6;text-shadow:rgba(0,0,0,.4) 0 0 4px,rgba(0,0,0,.4) 0 0 4px,rgba(0,0,0,.4) 0 0 4px}.h5peditor .file .remove:hover{text-decoration:none}.h5peditor .file .remove:hover:before{color:#fff;opacity:1;text-shadow:rgba(0,0,0,.4) 0 0 4px,rgba(0,0,0,.4) 0 0 4px,rgba(0,0,0,.4) 0 0 4px}.h5peditor .file img{max-width:100%;vertical-align:bottom;max-height:100px}.h5peditor .file .h5p-av-row{overflow:auto;margin-bottom:.5em}.h5peditor .file .h5p-av-row .h5p-thumbnail{display:table-cell}.h5peditor .file .h5p-av-row .h5p-video-quality{display:table-cell;overflow:hidden;width:10000px;padding-left:1em}.h5peditor .file .h5p-av-row .h5p-video-quality input.h5peditor-text{width:100%}.h5peditor .file .h5p-av-cell{overflow:auto;float:left}.h5peditor .video .file,.h5peditor .audio .file{position:static;overflow:visible}.h5peditor .video .file .thumbnail,.h5peditor .video .file .add,.h5peditor .audio .file .thumbnail,.h5peditor .audio .file .add{float:left}.h5peditor .video .file .add,.h5peditor .audio .file .add{margin-top:8px}.h5peditor .video .file .thumbnail,.h5peditor .audio .file .thumbnail{overflow:visible;position:relative;cursor:auto}.h5peditor .video .file .remove,.h5peditor .audio .file .remove{top:-3px;right:-5px}.h5peditor .video .file .type,.h5peditor .audio .file .type{padding:16px 8px 4px;background:#000;color:#fff;font-size:10px}.h5peditor .video .file .h5peditor-uploading,.h5peditor .audio .file .h5peditor-uploading{float:left;margin:.5em}.h5peditor .libwrap{margin-top:20px}.h5peditor .libwrap.no-margin,.h5peditor .libwrap:empty{margin-top:0}.h5peditor input[type=checkbox]{margin:4px 4px 4px 0;vertical-align:bottom}.h5peditor .moving{position:absolute;z-index:1;opacity:.8;-webkit-transform:translateZ(0)}.h5peditor .moving .h5peditor-label{cursor:grabbing;cursor:-moz-grabbing;cursor:-webkit-grabbing}.h5peditor .h5peditor-uploading,.h5peditor .h5peditor-loading{padding-top:10px;padding-bottom:6px;font-size:14px}.h5peditor .h5peditor-loading{padding:.875em 0 1em 3.25em;font-style:italic}.h5peditor .h5p-copyright-button{border-radius:.25em;height:30px;background:linear-gradient(to bottom, #fff 0, #f2f2f2 100%);border:1px solid #d0d0d1;color:#212121;font-size:14px;line-height:28px;padding-right:20px;padding-left:0;clear:both;font-weight:normal}.h5peditor .h5p-copyright-button:before{font-family:"H5P";content:"";color:#666;padding:0 .25em 0 .25em;vertical-align:middle;font-size:1.5em;line-height:.9}.h5peditor .h5p-copyright-button:hover:not([disabled]){background:linear-gradient(to bottom, #fff 0, #d0d0d1 100%);text-decoration:none;border-color:#999}.h5peditor .h5p-copyright-button:focus{box-shadow:0 0 16px 0 rgba(133,188,255,.84)}.h5peditor .field.file>.h5p-copyright-button,.h5peditor .field.video>.h5p-copyright-button,.h5peditor .field.audio>.h5p-copyright-button{float:left}.h5peditor .h5p-editor-dialog{position:absolute;z-index:2;margin:5.5em 0 1em;visibility:hidden;opacity:0;height:0;overflow:hidden;background:#fff;box-shadow:0 0 8px #666;transition:visibility 0s .2s,height 0s .2s,opacity .2s,margin-top .2s}.h5peditor .h5p-editor-dialog.h5p-open{margin-top:3.5em;visibility:visible;opacity:1;height:auto;transition:visibility 0s 0s,height 0s 0s,opacity .2s,margin-top .2s}.h5peditor .h5p-editor-dialog>.field{margin:0;border:0;box-shadow:none}.h5peditor .h5p-editor-dialog .content{border:none;background:#fff}.h5peditor .h5p-editor-dialog .content .h5peditor-label{font-size:18px;font-weight:600}.h5peditor .h5p-editor-dialog .h5p-close{color:#494949}.h5peditor .h5p-editor-dialog .h5p-close:before{font-size:2em;right:-0.125em;top:0;position:absolute;z-index:1;font-family:"H5P";content:"";line-height:1em;transition:scale .2s}.h5peditor .h5p-editor-dialog .h5p-close:hover:before{scale:1.1,1.1}.h5peditor .h5p-li>.content>.library{border:0;padding:0}.ck-powered-by-balloon{display:none !important}.h5p-editor-dialog.h5p-dialog-wide{width:90%;border-radius:.208em}.h5peditor-button-textual{border-radius:.25em;background:#747275;background-image:linear-gradient(#7b797c 50%, transparent 50%, transparent);display:inline-block;width:auto;margin:10px 0 0 0;padding:0 20px;box-sizing:border-box;height:38px;border:1px solid #d0d0d1;font-size:16px;font-family:"Open Sans",sans-serif;line-height:38px;color:#fff;cursor:pointer;font-weight:600;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.h5peditor-button-textual:focus{box-shadow:0 0 16px 0 rgba(133,188,255,.84)}.h5peditor-button-textual:before,.h5peditor-button-textual:after{color:#fff}.h5peditor-button-textual .h5p-editing-image-button:before{font-family:"H5P";content:"";color:#666;padding-right:.25em;vertical-align:middle;font-size:1.5em;line-height:.9}.h5peditor-button-textual:hover:not([disabled]){background:#636164;background-image:linear-gradient(#6b696c 50%, transparent 50%, transparent);text-decoration:none}.h5peditor-button-textual.importance-high{background:#2579c6;background-image:linear-gradient(#3080c9 50%, transparent 50%, transparent);border-color:#1f67a8;text-transform:uppercase;height:42px;line-height:42px}.h5peditor-button-textual.importance-high:hover:not([disabled]){background:#1f67a8;background-image:linear-gradient(#2a6fac 50%, transparent 50%, transparent);border-color:#1f67a8}.h5peditor-button-textual.importance-low{background:#f5f5f5;background-image:linear-gradient(#eeeeef 50%, transparent 50%, transparent);border-color:#d0d0d1;color:#212121}.h5peditor-button-textual.importance-low:before,.h5peditor-button-textual.importance-low:after{color:#212121}.h5peditor-button-textual.importance-low:hover:not([disabled]){background:#deddde;background-image:linear-gradient(#deddde 50%, transparent 50%, transparent);border-color:#deddde}.h5peditor-button-textual[disabled],.h5peditor-button-textual[aria-disabled=true]{background:#f5f5f5;color:#707171;border-color:#eee;cursor:not-allowed}.h5peditor-button-textual[disabled]:before,.h5peditor-button-textual[aria-disabled=true]:before{font-family:"H5P";content:"";color:#707171;margin-right:.5em;vertical-align:top}.h5peditor-field-description,.h5p-help-text{font-size:12px;margin-top:.3em;margin-bottom:1em;font-weight:500;color:#434446;line-height:15px;letter-spacing:.5px}.h5peditor-field-important-description{position:relative;padding:1.5em 2.2em 2em 2.2em;font-size:.9em;margin:0 0 20px 0;border:1px solid #ffde78;background-color:#f9f9d8;color:#000;display:none}.h5peditor-field-important-description .important-description-close{position:absolute;font-size:.9em;line-height:2em;right:1.5em;top:1em;user-select:none;cursor:pointer}.h5peditor-field-important-description .important-description-close:before{font-family:"H5P";content:"";vertical-align:top;font-size:1.6em}.h5peditor-field-important-description .h5p-info-icon{font-size:.75em}.h5peditor-field-important-description .h5p-info-icon:before{font-family:"H5P";content:"";font-size:2.3em;line-height:.94em;margin-left:-0.3em;vertical-align:middle}.h5peditor-field-important-description .important-description-title{font-weight:bold;font-size:1.2em;vertical-align:bottom}.h5peditor-field-important-description .important-description-content ul{padding:0;line-height:2em;margin-top:20px}.h5peditor-field-important-description .important-description-content ul li{line-height:1.8em;margin-left:1.5em}.h5peditor-field-important-description .important-description-example{border:1px solid #bbde98;background-color:#d9fac3;display:flex;margin-top:20px}.h5peditor-field-important-description .important-description-example .important-description-example-title{padding:15px;font-weight:bold}.h5peditor-field-important-description .important-description-example .important-description-example-text{padding:15px;width:100%;background-color:#f6fef1}.h5peditor-form{position:relative;background:#fcfcfc;border:1px solid #d0d0d1}.h5peditor-form.h5peditor-form-manager>.tree,.h5peditor-form.h5peditor-form-manager>.common,.h5peditor-form.h5peditor-form-manager>.field{max-width:918px;margin:20px auto;padding:0 20px}.h5peditor-form.h5peditor-semi-fullscreen{margin:0;position:fixed;overflow-y:scroll;margin-top:40px;padding-bottom:40px;box-sizing:border-box;background:#fff;height:calc(100% - 40px)}.h5peditor-label{display:block;margin-bottom:6px;font-weight:600;font-size:16px;color:#454347}.h5peditor-label-button{background:rgba(0,0,0,0);border:none;color:#454347;cursor:pointer;display:flex;flex-direction:row;font-family:inherit;font-weight:600;font-size:16px;padding:0 0 0 10px;text-align:left}.h5peditor-label-button.collapsed .icon::before{content:"";font-family:"H5P";margin-right:5px}.h5peditor-label-button:not(.collapsed) .icon::before{content:"";font-family:"H5P";margin-right:5px}#h5peditor-uploader{position:absolute;width:1px;height:1px;top:-1px;border:0;overflow:hidden}.h5p-tutorial-url,.h5p-example-url{font-size:1em;display:inline-flex;align-items:center;line-height:1;margin-right:1em;margin-bottom:.5em;margin-left:.25em;height:2rem;border-radius:1rem}.h5p-tutorial-url:focus,.h5p-example-url:focus{box-shadow:0px 0px 5px #1634f7}.h5p-tutorial-url:active,.h5p-example-url:active{border-color:#1c70ba}.h5p-tutorial-url::before,.h5p-example-url::before{font-family:"H5P";font-size:1.25em;border-radius:50%;width:2rem;height:2rem;position:absolute;display:flex;justify-content:center;align-items:center}.h5p-tutorial-url .h5p-tutorial-url-label,.h5p-tutorial-url .h5p-example-url-label,.h5p-example-url .h5p-tutorial-url-label,.h5p-example-url .h5p-example-url-label{font-style:italic;font-weight:bold;text-decoration:underline;margin:.25em .5em;margin-left:2rem;padding-left:.5em;padding-right:1em}.h5p-tutorial-url:active,.h5p-tutorial-url:hover{background-color:#eaffab}.h5p-tutorial-url::before{content:"";color:#eaffab;background-color:#749e00}.h5p-tutorial-url .h5p-tutorial-url-label{color:#415702}.h5p-example-url:active,.h5p-example-url:hover{background-color:#f8d4ff}.h5p-example-url::before{content:"";font-size:1em;color:#f8d4ff;background-color:#8f4f9c}.h5p-example-url .h5p-example-url-label{color:#422447}.h5peditor-widget-select{display:flex;flex-direction:row-reverse;justify-content:end;overflow:hidden;margin:0 0 -1px;padding:0;list-style:none}.h5peditor-widget-option{border:1px solid #ccc;margin-left:.5em;padding:.6em 1em;color:#0e1a25;font-size:.875em;background:#f5f5f5;line-height:1.285714286em;cursor:pointer;outline:none}.h5peditor-widget-option:hover{color:#000}.h5peditor-widget-option:active{color:#8e636a}.h5peditor-widget-active{background:#fff;line-height:1.357142857em;border-bottom:0}.h5peditor-widgets>.h5peditor-widget-wrapper{border:1px solid #ccc;margin:0 0 .25em;padding:.5em}.h5peditor-widgets>.h5peditor-label,.h5peditor-widgets>.h5peditor-label-button{float:left;margin-top:5px}.h5p-editor-iframe{margin-bottom:1em}.h5peditor-required:after{content:"*";color:#da0001;margin-left:.2em;position:relative;top:-0.2em}.h5peditor .cke_bottom,.h5peditor .cke_top{background:#d0d0d1}.h5peditor .cke_chrome{border:1px solid #f5f5f5;background:#d0d0d1}.h5peditor .cke_contents,.h5peditor .cke_toolgroup,.h5peditor .cke_combo_button{border:1px solid #f5f5f5}.important-description-show{background:#f3d55a;padding:.2em .5em .2em 1.7em;margin-bottom:.5em;font-size:.9em;cursor:pointer;float:right;position:relative;line-height:normal;font-style:italic;font-weight:bold}.important-description-show:before{font-family:"H5P";font-style:normal;font-weight:normal;content:"";font-size:1.8em;position:absolute;left:0em;top:0em;line-height:.85em;vertical-align:top}.important-description-clear-right{display:block;clear:right}.h5peditor fieldset.common-fields-library-wrapper{width:100%;padding:0 1em 1em;box-sizing:border-box;height:20px;border:solid 1px #e2e5ee;border-radius:4px;margin-bottom:1em}.h5peditor fieldset.common-fields-library-wrapper>*{display:none}.h5peditor fieldset.common-fields-library-wrapper>legend{display:block;cursor:pointer;outline:none;color:#363b42;background-color:#fff;padding:10px;font-weight:bold;font-size:.875em}.h5peditor fieldset.common-fields-library-wrapper>legend:before{font-family:"H5P";content:"";margin-right:.5em}.h5peditor fieldset.common-fields-library-wrapper>legend:focus:before{outline:1px dotted #666}.h5peditor fieldset.common-fields-library-wrapper.expanded{height:auto}.h5peditor fieldset.common-fields-library-wrapper.expanded>*{display:block}.h5peditor fieldset.common-fields-library-wrapper.expanded>legend:before{content:""}.h5p-metadata-button-wrapper{display:flex;flex-direction:row;align-items:center;margin-top:-7px;margin-left:7px;cursor:pointer}.h5p-metadata-button-wrapper.inline-with-selector{display:inline-flex;margin-left:17px}.h5p-metadata-toggler{margin-left:-11px;height:14.5px;max-height:14.5px;padding:.217rem .3rem .217rem .217rem;font-size:.625em;font-weight:bold;letter-spacing:.025em;border:1px solid #b6cada;border-left:none;border-radius:4px;background:linear-gradient(#fff, #deeaf1);color:#356593;z-index:1;justify-content:center;align-content:center;line-height:1.5em}.h5p-metadata-button-tip{width:16.5px;height:16.5px;content:"";background:linear-gradient(-215deg, #fff, #deeaf1);border:1px solid #b6cada;border-right:none;border-top:none;border-radius:4px;transform:rotate(45deg);z-index:0}.h5p-metadata-button-wrapper:hover .h5p-metadata-toggler,.h5p-metadata-button-wrapper:hover .h5p-metadata-button-tip{border-color:#6d9fce}.h5p-metadata-button-wrapper:hover .h5p-metadata-toggler{background:linear-gradient(#f3f8fb, #cee5f3)}.h5p-metadata-button-wrapper:hover .h5p-metadata-button-tip{background:linear-gradient(-215deg, #f3f8fb, #cee5f3)}.h5p-metadata-button-wrapper:active .h5p-metadata-toggler,.h5p-metadata-button-wrapper:active .h5p-metadata-button-tip{color:#294f73;border-color:#6d9fce}.h5p-metadata-button-wrapper:active .h5p-metadata-toggler{background:linear-gradient(#f3f8fb, #bcd4e2)}.h5p-metadata-button-wrapper:active .h5p-metadata-button-tip{background:linear-gradient(-215deg, #f3f8fb, #bcd4e2)}#metadata-title-main-label{margin-top:0}.h5p-metadata-button{background:#fff;padding:10px;text-align:center;border-radius:5px;border:2px solid #6b6b6b;color:#6b6b6b;font-weight:bold;display:inline;cursor:pointer}.h5p-metadata-button:hover{border-color:#4a4a4a;color:#4a4a4a}.h5p-metadata-button:active{border-color:#000;color:#000}.h5p-metadata-button.inverted{border:2px solid #0a715e;color:#0a715e}.h5p-metadata-button.inverted:hover{border-color:#0d826c;color:#0d826c}.h5p-metadata-button.inverted:active{border-color:#095345;color:#095345}.h5p-metadata-icon-button{border:none;cursor:pointer;color:#6b6b6b;background:rgba(0,0,0,0);padding:0}.h5p-metadata-icon-button:hover{color:#4a4a4a}.h5p-metadata-icon-button:active{color:#000}.h5p-metadata-wrapper{display:inline-block;background-color:#fff;max-width:700px;width:calc(100% - 4em);text-align:left;border-bottom:20px solid rgba(0,0,0,0);background-clip:padding-box;max-height:calc(100% - 40px);overflow:auto;margin-bottom:20px}.h5p-metadata-wrapper .h5p-metadata-header{display:flex;border-bottom:1px solid #ced6e3;padding:1.5em}.h5p-metadata-wrapper .h5p-metadata-header .h5p-title-container{flex-grow:1;padding-left:3.5em;white-space:nowrap;overflow:hidden;margin-right:1%;position:relative}.h5p-metadata-wrapper .h5p-metadata-header .h5p-title-container h2{margin:0}.h5p-metadata-wrapper .h5p-metadata-header .h5p-title-container p{margin:.1em}.h5p-metadata-wrapper .h5p-metadata-header .h5p-title-container:before{position:absolute;font-family:"h5p-metadata-icons";content:"";left:0;top:0;font-size:2em;height:1.4em;line-height:1.3}.h5p-metadata-wrapper .h5p-save{border:solid 2px #0a715e;border-radius:.3rem;color:#fff;background-color:#0a715e;padding:.75rem;white-space:nowrap}.h5p-metadata-wrapper .h5p-save:hover{border-color:#0d826c;background-color:#0d826c}.h5p-metadata-wrapper .h5p-save:active{border-color:#095345;background-color:#095345}.h5p-metadata-wrapper .h5peditor-label{font-size:.8em;color:#333}.h5p-metadata-wrapper .h5peditor-field-description{color:#697484;margin-top:.35em;letter-spacing:.5px}.h5p-metadata-wrapper .copyright-form{margin-top:20px}.h5p-metadata-wrapper h2{font-size:1em;overflow:hidden;text-overflow:ellipsis}.h5p-metadata-wrapper p{font-size:.8333em;color:#697484;overflow:hidden;text-overflow:ellipsis;margin-bottom:0}.h5p-metadata-wrapper .errors p,.h5p-metadata-wrapper .h5p-errors p{color:#da0001;font-size:1em;white-space:normal;text-overflow:unset}.h5p-metadata-wrapper select.h5peditor-select,.h5p-metadata-wrapper input.h5peditor-text,.h5p-metadata-wrapper textarea{border:1px solid #b8c0cd;font-size:.833em;border-radius:.208em;box-shadow:none;font-family:"Open Sans",sans-serif}.h5p-metadata-wrapper select:focus,.h5p-metadata-wrapper input:focus,.h5p-metadata-wrapper textarea:focus{box-shadow:inset 0px 0px 10px rgba(0,0,0,.15)}.h5p-metadata-wrapper select{width:100%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper{display:flex;flex-wrap:wrap;margin:1.5em}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field{margin-bottom:0;width:100%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-license{width:49%;margin-right:1%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-licenseVersion{width:49%;margin-left:1%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-yearFrom{width:24%;margin-right:1%;white-space:nowrap}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-yearFrom .h5peditor-text{width:100%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-yearTo{width:23%;margin-right:1%;margin-left:1%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-yearTo .h5peditor-text{width:100%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper>.field-name-source{width:49%;margin-left:1%}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label{justify-content:space-between}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label .a11y-title-toggle{background:none;border:none;cursor:pointer}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label .a11y-title-toggle:before{font-family:"h5p-metadata-icons";content:"";margin-right:.5em;font-size:1.5em;vertical-align:middle}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label .a11y-title-toggle:focus,.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label .a11y-title-toggle:active,.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label .a11y-title-toggle:hover{border:none}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-title label .a11y-title-toggle:hover .h5p-a11y-title-text{text-decoration:underline}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-a11yTitle{transition:max-height .2s,margin .2s;overflow:hidden}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-a11yTitle.hide{max-height:0;margin:0}.h5p-metadata-wrapper .h5p-metadata-fields-wrapper .field-name-a11yTitle.hidden{display:none}.h5p-metadata-wrapper .field.group>.title{font-weight:400;background:#f6f6f6;color:#323232;border:solid 1px #ced6e3;border-radius:.208em}.h5p-metadata-wrapper .field.group.expanded>.title{border-radius:.208em .208em 0 0}.h5p-metadata-wrapper .field.group>.title:focus{border-color:#4d90fe}.h5p-metadata-wrapper .field.group>.content{border:solid 1px #ced6e3;border-radius:0 0 .208em .208em;padding:20px;border-top:0}.h5p-metadata-additional-information{width:100%;margin-top:1em}.h5p-metadata-additional-information .content.h5peditor-single{min-height:2em;border:1px solid #d0d0d1;border-top:none;background:#fff}.h5p-metadata-additional-information .title{font-weight:400;background:#f6f6f6;color:#323232;border:solid 1px #ced6e3;border-radius:.208em}.h5p-metadata-additional-information .title:focus{border-color:#4d90fe}.h5p-metadata-popup-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,.85);z-index:101;text-align:center}.h5p-metadata-changelog{width:100%}.h5p-metadata-changelog .field-name-change.expanded .content{display:flex;flex-wrap:wrap}.h5p-metadata-changelog .field-name-change .field-name-date{width:49%;margin-bottom:.5em;margin-right:1%;margin-top:0}.h5p-metadata-changelog .field-name-change .field-name-date span{width:100%}.h5p-metadata-changelog .field-name-change .field-name-author{width:49%;margin-bottom:.5em;margin-left:1%;margin-top:0}.h5p-metadata-changelog .field-name-change .field-name-log{width:100%}.h5p-metadata-changelog .field-name-change .h5p-add-author:before{content:"+";margin-right:.7em}.h5p-metadata-changelog .field-name-change .h5p-cancel{margin-right:10px}.h5p-metadata-changelog .field-name-change .h5p-metadata-changelog-buttons{width:100%}.h5p-metadata-changelog .field-name-change .h5p-metadata-logged-changes{width:100%;margin-top:1em}.h5p-metadata-changelog .field-name-change .h5p-metadata-logged-changes.editing{display:none}.h5p-metadata-changelog .field-name-change .h5p-metadata-logged-changes .h5peditor-field-description{margin-bottom:0}.h5p-metadata-changelog .field-name-change .h5p-metadata-log-wrapper{margin-top:1em;border:solid 1px #ced6e3;border-radius:.208em;max-height:15.917rem;overflow-y:auto;padding:0 .5em}.h5p-metadata-changelog .field-name-change .h5p-metadata-log{display:flex;margin-top:.5em;padding-bottom:.5em}.h5p-metadata-changelog .field-name-change .h5p-metadata-log .h5p-metadata-delete{margin-left:2em}.h5p-metadata-changelog .field-name-change .h5p-metadata-log .h5p-metadata-delete:after{font-family:"h5p-metadata-icons";content:"";font-size:1.2em}.h5p-metadata-changelog .field-name-change .h5p-metadata-log .h5p-metadata-edit:after{font-family:"h5p-metadata-icons";content:"";font-size:1.2em}.h5p-metadata-changelog .field-name-change .h5p-metadata-log-buttons{min-width:3em;line-height:2.5}.h5p-metadata-changelog .field-name-change .h5p-metadata-log:not(:last-child){border-bottom:solid 1px #ced6e3}.h5p-metadata-changelog .field-name-change .h5p-metadata-log-date{min-width:25%;font-size:.85em;font-style:italic;line-height:2.5}.h5p-metadata-changelog .field-name-change .h5p-metadata-description-wrapper{flex-grow:1;font-size:.85em;font-style:italic}.h5p-metadata-changelog .field-name-change .h5p-metadata-description-wrapper{font-weight:bolder}.h5p-metadata-changelog .field-name-change .h5p-metadata-log-author{font-weight:normal}.h5p-metadata-changelog .field-name-change .h5p-metadata-new-log-message{width:100%;background:#c5e7e1;padding:.5em;margin-bottom:1em;color:#0a715e}.h5p-metadata-author-widget{display:flex;flex-direction:column;border:solid 1px #ced6e3;border-radius:.208em;width:100%;padding:1em;margin-top:1em}.h5p-metadata-author-widget .h5p-save-author{border:solid 2px #0a715e;color:#fff;background-color:#0a715e}.h5p-metadata-author-widget .h5p-save-author:hover{border-color:#0d826c;color:#fff;background-color:#0d826c}.h5p-metadata-author-widget .h5p-save-author:active{border-color:#095345;color:#fff;background-color:#095345}.h5p-metadata-author-widget .h5p-author-data{display:flex;flex-direction:row;flex-wrap:nowrap}.h5p-metadata-author-widget .h5p-author-data>.field{margin-bottom:0}.h5p-metadata-author-widget .field-name-name{flex-grow:1;margin-right:2%;overflow:hidden;white-space:nowrap;min-width:49%}.h5p-metadata-author-widget .field-name-role{margin-top:0;margin-right:2%;width:25%;flex-grow:1;overflow:hidden;white-space:nowrap}.h5p-metadata-author-widget .authorList{margin-top:1.5em;white-space:nowrap}.h5p-metadata-author-widget .authorList li{display:inline;margin-right:.5em}.h5p-metadata-author-widget .authorList li span{margin-right:1em;font-style:italic}.h5p-metadata-author-widget .h5p-author-list-wrapper{margin-top:.5em}.h5p-metadata-author-widget .h5p-author-list-wrapper ul{margin:0;padding:0}.h5p-metadata-author-widget .h5p-author-list-wrapper li{display:inline-block;margin-right:2em;list-style:none;font-weight:bold;font-size:.8em}.h5p-metadata-author-widget .h5p-author-list-wrapper .h5p-metadata-role{font-style:italic;margin:0 .6em;font-weight:normal;font-size:.85em;color:#757575}.h5p-metadata-author-widget .h5p-author-list-wrapper button:after{font-family:"h5p-metadata-icons";content:"";font-size:1em;position:relative;top:-0.1em}.h5peditor-copypaste-wrap{float:right}.h5peditor>.h5peditor-copypaste-wrap{margin-bottom:14px}.h5peditor-copypaste-wrap.hidden{display:none}.h5peditor-clearfix{clear:both}.h5peditor-paste-button,.h5peditor-copy-button{border:1px solid #deeeec;padding:.5em .75em .75em .5em;margin-left:.5em;border-radius:.25em;cursor:pointer;background:#f2faff;line-height:.5em}.h5peditor-paste-button:hover,.h5peditor-copy-button:hover{border-color:#bbdae8}.h5peditor-paste-button:active,.h5peditor-copy-button:active{background-color:#deeffb}.h5peditor-paste-button.disabled,.h5peditor-copy-button.disabled{color:#707070;background-color:#f5f5f5;border-color:#ededed;cursor:not-allowed}.h5peditor-copy-button:before,.h5peditor-paste-button:before{font-family:"H5P";margin-right:5px;font-size:1.5em;position:relative;top:.2em;color:#2372b3}.h5peditor-copy-button:before{content:""}.h5peditor-paste-button:before{content:""}.h5peditor-copy-button.disabled:before,.h5peditor-paste-button.disabled:before{color:#707070}.h5peditor-copy-button.disabled:before{content:""}.h5peditor-paste-button.disabled:before{content:""}.h5p-hub .h5peditor-paste-button{font-family:"Open Sans",sans-serif;color:#fff;border:solid 1px #9fc8f4;padding:0 .75em .5em .75em;background:rgba(0,0,0,0);line-height:1;height:auto;margin-top:.675em;margin-right:.675em}.h5p-hub .h5peditor-paste-button:hover{background:#4b5460;border-color:#606a78}.h5p-hub .h5peditor-paste-button:active{background:#434b55}.h5p-hub .h5peditor-paste-button.disabled{border-color:#30353d;background:#30353d;color:#c2c2c2}.h5p-hub .h5peditor-paste-button:before{color:#9fc8f4}.h5p-hub .h5peditor-paste-button.disabled:before{color:#c3c3c3}@font-face{font-family:"h5p-fullscreen-bar";src:url(./fonts/h5p-fullscreen-bar.eot);src:url(./fonts/h5p-fullscreen-bar.eot#iefix) format("embedded-opentype"),url(./fonts/h5p-fullscreen-bar.ttf) format("truetype"),url(./fonts/h5p-fullscreen-bar.woff) format("woff"),url(./fonts/h5p-fullscreen-bar.svg#h5p) format("svg");font-weight:normal;font-style:normal}.h5peditor-form-manager-head{background:#f5f5f5;color:#414141;border-bottom:1px solid #dfdfdf;height:41px;line-height:40px;box-sizing:border-box;position:relative;display:flex;z-index:3;justify-content:space-between;align-items:flex-start;box-shadow:0px 2px 2px rgba(128,128,128,.15);padding:0 1em 0 .5em}.h5peditor-form-manager-button{background:rgba(0,0,0,0);padding:0;border:0;cursor:pointer;color:#414141;position:relative;white-space:nowrap;line-height:normal}.h5peditor-form-manager-button-inner{display:block;outline:none}.h5peditor-form-manager-breadcrumb{display:flex;min-width:0;flex-grow:1}.h5peditor-form-manager-proceed{display:none;background:#186df7;color:#fff;font-size:14px;font-weight:bold;font-family:Open Sans,sans-serif;border-radius:2px;margin-right:5px;margin-top:5px;padding:5px 10px}.h5peditor-form-manager-proceed:hover{background:#20588f}.h5peditor-form-manager-fullscreen{width:24px;height:24px;font-size:20px;margin-top:9px;margin-left:.25em}.h5peditor-form-manager-fullscreen .h5peditor-form-manager-button-inner:before{font-family:"h5p-fullscreen-bar";content:""}.h5peditor-form-manager-fullscreen:after{visibility:hidden;position:absolute;top:120%;right:-10%;z-index:3;padding:.25em .75em;background:#212121;color:#fff;white-space:nowrap;font-size:14px;box-shadow:0 0 .5em #858585;text-indent:0;font-weight:normal;pointer-events:none;outline:none;line-height:normal;content:attr(aria-label)}.h5peditor-form-manager-fullscreen:hover:after,.h5peditor-form-manager-fullscreen:focus:after{visibility:visible}.h5peditor-semi-fullscreen .h5peditor-form-manager-fullscreen .h5peditor-form-manager-button-inner:before{content:""}.h5peditor-semi-fullscreen .h5peditor-form-manager-proceed{display:block}.h5peditor-semi-fullscreen .h5peditor-form-manager-head{position:fixed;top:0;left:0;right:0;z-index:2}.form-manager-exit.form-manager-fullscreen .h5peditor-form-manager-button-inner:before{content:""}.h5peditor-form-manager-title{position:relative;min-width:20px;font-weight:bold;font-size:14px}.h5peditor-form-manager-title:before{font-family:"h5p-fullscreen-bar";content:"";font-size:1.2em;position:relative;top:.1em;margin-right:.25em;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;line-height:1;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.h5peditor-form-manager-title.dragtext:before{content:""}.h5peditor-form-manager-title.markthewords:before{content:""}.h5peditor-form-manager-title.multichoice:before{content:""}.h5peditor-form-manager-title.interactivevideo:before{content:""}.h5peditor-form-manager-title.audio:before{content:""}.h5peditor-form-manager-title.truefalse:before{content:""}.h5peditor-form-manager-title.dialogcards:before{content:""}.h5peditor-form-manager-title.questionnaire:before{content:""}.h5peditor-form-manager-title.coursepresentation:before{content:""}.h5peditor-form-manager-title.dragquestion:before{content:""}.h5peditor-form-manager-title.summary:before{content:""}.h5peditor-form-manager-title.singlechoiceset:before{content:""}.h5peditor-form-manager-title.blanks:before{content:""}.h5peditor-semi-fullscreen+.h5p-metadata-popup-overlay{position:fixed}.h5peditor-semi-fullscreen+.h5p-metadata-popup-overlay .h5p-metadata-wrapper{margin-top:20px !important}.h5peditor .h5peditor-language-switcher{float:right;white-space:nowrap;margin-bottom:1em}.h5peditor .h5peditor-language-switcher .language-label{padding:0 10px;font-size:15px}.h5peditor .h5peditor-language-switcher select{padding:6px 30px 6px 8px;font-size:15px}.h5peditor-language-notice{display:none;clear:both;font-size:14px;background:#dcf6ff;color:#295b7a;padding:10px 20px 10px 40px;margin:1em 0;line-height:1.5;position:relative}.h5peditor-language-notice:before{font-family:h5p;content:"";position:absolute;left:15px;font-size:1.125em}.h5peditor-language-notice.show{display:block}.h5peditor-language-notice .first{font-weight:bold}.h5peditor-language-notice a{text-decoration:underline}.h5p-loader__wrapper{width:100%;height:100%;flex:1;display:flex;align-items:center;padding:10px;min-width:180px}.h5p-loader__wrapper .h5p-loader__icon{border:8px solid #d0cfd4;border-bottom-color:#554e4a;border-radius:50%;width:40px;height:40px;animation:rotation linear 1s infinite;margin:0 auto}@keyframes rotation{0%{transform:rotate(0deg)}100%{transform:rotate(360deg)}}.h5p-sr-only{position:absolute;width:1px;height:1px;padding:0;margin:-1px;overflow:hidden;clip:rect(0, 0, 0, 0);white-space:nowrap;border-width:0} PK*\6V117h5plib/v127/joubel/editor/styles/css/h5p-hub-client.cssnu[.h5p-hub article,.h5p-hub aside,.h5p-hub details,.h5p-hub figcaption,.h5p-hub figure,.h5p-hub footer,.h5p-hub header,.h5p-hub hgroup,.h5p-hub menu,.h5p-hub nav,.h5p-hub section{display:block}.h5p-hub ol,.h5p-hub ul{list-style:none}.h5p-hub ul.ul,.h5p-hub .h5p-hub-ul{list-style:disc;margin:.833em 0}.h5p-hub ul.ul li,.h5p-hub .h5p-hub-ul li{margin-left:2.499em}.h5p-hub blockquote,.h5p-hub q{quotes:none}.h5p-hub blockquote:before,.h5p-hub blockquote:after,.h5p-hub q:before,.h5p-hub q:after{content:'';content:none}.h5p-hub table{border-collapse:collapse;border-spacing:0}.h5p-hub dl{margin-top:0;margin-bottom:0}.h5p-hub dd,.h5p-hub dt{padding:0;margin:0}.h5p-hub dt{font-weight:700}.h5p-hub button{border:0;padding:0;margin:0}.h5p-hub{font-family:'Open Sans', sans-serif;font-size:.917em;color:#1f2227}.h5p-hub .h1,.h5p-hub .h2,.h5p-hub .h3,.h5p-hub .h4,.h5p-hub .h5,.h5p-hub .h6,.h5p-hub h1,.h5p-hub h2,.h5p-hub h3,.h5p-hub h4,.h5p-hub h5,.h5p-hub h6{font-family:inherit;color:inherit;font-weight:300;line-height:1.1}.h5p-hub .h1,.h5p-hub .h2,.h5p-hub .h3,.h5p-hub h1,.h5p-hub h2,.h5p-hub h3{margin-top:.833em;margin-bottom:.4165em}.h5p-hub .h4,.h5p-hub .h5,.h5p-hub .h6,.h5p-hub h4,.h5p-hub h5,.h5p-hub h6{margin-top:.4165em;margin-bottom:.4165em;font-weight:600}.h5p-hub h1,.h5p-hub .h1{font-size:1.733em}.h5p-hub h2,.h5p-hub .h2{font-size:1.458em}.h5p-hub h3,.h5p-hub .h3{font-size:1.250em}.h5p-hub h4,.h5p-hub .h4{font-size:1.042em}.h5p-hub h5,.h5p-hub .h5{font-size:0.938em}.h5p-hub h6,.h5p-hub .h6{font-size:0.875em}.h5p-hub ul{padding:0;margin:0}.h5p-hub hr{border:0;height:0;margin:.833em 0;border-bottom:1px solid #ececec}.h5p-hub small,.h5p-hub .small,.h5p-hub .h5p-hub-small{color:#697585;line-height:1.7em;font-size:.95em}.h5p-hub .link,.h5p-hub a{font-family:'Open Sans', sans-serif;color:#1f2227;font-size:1em;font-weight:400;cursor:pointer;text-decoration:underline;background-color:transparent;border:0;padding:0}.h5p-hub .dl-horizontal dt{float:left;width:5em;overflow:hidden;clear:left;text-align:right;text-overflow:ellipsis;white-space:nowrap}.h5p-hub .dl-horizontal dd{margin-left:5.833em}.h5p-hub .additional-information{font-style:italic;color:#697585}.h5p-hub .hidden{display:none}.h5p-hub .h5p-hub-hidden{display:none}.h5p-hub .h5p-hub-button{font-family:'Open Sans', sans-serif;font-size:.95em;font-weight:600;text-align:center;text-decoration:none;line-height:1em;min-width:4em;padding:0.708em 1.5em;border-radius:1.375em;background-color:#f3f3f3;color:#1f2227;display:inline-block;cursor:pointer;border:2px solid transparent;transition:background-color .35s ease}.h5p-hub .h5p-hub-button[disabled],.h5p-hub .h5p-hub-button[aria-disabled]{cursor:not-allowed}.h5p-hub .h5p-hub-button:focus{outline:0;box-shadow:0.06em 0 0.6em 0.1em #7bc1f9}.h5p-hub .h5p-hub-button.h5p-hub-button-primary{background-color:#0a78d1;color:#fff;border-color:#0a78d1}.h5p-hub .h5p-hub-button.h5p-hub-button-primary:hover{background-color:#096ab9;border-color:#096ab9}.h5p-hub .h5p-hub-button.h5p-hub-button-primary:active{background-color:#085ca0;border-color:#085ca0}.h5p-hub .h5p-hub-button.h5p-hub-button-inverse-primary{background-color:#fff;color:#0a78d1;border-color:#0a78d1}.h5p-hub .h5p-hub-button.h5p-hub-button-inverse-primary:hover{color:#085ca0;border-color:#085ca0}.h5p-hub .h5p-hub-button.h5p-hub-button-inverse-primary:active{color:#054070;border-color:#054070}.h5p-hub .h5p-hub-button:before{font-weight:normal}.h5p-hub .h5p-hub-img-responsive{max-width:100%;object-fit:contain}.h5p-hub #h5p-hub-reuse-view .h5p-hub-img-responsive{background-color:#d0d0d1}@-webkit-keyframes spin{100%{transform:rotate(360deg)}}@keyframes spin{100%{transform:rotate(360deg)}}.h5p-hub .h5p-hub-button [class^="icon-"]{margin-right:.4165em;display:inline-block;font-weight:normal;font-size:0.9em}.h5p-hub .h5p-hub-icon-hub-icon:before{font-family:'h5p-hub';content:""}.h5p-hub .h5p-hub-icon-arrow-thick:before{font-family:'h5p-hub';content:""}.h5p-hub .h5p-hub-icon-arrow-thin:before{font-family:'h5p-hub';content:""}.h5p-hub .h5p-hub-icon-accordion-arrow:before{font-family:'h5p-hub';font-weight:normal;content:""}.h5p-hub .h5p-hub-icon-search:before{font-family:'h5p-hub';content:""} .h5p-hub .h5p-hub-client-drop-down{background-color:white;color:#697585;font-style:italic;font-weight:600;cursor:pointer;position:relative}.h5p-hub .h5p-hub-client-drop-down .h5p-hub-icon-hub-icon{color:#474f5a;padding:0.833em 1.55em}.h5p-hub .h5p-hub-client-drop-down .h5p-hub-icon-hub-icon:before{font-style:normal;font-weight:normal;margin-right:1em}.h5p-hub .h5p-hub-client-drop-down .h5p-hub-icon-hub-icon:after{font-family:'h5p-hub';content:"";display:inline-block;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;margin-right:.9163em;margin-right:1.8em;display:block;font-size:0.9em;line-height:3.5em;position:absolute;right:0;top:0}.h5p-hub .h5p-hub-client-drop-down .h5p-hub-description{color:transparent;width:1px;height:1px;overflow:hidden;display:inline-block;position:absolute}.h5p-hub .h5p-hub-client-drop-down .h5p-hub-selected{color:#474f5a} .h5p-hub .h5p-hub-panel.h5p-hub-section-content-types .h5p-hub-tab-button[aria-selected="true"]{border-bottom:3px solid #0a78d1}.h5p-hub .h5p-hub-panel.h5p-hub-section-reuse .h5p-hub-tab-button[aria-selected="true"]{border-bottom:3px solid #db6f28}.h5p-hub .h5p-hub-panel.h5p-hub-section-upload .h5p-hub-tab-button[aria-selected="true"]{border-bottom:3px solid #ced6e3}.h5p-hub .h5p-hub-tab-panel{border:none}.h5p-hub .h5p-hub-tab-panel [role="tablist"]{background-color:#474f5a;list-style:none;border-bottom:none;padding-left:1em;margin:0}.h5p-hub .h5p-hub-tab-panel [role="tablist"]>span{display:block;height:0.3em;background:#0a78d1;position:relative;transition:all .5s ease}.h5p-hub .h5p-hub-tab-panel [role="tab"]{display:inline-block;text-decoration:none;text-align:center;transition:all .5s ease;color:#f3f3f3;outline-color:#1a93f4;border-bottom:3px solid transparent;transition:border-bottom 0.4s}.h5p-hub .h5p-hub-tab-panel [role="tab"]:nth-child(1) ~ span,.h5p-hub .h5p-hub-tab-panel [role="tab"]:nth-child(1)[aria-selected="true"] ~ span{height:0.27em;width:200px;right:0}.h5p-hub .h5p-hub-tab-panel [role="tab"]:nth-child(2) ~ span,.h5p-hub .h5p-hub-tab-panel [role="tab"]:nth-child(2)[aria-selected="true"] ~ span{height:0.27em;width:4em;right:-230px}.h5p-hub .h5p-hub-tab-panel [role="tab"]>a{display:block;color:#fff;text-decoration:none;padding:.833em}.h5p-hub .h5p-hub-tab-panel [role="tab"]>a:before{font-family:'h5p-hub';content:"";display:inline-block;speak:none;font-style:normal;font-weight:normal;font-variant:normal;text-transform:none;margin-right:.833em}.h5p-hub .h5p-hub-tab-panel [role="tab"]>a:focus:before{border-radius:50%;box-shadow:0 0 0.6em 0.1em #7bc1f9}.h5p-hub .h5p-hub-tab-panel [role="tab"][aria-selected='true']>a:before{content:""} .h5p-hub .h5p-hub-no-content{display:flex;box-shadow:0 -0.4em 0.4em -0.2em rgba(79,87,99,0.2) inset}.h5p-hub .h5p-hub-no-content .h5p-hub-no-results-img{width:12.7em;height:4.95em;padding:3em 2em}@media (max-width: 576px){.h5p-hub .h5p-hub-no-content .h5p-hub-no-results-img{width:8em;padding:3em 1em}}.h5p-hub .h5p-hub-no-content .h5p-hub-right-text{padding:3em 2em}.h5p-hub .h5p-hub-no-content .h5p-hub-right-text .h5p-hub-header{font-size:1.2em;font-weight:bold;margin-bottom:0.4em}.h5p-hub .h5p-hub-no-content .h5p-hub-right-text .h5p-hub-suggestion-text{color:#4d4d4d;margin-bottom:0.3em}@media (max-width: 576px){.h5p-hub .h5p-hub-no-content .h5p-hub-right-text{padding:3em 1em}}.h5p-hub .h5p-hub-no-content .h5p-hub-right-text .h5p-hub-url{color:#186df7;font-weight:bold} .h5p-hub-list{overflow:auto}.h5p-hub-list ol{margin:1.25em 0;padding:0;list-style:none} .h5p-hub ul.h5p-hub-list-of-numbers{margin-top:1.5em;display:flex;flex-direction:row;border-radius:0.15146em;justify-content:center}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element{user-select:none;-ms-user-select:none;padding:0.17039em}@media (max-width: 576px){.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element{padding:0.25em;margin-bottom:1em}}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element a{padding:0.25em 0.75em;font-size:1em;font-weight:bold;text-decoration:none;outline:none;border-radius:0.15146em;border:0.07573em solid #ffffff;display:inline-block}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element a.h5p-hub-highlight{background-color:RGBA(209, 107, 23, 0.1);border:0.07573em solid #d16b17}@media (hover: hover){.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element a:hover{background-color:RGBA(209, 107, 23, 0.05);border:0.07573em solid #ffffff}}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element a:focus{box-shadow:0 0 0.4em 0.01em RGBA(26, 147, 244, 0.7)}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element.disabled{pointer-events:none}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element.disabled a{color:#b3b3b3}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-list-element.disabled a:hover{background-color:#ffffff}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-previous-arrow::after{font-family:'h5p-hub';content:"";transform:rotate(90deg);font-style:normal;font-size:0.7em;display:inline-block}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-next-arrow::before{font-family:'h5p-hub';content:"";transform:rotate(-90deg);font-style:normal;font-size:0.7em;display:inline-block}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-dots{padding:0.17039em;pointer-events:none;user-select:none;-ms-user-select:none}.h5p-hub ul.h5p-hub-list-of-numbers .h5p-hub-dots .h5p-hub-dots-text{padding:0.25em 0.75em} .h5p-hub .h5p-hub-content-item.h5p-hub-tabular{font-size:16px;display:flex;padding:0.5em 1em;border-bottom:1px solid #ececec;align-items:center;cursor:pointer}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-left{align-self:flex-start}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-middle{flex-grow:10;flex-shrink:10;margin-left:1em;overflow:hidden;min-width:0}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-content-icon{width:7em;height:5.25em;object-fit:contain;background-color:#d0d0d1}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-headline{line-height:1.2}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-title{font-size:1.1em;font-weight:bold;line-height:normal;letter-spacing:-0.5px}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-title.h5p-hub-reviewed:after{font-size:0.8em;font-family:'h5p-hub';font-weight:normal;content:'\e90b';color:#359d94;position:relative;top:-0.2em;margin-left:0.3em}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-by{font-size:1em;color:#666;margin:0 0.3em}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-owner{font-size:1em}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-content-type{font-size:0.9em;color:#303030;letter-spacing:0.65px;margin:0.25em 0}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-summary{color:#72757c;font-size:0.95em;white-space:nowrap;overflow:hidden;text-overflow:ellipsis}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-right{flex-grow:0;flex-shrink:0;position:relative;font-size:1.5em;width:1.5em;height:1em;text-align:center}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-right:before{color:#72757c;display:inline-block;opacity:0;transition:opacity 0.3s, left 0.3s;font-family:'h5p-hub';content:'\e906';position:relative;left:-0.2em}@media (max-width: 576px){.h5p-hub .h5p-hub-content-item.h5p-hub-tabular .h5p-hub-right{display:none}}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular:hover,.h5p-hub .h5p-hub-content-item.h5p-hub-tabular:focus{background-color:#fafafa}.h5p-hub .h5p-hub-content-item.h5p-hub-tabular:hover .h5p-hub-right:before,.h5p-hub .h5p-hub-content-item.h5p-hub-tabular:focus .h5p-hub-right:before{opacity:1;left:0em} .h5p-hub .h5p-hub-content-item.h5p-hub-grid{display:inline-block;width:16.66%;margin-top:0.5em;outline:none}@media (max-width: 768px){.h5p-hub .h5p-hub-content-item.h5p-hub-grid{width:33.33%}.h5p-hub .h5p-hub-content-item.h5p-hub-grid .h5p-hub-content-icon{height:10.5em}}@media (max-width: 576px){.h5p-hub .h5p-hub-content-item.h5p-hub-grid{width:50%}.h5p-hub .h5p-hub-content-item.h5p-hub-grid .h5p-hub-content-icon{height:12em}}.h5p-hub .h5p-hub-content-item.h5p-hub-grid:focus .h5p-hub-grid-item,.h5p-hub .h5p-hub-content-item.h5p-hub-grid:hover .h5p-hub-grid-item{background-color:#fafafa}.h5p-hub .h5p-hub-content-item.h5p-hub-grid:focus .h5p-hub-grid-item{border-color:#5B9DD9}.h5p-hub .h5p-hub-grid-item{cursor:pointer;text-align:center;padding:0.5em;border:1px solid #ddd;margin:0 0.3em}.h5p-hub .h5p-hub-grid-item .h5p-hub-grid-item-title{font-weight:bold;letter-spacing:-0.5px;display:-webkit-box;-webkit-line-clamp:2;-webkit-box-orient:vertical;overflow:hidden;text-overflow:ellipsis;height:3em}.h5p-hub .h5p-hub-grid-item img{width:100%;height:6em;object-fit:contain;background-color:#d0d0d1}.h5p-hub .h5p-hub-grid-item button{margin:0.5em 0 0.75em} .h5p-hub-list.h5p-hub-loading{pointer-events:none}.h5p-hub-list.h5p-hub-loading .h5p-hub-content-item{animation:opacitychange 1s infinite}.h5p-hub-list.h5p-hub-loading .h5p-hub-loading-block{background:#ccc;min-height:1.15em}.h5p-hub-list.h5p-hub-loading .h5p-hub-loading-block.h5p-hub-button{background:transparent;animation:none;border:2px solid #ccc}.h5p-hub-list.h5p-hub-loading .h5p-hub-middle{height:5.25em;display:flex;flex-direction:column;justify-content:space-between}.h5p-hub-list.h5p-hub-loading .h5p-hub-text-long{width:100%}.h5p-hub-list.h5p-hub-loading .h5p-hub-text-medium{width:60%}.h5p-hub-list.h5p-hub-loading .h5p-hub-text-short{width:30%}.h5p-hub-list.h5p-hub-loading .h5p-hub-grid-item{padding:1em}.h5p-hub-list.h5p-hub-loading .h5p-hub-grid-item .h5p-hub-image{height:8vw;min-height:5em}.h5p-hub-list.h5p-hub-loading .h5p-hub-grid-item .h5p-hub-loading-block{margin-bottom:0.5em}.h5p-hub-list.h5p-hub-loading .h5p-hub-grid-item .h5p-hub-loading-block.h5p-hub-button{margin-bottom:0;min-width:0;width:4em;max-width:40%}@keyframes opacitychange{0%{opacity:1}50%{opacity:0.6}100%{opacity:1}} .h5p-hub .h5p-hub-content-list{transition:opacity 0.2s, visibility 0s linear 0s}.h5p-hub .h5p-hub-content-list[aria-hidden="true"]{display:inherit;opacity:0;visibility:hidden;transition:opacity 0.2s, visibility 0s linear 0.2s}.h5p-hub .h5p-hub-content-list .h5p-hub-list.h5p-hub-tabular:before{content:" ";width:100%;height:calc(100% - 5.996455834em);position:absolute;pointer-events:none}.h5p-hub .h5p-hub-content-list .h5p-hub-list.h5p-hub-grid ol{margin:0}.h5p-hub .h5p-hub-content-list .h5p-hub-fetching-failed{display:inline-block;font-size:0.925em;border-radius:5px;margin-left:1em;padding:0.5em 0.85em;color:#c64750;background:rgba(198,71,80,0.1)} .h5p-hub .h5p-hub-navbar{background-color:transparent;list-style:none;color:#020202;border:0;padding:1.2em 1.2em 0.975422574em 2.292em;margin:0;font-size:1em;opacity:1;visibility:visible;transition:opacity 0.2s, visibility 0s linear 0s;overflow:auto;display:block}.h5p-hub .h5p-hub-navbar.h5p-hub-hidden{opacity:0;visibility:hidden;transition:opacity 0.2s, visibility 0s linear 0.2s}.h5p-hub .h5p-hub-result-header{font-size:1.042em;font-weight:600}.h5p-hub .h5p-hub-result-hits{font-size:0.8em;color:#697585;font-weight:400;padding-left:0.4em}.h5p-hub ul.h5p-hub-sort-by-list{margin-top:0.7844743em}.h5p-hub ul.h5p-hub-sort-by-list>li{float:left;margin-left:0.5em;user-select:none}.h5p-hub ul.h5p-hub-sort-by-list>li>a{display:block;color:#697585;padding:0.25em 0.75em;font-size:0.9em;text-decoration:none}.h5p-hub ul.h5p-hub-sort-by-list>li>a:hover{color:#3c434c}.h5p-hub ul.h5p-hub-sort-by-list>li>a:focus{box-shadow:0 0 1px 1px #1a93f4;outline:none}.h5p-hub ul.h5p-hub-sort-by-list>li>a.h5p-hub-highlight{font-weight:600;color:#000000;text-decoration:underline}.h5p-hub .h5p-hub-sort-by-header{float:left;padding:0.25em 0.75em 0.25em 0;font-size:0.9em;margin-top:0.871637586em} .h5p-hub-content-selection-list{padding:2em 1em 0}.h5p-hub-content-selection-list .h5p-hub-header{position:relative;font-weight:bold;padding:0 1em;margin-bottom:0.5em}.h5p-hub-content-selection-list .h5p-hub-title{font-size:1.2em}.h5p-hub-content-selection-list .h5p-hub-action{position:absolute;right:1.5em;top:0}.h5p-hub-content-selection-list:last-child{padding-bottom:1em} .h5p-hub .h5p-hub-filter-bar{background-color:#697585;font-size:1em;padding:0 0.833em 0.833em 1.125em;display:flex}.h5p-hub .h5p-hub-filter-bar .h5p-hub-filter-label{color:#ffffff;align-self:center}@media (max-width: 768px){.h5p-hub .h5p-hub-filter-bar{flex-direction:column}.h5p-hub .h5p-hub-filter-bar .h5p-hub-filter-label{align-self:start;margin-left:1em}}.h5p-hub .h5p-hub-filter-buttons{display:flex;flex-direction:row;flex-wrap:wrap}.h5p-hub .h5p-hub-filter-buttons li{outline:none;margin:0.5em 0 0.5em 0}.h5p-hub .h5p-hub-filter-buttons li:focus .h5p-hub-filter-button{box-shadow:0.06em 0 0.6em 0.1em #7bc1f9}.h5p-hub .h5p-hub-filter-buttons li:focus .h5p-hub-filter-button button{background-image:linear-gradient(0deg, #e3e3e3 0%, #fff 100%)}.h5p-hub .h5p-hub-clear-filters{flex-grow:1;align-self:center}@media (max-width: 768px){.h5p-hub .h5p-hub-clear-filters{align-self:start;margin-left:1em}}.h5p-hub .h5p-hub-clear-filters button{font-family:"Open Sans", sans-serif;align-items:center;float:right;display:flex;font-size:1em;background:none;color:#ffffff;font-size:0.88889em;cursor:pointer}.h5p-hub .h5p-hub-clear-filters button:focus{box-shadow:0.06em 0 0.6em 0.1em #7bc1f9;outline:none}.h5p-hub .h5p-hub-clear-filters button::before{font-family:'h5p-hub';content:"";font-style:normal;font-size:0.7em;margin-right:0.7em} .h5p-hub .h5p-hub-filter-modal{background:rgba(71,79,90,0.6);top:14.7em;width:100%;height:100%;left:0;position:absolute}.h5p-hub .h5p-hub-filter-dialog-content{padding:1.5em}.h5p-hub .h5p-hub-filter-dialog{position:absolute;width:40em;max-width:100%;box-sizing:border-box;background-color:#ffffff;border-radius:0.25em;box-shadow:2px 5px 5px 1px rgba(0,0,0,0.1)}.h5p-hub .h5p-hub-filter-dialog .h5p-hub-apply-filters-button{background-color:#697585;text-align:center;width:100%;color:#ffffff;font-size:1.15em;font-family:'Open Sans', sans-serif;padding:1em;border-radius:0.25em;margin-top:1em;cursor:pointer}.h5p-hub .h5p-hub-filter-dialog .h5p-hub-apply-filters-button::before{font-family:'h5p-hub';content:"";font-style:normal;font-size:1em;margin:0 0.4em 0 0.4em;margin-right:1em}.h5p-hub .h5p-hub-filter-dialog .h5p-hub-header-text{color:#000000;font-size:1.25em;font-weight:bold;margin-bottom:1em}.h5p-hub .h5p-hub-filter-dialog .h5p-hub-loading:after{font-family:'h5p-hub';content:"";font-size:1em;line-height:1;width:1em;height:1em;padding:.833em;display:block;color:#7c8696;-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;width:1em;margin:0 auto} .h5p-hub-message{position:relative;margin:.833em 0;padding:0.5em 1.250em;padding-right:2.250em}.h5p-hub-message .h5p-hub-title{font-size:1.042em;color:#1f2227}.h5p-hub-message .h5p-hub-message-content h2{margin-top:0.4165em;font-size:1.2em}.h5p-hub-message .h5p-hub-description{font-size:.95em;color:#697585}.h5p-hub-message .h5p-hub-message-header{margin:0;font-size:1.19em;line-height:1.9em}.h5p-hub-message .h5p-hub-message-body{font-size:0.925em;margin:0;padding-bottom:0.5em}.h5p-hub-message .h5p-hub-message-body ul.h5p-hub-message-item-list{list-style-type:disc;margin:1em}.h5p-hub-message .h5p-hub-message-content .h5p-hub-message-body{color:#697585}.h5p-hub-message .h5p-hub-get-help{margin-left:0.75em;color:#c62c15;text-decoration:none}.h5p-hub-message .h5p-hub-get-help:before{font-family:'h5p-hub';content:"";font-size:0.9em;margin-right:0.3em;display:inline-block}.h5p-hub-message .h5p-hub-message-close{cursor:pointer;display:block;position:absolute;background-color:transparent;color:#555;right:1.75em;line-height:2.75;font-size:0.75em;width:2.75em;text-align:center}.h5p-hub-message .h5p-hub-message-close:before{font-family:'h5p-hub';content:""}.h5p-hub-message .h5p-hub-message-close:hover{color:#333}.h5p-hub-message.h5p-hub-info{-webkit-box-shadow:0.167em 0 0 0 #00aa54 true;-moz-box-shadow:0.167em 0 0 0 #00aa54 true;box-shadow:0.167em 0 0 0 #00aa54 true;background:rgba(0,170,84,0.15);box-shadow:inset 0.167em 0 #00aa54}.h5p-hub-message.h5p-hub-info .h5p-hub-button{color:#00aa54;border:solid 1px;background-color:transparent;margin-top:1em}.h5p-hub-message.h5p-hub-warning{-webkit-box-shadow:0.167em 0 0 0 #fc3 true;-moz-box-shadow:0.167em 0 0 0 #fc3 true;box-shadow:0.167em 0 0 0 #fc3 true;background:rgba(255,204,51,0.15);box-shadow:inset 0.167em 0 #fc3}.h5p-hub-message.h5p-hub-warning .h5p-hub-button{color:#1f2227;border:solid 1px;background-color:transparent;margin-top:1em}.h5p-hub-message.h5p-hub-error{-webkit-box-shadow:0.167em 0 0 0 #c64750 true;-moz-box-shadow:0.167em 0 0 0 #c64750 true;box-shadow:0.167em 0 0 0 #c64750 true;background:rgba(198,71,80,0.15);box-shadow:inset 0.167em 0 #c64750}.h5p-hub-message.h5p-hub-error .h5p-hub-button{color:#c64750;border:solid 1px;background-color:transparent;margin-top:1em}.h5p-hub-message.h5p-hub-dismissible{overflow:auto;padding-right:3.5em} .h5p-hub .h5p-hub-filter-button{margin-left:0.85em}.h5p-hub .h5p-hub-filter-button button{font-family:'Open Sans', sans-serif;font-weight:600;padding:0.25em 0.426em;-ms-user-select:none;user-select:none;display:flex;align-items:center;font-size:1em;box-shadow:2px 2px 3px 1px rgba(0,0,0,0.1);border-radius:2px;background-image:linear-gradient(0deg, #e3e3e3 0%, #fff 100%)}.h5p-hub .h5p-hub-filter-button button.h5p-hub-open{background-image:linear-gradient(0deg, #c2c6cf 0%, #dde2e6 100%)}.h5p-hub .h5p-hub-filter-button button.h5p-hub-filter-checked{background-image:linear-gradient(0deg, #f4ddcd 0%, #fbfffc 100%)}.h5p-hub .h5p-hub-filter-button button.h5p-hub-one-checked{background-image:linear-gradient(0deg, #f4ddcd 0%, #fbfffc 100%)}.h5p-hub .h5p-hub-filter-button button:hover{background-image:linear-gradient(0deg, #c2c6cf 0%, #dde2e6 100%);cursor:pointer}.h5p-hub .h5p-hub-filter-button button .h5p-hub-icon{margin-left:0.3em}@media (min-width: 576px){.h5p-hub .h5p-hub-filter-button button .h5p-hub-icon::after{content:"\e565";font-family:"h5p";font-style:normal;font-size:0.8em;margin-left:0.6em}}.h5p-hub .h5p-hub-filter-button button .h5p-hub-icon.h5p-hub-check::before{font-family:'h5p-hub';content:"";font-style:normal;font-size:0.7em;margin:0 0.4em 0 0.4em} .h5p-hub .h5p-hub-checkbox-list{list-style:none}.h5p-hub .h5p-hub-checkbox-list.h5p-hub-animate-in-right{animation:move-from-right 0.35s}.h5p-hub .h5p-hub-checkbox-list.h5p-hub-animate-in-left{animation:move-from-left 0.35s}@keyframes move-from-right{0%{opacity:0;transform:translateX(30%)}30%{opacity:0}100%{opacity:1;transform:translateX(0)}}@keyframes move-from-left{0%{opacity:0;transform:translateX(-10%)}30%{opacity:0}100%{opacity:1;transform:translateX(0)}} .h5p-hub .h5p-hub-checkbox{font-size:1.05em;padding:0.5em 0;font-weight:bold;display:flex;cursor:pointer;align-self:start;color:#4d5057;width:100%;position:relative}.h5p-hub .h5p-hub-checkbox:focus{box-shadow:0 0 0.4em 0.01em RGBA(26, 147, 244, 0.7);outline:none}.h5p-hub .h5p-hub-checkbox.h5p-hub-parent::after{font-family:'h5p-hub';content:"";font-family:"h5p";transform:rotate(90deg);font-style:normal;font-size:1.1em;display:block;align-self:center}.h5p-hub .h5p-hub-checkbox .h5p-hub-non-bold{font-weight:normal}.h5p-hub .h5p-hub-checkbox .h5p-hub-content{display:flex}.h5p-hub .h5p-hub-checkbox .h5p-hub-content .h5p-hub-icon::before{font-family:'h5p-hub';content:"";font-style:normal;font-weight:normal;font-size:1em;margin:0.4em 0.4em 0 0.4em;margin-right:1em;color:#697585}.h5p-hub .h5p-hub-checkbox.h5p-hub-checked .h5p-hub-content .h5p-hub-icon::before{font-family:'h5p-hub';content:"";font-style:normal;font-weight:normal;font-size:1em;margin:0.4em 0.4em 0 0.4em;margin-right:1em;color:#697585} .h5p-hub .h5p-hub-bottom-line{border-bottom:2px solid #697585}.h5p-hub .h5p-hub-category-header{background-color:#f2f2f2;color:#313131;font-style:italic;padding:0 0 0 0.9em;font-size:0.81788em;text-transform:capitalize} .h5p-hub .h5p-hub-search-button{width:100%}.h5p-hub .h5p-hub-search-button .h5p-hub-search-field{position:relative}.h5p-hub .h5p-hub-search-button .h5p-hub-search-field::before{position:absolute;font-family:'h5p-hub';content:"";font-style:normal;font-size:1em;margin-left:1em;color:#b7b8ba;top:50%;transform:translateY(-50%)}.h5p-hub .h5p-hub-search-button .h5p-hub-search-field .h5p-hub-icon-arrow{position:absolute;font-size:1.30353em;top:0.7em;right:1em;cursor:pointer;color:#000000}.h5p-hub .h5p-hub-search-button .h5p-hub-search-field .h5p-hub-icon-arrow::before{content:"\e565";font-family:"h5p";font-style:normal;font-size:1.25em}.h5p-hub .h5p-hub-filter-search-bar{border:0.04545em solid #e6e6e8;padding:0.7em;font-style:italic;font-size:1.25em;width:100%;box-sizing:border-box;padding-left:2.25em}.h5p-hub .h5p-hub-filter-search-bar::placeholder{color:#b7b8ba}.h5p-hub .h5p-hub-filter-search-bar:focus{border-color:#3ba0f2;background-color:#fff;outline:none} .h5p-hub .h5p-hub-search-filter{outline:0.06815em solid #bebdcd;position:relative}.h5p-hub .h5p-hub-search-filter .h5p-hub-clear-button{background:none;position:absolute;top:0;padding:1.2em;right:3em;color:#757575}.h5p-hub .h5p-hub-search-filter .h5p-hub-clear-button::before{font-family:'h5p-hub';content:"";font-style:normal;font-size:1em}.h5p-hub .h5p-hub-search-filter .h5p-hub-navigate-parent{font-size:1.25em;padding:0.3534em;display:flex;font-weight:bold;font-family:"Open Sans", sans-serif;border:1px solid #e6e6e8;align-items:center}.h5p-hub .h5p-hub-search-filter .h5p-hub-navigate-parent button{background-color:#ffffff;position:relative;font-style:normal;font-size:0.8em;border-radius:50%;margin-right:0.4em;align-self:center;padding:0.5em;width:2.75em;height:2.75em}.h5p-hub .h5p-hub-search-filter .h5p-hub-navigate-parent button::before{font-family:'h5p-hub';content:"";transform:rotate(180deg);font-weight:normal;display:inline-block}.h5p-hub .h5p-hub-search-filter .h5p-hub-navigate-parent button:hover{background-color:#dadada;cursor:pointer}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list{overflow:hidden;overflow-y:scroll;max-height:25em}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li{border:1px solid #e6e6e8}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li .h5p-hub-content{padding:0.3em}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li .h5p-hub-content .h5p-hub-label-text{margin-right:0.2em}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li:focus{border-color:#3ba0f2;background-color:#fff;outline:none;box-shadow:none}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li:hover{background-color:#f2f2f2}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li.h5p-hub-highlighted{border-color:#3ba0f2;background-color:#fff;box-shadow:none}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list li:hover{background-color:rgba(230,230,232,0.25)}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list::-webkit-scrollbar{background-color:rgba(105,117,133,0.25);width:0.54525em;border-radius:5.45256em}.h5p-hub .h5p-hub-search-filter .h5p-hub-checkbox-list::-webkit-scrollbar-thumb{background-color:#697585;background-size:24px 100%;border-radius:5.45256em} .h5p-hub .h5p-hub-downloading-modal-overlay{position:absolute;top:0;left:0;right:0;bottom:0;background-color:rgba(255,255,255,0.8)}.h5p-hub .h5p-hub-downloading-modal{position:absolute;width:30rem;max-width:90%;border-radius:0.25rem;background-color:#ffffff;box-shadow:0px 1px 82px 0px rgba(0,0,0,0.2);left:50%;top:50%;transform:translate(-50%, -50%);transition:background-color 0.3s ease-in;display:flex;flex-wrap:wrap;flex-direction:row;justify-content:center;align-items:center;outline:none;box-sizing:border-box;padding:1em}.h5p-hub .h5p-hub-downloading-modal .h5p-hub-spinner{margin:1em;animation:spin 0.5s linear infinite}.h5p-hub .h5p-hub-downloading-modal span.h5p-hub-downloading-message{font-family:'Open Sans', sans-serif;font-weight:bold;font-size:2rem}.h5p-hub .h5p-hub-downloading-modal span.h5p-hub-downloading-message:focus{outline:none}@keyframes spin{from{transform:rotate(0deg)}to{transform:rotate(360deg)}} .h5p-hub-search-wrapper{padding:.833em 1.125em;background-color:#697585;position:relative}.h5p-hub-search-wrapper .h5p-hub-border-wrap{padding:3px;background:#fff;border-radius:1.25em;font-size:1.15em}.h5p-hub-search-wrapper .h5p-hub-icon-search{position:absolute;font-size:1em;top:1.4em;right:2.2em;cursor:pointer;color:#4f5662}.h5p-hub-search-bar{border:1px solid #bfc0c0;padding:0.5em 0.5em 0.5em 1.2em;font-style:italic;font-weight:400;font-size:1em;box-shadow:inset 0 0 10px rgba(0,0,0,0.4);color:#000000;border-radius:1.25em;width:100%;box-sizing:border-box}.h5p-hub-search-bar::placeholder{color:#000000}.h5p-hub-search-bar:focus{border-color:#3ba0f2;background-color:#fff;box-shadow:inset 0 0 10px rgba(0,0,0,0.2);outline:none}.h5p-hub-search-bar:focus::placeholder{color:#697585}.h5p-hub-search-bar:before{background:none;border:4px solid #fff;content:"";display:block;position:absolute;top:4px;left:4px;right:4px;bottom:4px;pointer-events:none}.h5p-hub-search-bar::-ms-clear{display:none;width:0;height:0} .h5p-hub .h5p-hub-button.h5p-hub-button-orange{background:transparent;color:#d16b17;border:0.125em solid #d16b17}.h5p-hub .h5p-hub-button.h5p-hub-button-orange:hover{color:#fff;background-color:#d16b17;border-color:#d16b17}.h5p-hub .h5p-hub-button.h5p-hub-button-orange:active{color:#fff;background-color:#c26d13;border-color:#c26d13} .h5p-hub-lightbox{position:absolute;top:0;left:0;right:0;bottom:0;background:rgba(0,0,0,0.8)}.h5p-hub-lightbox-inner{position:absolute;left:50%;top:50%;transform:translate(-50%, -50%);width:100%;box-sizing:border-box;padding:2em;text-align:center}.h5p-hub-lightbox-inner:focus{outline:0}.h5p-hub-lightbox-close{position:relative;top:-1.5em;right:0;float:right;width:1.2em;height:1.2em;border-radius:50%;color:#fff;font-size:2em;line-height:1;text-align:center;cursor:pointer;z-index:1;user-select:none;border:2px solid transparent;transition:background 0.2s}.h5p-hub-lightbox-close:focus{border-color:#7bc1f9;box-shadow:0.06em 0 0.6em 0.1em #7bc1f9;outline:0}.h5p-hub-lightbox-close:hover{background:rgba(132,143,158,0.8)}.h5p-hub-license .h5p-hub-lightbox-close:hover{background:rgba(165,175,189,0.43)}.h5p-hub-lightbox-close:before{font-family:'h5p-hub';content:"";font-size:0.6em} .h5p-hub-carousel{width:100%;box-sizing:border-box;position:relative}.h5p-hub-carousel .h5p-hub-scroller{overflow:hidden;width:calc(100% - 5em);margin-left:2.5em}.h5p-hub-carousel ul{width:100%;padding:0;margin:0 auto;word-wrap:break-word;transition:margin 0.3s linear;display:flex;flex-direction:row;flex-wrap:nowrap;align-items:center}.h5p-hub-carousel li{padding:0 .3125em;width:20%;margin:0;list-style-type:none;float:left;box-sizing:border-box;overflow:hidden}.h5p-hub-carousel li img{max-width:100%;box-sizing:border-box;border:1px solid #ced6e3}.h5p-hub-carousel li img.h5p-hub-selectable{cursor:pointer}.h5p-hub-carousel li:focus{outline:0}.h5p-hub-carousel li:focus img{border-color:#0a78d1}.h5p-hub-carousel .h5p-hub-progress{color:#fff;position:relative;bottom:-2em;text-align:center}.h5p-hub-carousel .h5p-hub-navigation{width:2.1em;height:2.1em;line-height:2.1em;position:absolute;border-radius:50%;color:white;background-color:rgba(105,117,133,0.8);cursor:pointer;border:2px solid transparent;top:50%;transform:translateY(-50%)}.h5p-hub-carousel .h5p-hub-navigation[disabled]{background-color:rgba(189,195,203,0.8);color:rgba(255,255,255,0.6);pointer-events:none}.h5p-hub-carousel .h5p-hub-navigation:before{display:inline-block;line-height:1em;height:1em}.h5p-hub-carousel .h5p-hub-navigation:hover{background-color:rgba(132,143,158,0.8)}.h5p-hub-carousel .h5p-hub-navigation:focus{outline:0;box-shadow:0.06em 0 0.6em 0.1em #7bc1f9;border-color:#7bc1f9}.h5p-hub-carousel .h5p-hub-prev{left:0}.h5p-hub-carousel .h5p-hub-prev:before{font-family:'h5p-hub';content:""}.h5p-hub-carousel .h5p-hub-next{right:0}.h5p-hub-carousel .h5p-hub-next:before{font-family:'h5p-hub';content:"";transform:rotate(180deg)}.h5p-hub-lightbox-inner .h5p-hub-carousel ul{transition-duration:0.15s}.h5p-hub-lightbox-inner .h5p-hub-carousel li{padding:0}.h5p-hub-lightbox-inner .h5p-hub-carousel li img{border-color:transparent;background:#fff}.h5p-hub-lightbox-inner .h5p-hub-carousel .h5p-hub-navigation{font-size:1.2em}.h5p-hub-lightbox-inner .h5p-hub-carousel .h5p-hub-navigation:focus{background-color:transparent}.h5p-hub-lightbox-inner .h5p-hub-carousel .h5p-hub-next{right:-0.75em}.h5p-hub-lightbox-inner .h5p-hub-carousel .h5p-hub-prev{left:-0.75em} .h5p-hub-text-details .h5p-read-more span{outline:none}.h5p-hub-text-details .h5p-read-more .h5p-hub-link{color:#1f2227;outline:none;margin-left:0.5em}.h5p-hub-text-details .h5p-read-more .h5p-hub-link:hover{color:#000}.h5p-hub-text-details .h5p-read-more .h5p-hub-link:focus{box-shadow:0 0 1px 1px #1a93f4} .h5p-hub-accordion{border:1px solid #ced6e3;border-bottom:0}.h5p-hub-accordion .h5p-hub-icon-accordion-arrow{margin-top:-4px;font-size:0.7em;margin-right:.833em;margin-left:.833em;display:inline-block;vertical-align:middle;transition:transform 0.1s ease-out}.h5p-hub-accordion [aria-expanded="true"] .h5p-hub-icon-accordion-arrow{transform:rotate(90deg)}.h5p-hub-accordion-toggler{display:block;box-sizing:border-box;text-decoration:none;width:100%;padding:.833em;color:#1f2227}.h5p-hub-accordion-heading{border-bottom:1px solid #ced6e3;background-color:#f3f3f3;cursor:pointer}.h5p-hub-accordion-region{border-bottom:1px solid #ced6e3}.h5p-hub-accordion-region .h5p-hub-panel-body{padding:1em;line-height:1.7em;font-size:0.95em} .h5p-hub .publisher-info{overflow:auto}.h5p-hub .publisher-info .h5p-hub-publisher-image{max-width:10em;max-height:10em;height:auto;width:auto;margin-right:1em;float:left}.h5p-hub .h5p-hub-publisher-image{max-width:150px} .h5p-hub .h5p-hub-content-detail{background-color:white;padding:1.3em;display:inherit;position:absolute;top:0;left:0;visibility:hidden;outline:none;overflow:auto;width:100%;height:100%;box-sizing:border-box;transform:translateX(100%);transition:transform 0.2s ease-out, visibility 0s linear 0.2s}.h5p-hub .h5p-hub-content-detail::-webkit-scrollbar{background-color:#f3f3f3;width:0.750em}.h5p-hub .h5p-hub-content-detail::-webkit-scrollbar-thumb{background:#5e6978 url("data:image/svg+xml;base64,PHN2ZyBpZD0ic2Nyb2xsYmFyX2hhbmRsZSIgZGF0YS1uYW1lPSJzY3JvbGxiYXIgaGFuZGxlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogIDxkZWZzPg0KICAgIDxzdHlsZT4NCiAgICAgIC5jbHMtMSB7DQogICAgICAgIGZpbGw6ICNjZWQ2ZTM7DQogICAgICB9DQoNCiAgICAgIC5jbHMtMiB7DQogICAgICAgIGZpbGw6IG5vbmU7DQogICAgICB9DQogICAgPC9zdHlsZT4NCiAgPC9kZWZzPg0KICA8dGl0bGU+c2Nyb2xsYmFyLWJhcnMtaWNvbjwvdGl0bGU+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE1LjI4LDguNWMwLC4yNC0uMS40My0uMjQuNDNIOS42MmMtLjE0LDAtLjI0LS4xOS0uMjQtLjQzVjcuNjVjMC0uMjQuMS0uNDMuMjQtLjQzSDE1Yy4xNCwwLC4yNC4xOS4yNC40M1ptMCwzLjQxYzAsLjI0LS4xLjQzLS4yNC40M0g5LjYyYy0uMTQsMC0uMjQtLjE5LS4yNC0uNDN2LS44NWMwLS4yNC4xLS40My4yNC0uNDNIMTVjLjE0LDAsLjI0LjE5LjI0LjQzWm0wLDMuNDNjMCwuMjQtLjEuNDMtLjI0LjQzSDkuNjJjLS4xNCwwLS4yNC0uMTktLjI0LS40M3YtLjg1YzAtLjI0LjEtLjQzLjI0LS40M0gxNWMuMTQsMCwuMjQuMTkuMjQuNDNaIi8+DQogIDxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+DQo8L3N2Zz4NCg==") no-repeat center;background-size:24px 100%}.h5p-hub .h5p-hub-content-detail::-webkit-scrollbar-button:vertical{background-size:20px 20px;background-position-x:-4px;background-position-y:-3px;background-color:#5e6978;background-repeat:no-repeat}.h5p-hub .h5p-hub-content-detail::-webkit-scrollbar-button:vertical:decrement{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQoJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4qIHtmaWxsOiAjY2VkNmUzO30gLnN0MHtmaWxsOm5vbmU7fTwvc3R5bGU+DQoJPHRpdGxlPmFycm93LXVwPC90aXRsZT4NCgk8cGF0aCBkPSJNOCAxMy45bDAuNCAwLjRjMC4zIDAuMyAwLjggMC4zIDEuMSAwbDIuNC0yLjQgMi40IDIuNGMwLjMgMC4zIDAuOCAwLjMgMS4xIDBsMC40LTAuNGMwLjMtMC4zIDAuMy0wLjggMC0xLjEgMCAwIDAgMCAwIDBsLTMuMy0zLjNjLTAuMy0wLjMtMC44LTAuMy0xLjEgMCAwIDAgMCAwIDAgMEw4IDEyLjhDNy43IDEzLjEgNy43IDEzLjUgOCAxMy45IDggMTMuOCA4IDEzLjggOCAxMy45eiIvPg0KCTxyZWN0IGNsYXNzPSJzdDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIvPg0KPC9zdmc+")}.h5p-hub .h5p-hub-content-detail::-webkit-scrollbar-button:vertical:increment{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHN0eWxlPioge2ZpbGw6ICNjZWQ2ZTM7fSAuY2xzLTEge2ZpbGw6IG5vbmU7fTwvc3R5bGU+DQogIDx0aXRsZT5hcnJvdy1kb3duPC90aXRsZT4NCiAgPHBhdGggZD0iTTE2LDEwLjE1bC0uMzUtLjM1YS43OS43OSwwLDAsMC0xLjA4LDBsLTIuNDMsMi40M0w5LjY5LDkuNzlhLjc4Ljc4LDAsMCwwLTEuMDgsMGwtLjM2LjM2YS43Ni43NiwwLDAsMCwwLDEuMDhsMy4zMiwzLjMyYS43Ni43NiwwLDAsMCwxLjA4LDBMMTYsMTEuMjNhLjc2Ljc2LDAsMCwwLDAtMS4wOFoiLz4NCiAgPHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4NCjwvc3ZnPg0K")}.h5p-hub .h5p-hub-content-detail.h5p-hub-show{transform:translateX(0);visibility:visible;transition:transform 0.2s ease-out, visibility 0s linear 0s}.h5p-hub .h5p-hub-content-detail .h5p-hub-panel[aria-hidden="false"]{display:none}.h5p-hub .h5p-hub-content-detail .h5p-hub-container{max-width:100%;margin-left:auto;margin-right:auto;margin-top:.833em;margin-bottom:1.666em;padding-bottom:1em;display:flex;flex-wrap:wrap;flex-direction:column}.h5p-hub .h5p-hub-content-detail .h5p-hub-container:after{content:" ";display:block;clear:both}@media (min-width: 576px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container{flex-direction:row}}.h5p-hub .h5p-hub-content-detail .h5p-hub-container .h5p-hub-image-wrapper{flex-shrink:0;order:1;display:flex;justify-content:center;align-items:center}@media (min-width: 768px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container .h5p-hub-image-wrapper{justify-content:normal;align-items:normal;margin-top:2em}}.h5p-hub .h5p-hub-content-detail .h5p-hub-container .h5p-hub-image-wrapper img{width:16.5em;height:12.375em}@media (min-width: 768px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container .h5p-hub-image-wrapper img{width:15.5em;height:11.625em}}.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-text-details{order:2;flex-grow:1;margin:2em}.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-text-details .h5p-hub-info-list{order:2}@media (min-width: 576px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-text-details{order:3;flex-basis:100%}.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-text-details .h5p-hub-info-list{display:none}}@media (min-width: 768px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-text-details{order:2;flex-basis:0;margin:2em 2em 0}}.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-text-details h2{margin-top:0;font-size:1.458em;line-height:1.458em}.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-info-list{order:3;flex-shrink:0;min-width:15em;margin:1em;display:none}@media (min-width: 576px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-info-list{display:block;order:2;flex-grow:1}}@media (min-width: 768px){.h5p-hub .h5p-hub-content-detail .h5p-hub-container>.h5p-hub-info-list{order:3;flex-grow:0}}.h5p-hub .h5p-hub-content-detail .h5p-hub-title{outline:0}.h5p-hub .h5p-hub-content-detail .h5p-hub-title.h5p-hub-reviewed:after{font-size:0.8em;font-family:"h5p-hub";font-weight:normal;content:"\e90b";color:#359d94;position:relative;top:-0.2em;margin-left:0.3em}.h5p-hub .h5p-hub-content-detail .h5p-hub-back-button{color:#474f5a;font-size:1.3em;display:inline-block;background:transparent;border:none;text-decoration:none;outline:none;transform:rotate(180deg)}.h5p-hub .h5p-hub-content-detail .h5p-hub-back-button:hover{color:#000}.h5p-hub .h5p-hub-content-detail .h5p-hub-back-button:focus{box-shadow:0 0 1px 1px #1a93f4}.h5p-hub .h5p-hub-content-detail .h5p-hub-back-button.h5p-hub-icon-arrow-thick:before{cursor:pointer}.h5p-hub .h5p-hub-content-detail .h5p-hub-button-bar{text-align:right;margin:1.666em 0}.h5p-hub .h5p-hub-content-detail .h5p-hub-button-download-content{display:inline-flex;align-items:center}.h5p-hub .h5p-hub-content-detail .h5p-hub-button-download-content::before{font-family:"h5p-hub";font-size:0.7em;content:"\e90c";display:inline-block;margin-right:1em;transform:rotate(-90deg)}.h5p-hub .h5p-hub-content-detail .h5p-hub-lightbox-inner.h5p-hub-license::-webkit-scrollbar{background-color:#f3f3f3;width:0.750em}.h5p-hub .h5p-hub-content-detail .h5p-hub-lightbox-inner.h5p-hub-license::-webkit-scrollbar-thumb{background:#5e6978 url("data:image/svg+xml;base64,PHN2ZyBpZD0ic2Nyb2xsYmFyX2hhbmRsZSIgZGF0YS1uYW1lPSJzY3JvbGxiYXIgaGFuZGxlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogIDxkZWZzPg0KICAgIDxzdHlsZT4NCiAgICAgIC5jbHMtMSB7DQogICAgICAgIGZpbGw6ICNjZWQ2ZTM7DQogICAgICB9DQoNCiAgICAgIC5jbHMtMiB7DQogICAgICAgIGZpbGw6IG5vbmU7DQogICAgICB9DQogICAgPC9zdHlsZT4NCiAgPC9kZWZzPg0KICA8dGl0bGU+c2Nyb2xsYmFyLWJhcnMtaWNvbjwvdGl0bGU+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE1LjI4LDguNWMwLC4yNC0uMS40My0uMjQuNDNIOS42MmMtLjE0LDAtLjI0LS4xOS0uMjQtLjQzVjcuNjVjMC0uMjQuMS0uNDMuMjQtLjQzSDE1Yy4xNCwwLC4yNC4xOS4yNC40M1ptMCwzLjQxYzAsLjI0LS4xLjQzLS4yNC40M0g5LjYyYy0uMTQsMC0uMjQtLjE5LS4yNC0uNDN2LS44NWMwLS4yNC4xLS40My4yNC0uNDNIMTVjLjE0LDAsLjI0LjE5LjI0LjQzWm0wLDMuNDNjMCwuMjQtLjEuNDMtLjI0LjQzSDkuNjJjLS4xNCwwLS4yNC0uMTktLjI0LS40M3YtLjg1YzAtLjI0LjEtLjQzLjI0LS40M0gxNWMuMTQsMCwuMjQuMTkuMjQuNDNaIi8+DQogIDxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+DQo8L3N2Zz4NCg==") no-repeat center;background-size:24px 100%}.h5p-hub .h5p-hub-content-detail .h5p-hub-lightbox-inner.h5p-hub-license::-webkit-scrollbar-button:vertical{background-size:20px 20px;background-position-x:-4px;background-position-y:-3px;background-color:#5e6978;background-repeat:no-repeat}.h5p-hub .h5p-hub-content-detail .h5p-hub-lightbox-inner.h5p-hub-license::-webkit-scrollbar-button:vertical:decrement{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQoJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4qIHtmaWxsOiAjY2VkNmUzO30gLnN0MHtmaWxsOm5vbmU7fTwvc3R5bGU+DQoJPHRpdGxlPmFycm93LXVwPC90aXRsZT4NCgk8cGF0aCBkPSJNOCAxMy45bDAuNCAwLjRjMC4zIDAuMyAwLjggMC4zIDEuMSAwbDIuNC0yLjQgMi40IDIuNGMwLjMgMC4zIDAuOCAwLjMgMS4xIDBsMC40LTAuNGMwLjMtMC4zIDAuMy0wLjggMC0xLjEgMCAwIDAgMCAwIDBsLTMuMy0zLjNjLTAuMy0wLjMtMC44LTAuMy0xLjEgMCAwIDAgMCAwIDAgMEw4IDEyLjhDNy43IDEzLjEgNy43IDEzLjUgOCAxMy45IDggMTMuOCA4IDEzLjggOCAxMy45eiIvPg0KCTxyZWN0IGNsYXNzPSJzdDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIvPg0KPC9zdmc+")}.h5p-hub .h5p-hub-content-detail .h5p-hub-lightbox-inner.h5p-hub-license::-webkit-scrollbar-button:vertical:increment{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHN0eWxlPioge2ZpbGw6ICNjZWQ2ZTM7fSAuY2xzLTEge2ZpbGw6IG5vbmU7fTwvc3R5bGU+DQogIDx0aXRsZT5hcnJvdy1kb3duPC90aXRsZT4NCiAgPHBhdGggZD0iTTE2LDEwLjE1bC0uMzUtLjM1YS43OS43OSwwLDAsMC0xLjA4LDBsLTIuNDMsMi40M0w5LjY5LDkuNzlhLjc4Ljc4LDAsMCwwLTEuMDgsMGwtLjM2LjM2YS43Ni43NiwwLDAsMCwwLDEuMDhsMy4zMiwzLjMyYS43Ni43NiwwLDAsMCwxLjA4LDBMMTYsMTEuMjNhLjc2Ljc2LDAsMCwwLDAtMS4wOFoiLz4NCiAgPHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4NCjwvc3ZnPg0K")} .h5p-hub .h5p-hub-info-list{max-width:20em}.h5p-hub .h5p-hub-info-list li{font-size:0.8em;border-bottom:1px solid #dadada;padding:0.85em 0.5em}.h5p-hub .h5p-hub-info-list li .h5p-hub-label{color:#72757c;margin-right:0.3em}.h5p-hub .h5p-hub-info-list li .h5p-hub-content{color:#242424;font-weight:bold}.h5p-hub .h5p-hub-info-list li .h5p-hub-capitalize{text-transform:capitalize}.h5p-hub .h5p-hub-info-list li:last-child{border-bottom:none} .h5p-hub .h5p-hub-short-license-info h3{display:inline-block}.h5p-hub .h5p-hub-short-license-info .h5p-hub-short-license-read-more{border:0;background-color:transparent;cursor:pointer}.h5p-hub .h5p-hub-short-license-info a.h5p-hub-short-license-read-more{text-decoration:none}.h5p-hub .h5p-hub-short-license-info .h5p-hub-short-license-read-more:before{font-family:'h5p-hub';content:"";margin-left:0.5em} .h5p-hub .h5p-hub-reuse-content-result{position:relative;overflow-y:auto;overflow-x:hidden;max-height:56em;box-shadow:0 0.4em 0.4em -0.2em rgba(79,87,99,0.2) inset}.h5p-hub .h5p-hub-reuse-content-result::-webkit-scrollbar{background-color:#F3F3F3;width:0.750em}.h5p-hub .h5p-hub-reuse-content-result::-webkit-scrollbar-thumb{background:#5e6978 url("data:image/svg+xml;base64,PHN2ZyBpZD0ic2Nyb2xsYmFyX2hhbmRsZSIgZGF0YS1uYW1lPSJzY3JvbGxiYXIgaGFuZGxlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogIDxkZWZzPg0KICAgIDxzdHlsZT4NCiAgICAgIC5jbHMtMSB7DQogICAgICAgIGZpbGw6ICNjZWQ2ZTM7DQogICAgICB9DQoNCiAgICAgIC5jbHMtMiB7DQogICAgICAgIGZpbGw6IG5vbmU7DQogICAgICB9DQogICAgPC9zdHlsZT4NCiAgPC9kZWZzPg0KICA8dGl0bGU+c2Nyb2xsYmFyLWJhcnMtaWNvbjwvdGl0bGU+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE1LjI4LDguNWMwLC4yNC0uMS40My0uMjQuNDNIOS42MmMtLjE0LDAtLjI0LS4xOS0uMjQtLjQzVjcuNjVjMC0uMjQuMS0uNDMuMjQtLjQzSDE1Yy4xNCwwLC4yNC4xOS4yNC40M1ptMCwzLjQxYzAsLjI0LS4xLjQzLS4yNC40M0g5LjYyYy0uMTQsMC0uMjQtLjE5LS4yNC0uNDN2LS44NWMwLS4yNC4xLS40My4yNC0uNDNIMTVjLjE0LDAsLjI0LjE5LjI0LjQzWm0wLDMuNDNjMCwuMjQtLjEuNDMtLjI0LjQzSDkuNjJjLS4xNCwwLS4yNC0uMTktLjI0LS40M3YtLjg1YzAtLjI0LjEtLjQzLjI0LS40M0gxNWMuMTQsMCwuMjQuMTkuMjQuNDNaIi8+DQogIDxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+DQo8L3N2Zz4NCg==") no-repeat center;background-size:24px 100%}.h5p-hub .h5p-hub-reuse-content-result::-webkit-scrollbar-button:vertical{background-size:20px 20px;background-position-x:-4px;background-position-y:-3px;background-color:#5e6978;background-repeat:no-repeat}.h5p-hub .h5p-hub-reuse-content-result::-webkit-scrollbar-button:vertical:decrement{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQoJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4qIHtmaWxsOiAjY2VkNmUzO30gLnN0MHtmaWxsOm5vbmU7fTwvc3R5bGU+DQoJPHRpdGxlPmFycm93LXVwPC90aXRsZT4NCgk8cGF0aCBkPSJNOCAxMy45bDAuNCAwLjRjMC4zIDAuMyAwLjggMC4zIDEuMSAwbDIuNC0yLjQgMi40IDIuNGMwLjMgMC4zIDAuOCAwLjMgMS4xIDBsMC40LTAuNGMwLjMtMC4zIDAuMy0wLjggMC0xLjEgMCAwIDAgMCAwIDBsLTMuMy0zLjNjLTAuMy0wLjMtMC44LTAuMy0xLjEgMCAwIDAgMCAwIDAgMEw4IDEyLjhDNy43IDEzLjEgNy43IDEzLjUgOCAxMy45IDggMTMuOCA4IDEzLjggOCAxMy45eiIvPg0KCTxyZWN0IGNsYXNzPSJzdDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIvPg0KPC9zdmc+")}.h5p-hub .h5p-hub-reuse-content-result::-webkit-scrollbar-button:vertical:increment{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHN0eWxlPioge2ZpbGw6ICNjZWQ2ZTM7fSAuY2xzLTEge2ZpbGw6IG5vbmU7fTwvc3R5bGU+DQogIDx0aXRsZT5hcnJvdy1kb3duPC90aXRsZT4NCiAgPHBhdGggZD0iTTE2LDEwLjE1bC0uMzUtLjM1YS43OS43OSwwLDAsMC0xLjA4LDBsLTIuNDMsMi40M0w5LjY5LDkuNzlhLjc4Ljc4LDAsMCwwLTEuMDgsMGwtLjM2LjM2YS43Ni43NiwwLDAsMCwwLDEuMDhsMy4zMiwzLjMyYS43Ni43NiwwLDAsMCwxLjA4LDBMMTYsMTEuMjNhLjc2Ljc2LDAsMCwwLDAtMS4wOFoiLz4NCiAgPHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4NCjwvc3ZnPg0K")}.h5p-hub .h5p-hub-reuse-content-result>.h5p-hub-content-list .h5p-hub-fetching-failed{margin-top:2em;margin-left:2em}.h5p-hub .h5p-hub-reuse-content-container{position:relative}.h5p-hub .h5p-hub-content-list-hidden{visibility:hidden} .h5p-hub .h5p-hub-content-type-list .h5p-hub-media .h5p-hub-media-body{overflow:visible;zoom:1;width:10000px}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-left{display:table-cell;vertical-align:top}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-body{display:table-cell;vertical-align:middle}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-left{padding-right:.833em}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-object{width:50px}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-heading{margin-top:0;float:left;margin-right:0.5em}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-text-icon{float:left;height:15px}.h5p-hub .h5p-hub-content-type-list .h5p-hub-button{min-width:4em;padding:0.65em 1.5em;float:right}.h5p-hub .h5p-hub-content-type-list .h5p-hub-description{color:#697585;font-size:.95em;float:left;clear:left}.h5p-hub .h5p-hub-content-type-list .h5p-hub-content-type-update-info{margin-right:0;color:#697585;font-size:0.8em;font-style:italic;float:left}.h5p-hub .h5p-hub-content-type-list .h5p-hub-content-type-update-info:before{font-family:'h5p-hub';content:"";font-style:normal;font-size:0.8em;margin-right:0.4em}.h5p-hub .h5p-hub-content-type-list .h5p-hub-button-install:before{font-family:'h5p-hub';content:"";display:inline-block;transform:rotate(-90deg);margin-right:0.7em;font-size:0.9em}@media (min-width: 768px){.h5p-hub .h5p-hub-content-type-list .h5p-hub-button{margin-top:0.25em}.h5p-hub .h5p-hub-content-type-list .h5p-hub-content-type-update-info{margin-right:2em;margin-top:1em;float:right}}@media (min-width: 576px){.h5p-hub .h5p-hub-content-type-list .h5p-hub-media-object{width:100px}} .h5p-hub .h5p-hub-content-type-list{overflow:auto;height:37.422137em;opacity:1;transition:opacity 0.2s, visibility 0s linear 0s}.h5p-hub .h5p-hub-content-type-list[aria-hidden="true"]{display:inherit;opacity:0;visibility:hidden;transition:opacity 0.2s, visibility 0s linear 0.2s}.h5p-hub .h5p-hub-content-type-list::-webkit-scrollbar{background-color:#F3F3F3;width:0.750em}.h5p-hub .h5p-hub-content-type-list::-webkit-scrollbar-thumb{background:#5e6978 url("data:image/svg+xml;base64,PHN2ZyBpZD0ic2Nyb2xsYmFyX2hhbmRsZSIgZGF0YS1uYW1lPSJzY3JvbGxiYXIgaGFuZGxlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogIDxkZWZzPg0KICAgIDxzdHlsZT4NCiAgICAgIC5jbHMtMSB7DQogICAgICAgIGZpbGw6ICNjZWQ2ZTM7DQogICAgICB9DQoNCiAgICAgIC5jbHMtMiB7DQogICAgICAgIGZpbGw6IG5vbmU7DQogICAgICB9DQogICAgPC9zdHlsZT4NCiAgPC9kZWZzPg0KICA8dGl0bGU+c2Nyb2xsYmFyLWJhcnMtaWNvbjwvdGl0bGU+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE1LjI4LDguNWMwLC4yNC0uMS40My0uMjQuNDNIOS42MmMtLjE0LDAtLjI0LS4xOS0uMjQtLjQzVjcuNjVjMC0uMjQuMS0uNDMuMjQtLjQzSDE1Yy4xNCwwLC4yNC4xOS4yNC40M1ptMCwzLjQxYzAsLjI0LS4xLjQzLS4yNC40M0g5LjYyYy0uMTQsMC0uMjQtLjE5LS4yNC0uNDN2LS44NWMwLS4yNC4xLS40My4yNC0uNDNIMTVjLjE0LDAsLjI0LjE5LjI0LjQzWm0wLDMuNDNjMCwuMjQtLjEuNDMtLjI0LjQzSDkuNjJjLS4xNCwwLS4yNC0uMTktLjI0LS40M3YtLjg1YzAtLjI0LjEtLjQzLjI0LS40M0gxNWMuMTQsMCwuMjQuMTkuMjQuNDNaIi8+DQogIDxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+DQo8L3N2Zz4NCg==") no-repeat center;background-size:24px 100%}.h5p-hub .h5p-hub-content-type-list::-webkit-scrollbar-button:vertical{background-size:20px 20px;background-position-x:-4px;background-position-y:-3px;background-color:#5e6978;background-repeat:no-repeat}.h5p-hub .h5p-hub-content-type-list::-webkit-scrollbar-button:vertical:decrement{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQoJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4qIHtmaWxsOiAjY2VkNmUzO30gLnN0MHtmaWxsOm5vbmU7fTwvc3R5bGU+DQoJPHRpdGxlPmFycm93LXVwPC90aXRsZT4NCgk8cGF0aCBkPSJNOCAxMy45bDAuNCAwLjRjMC4zIDAuMyAwLjggMC4zIDEuMSAwbDIuNC0yLjQgMi40IDIuNGMwLjMgMC4zIDAuOCAwLjMgMS4xIDBsMC40LTAuNGMwLjMtMC4zIDAuMy0wLjggMC0xLjEgMCAwIDAgMCAwIDBsLTMuMy0zLjNjLTAuMy0wLjMtMC44LTAuMy0xLjEgMCAwIDAgMCAwIDAgMEw4IDEyLjhDNy43IDEzLjEgNy43IDEzLjUgOCAxMy45IDggMTMuOCA4IDEzLjggOCAxMy45eiIvPg0KCTxyZWN0IGNsYXNzPSJzdDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIvPg0KPC9zdmc+")}.h5p-hub .h5p-hub-content-type-list::-webkit-scrollbar-button:vertical:increment{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHN0eWxlPioge2ZpbGw6ICNjZWQ2ZTM7fSAuY2xzLTEge2ZpbGw6IG5vbmU7fTwvc3R5bGU+DQogIDx0aXRsZT5hcnJvdy1kb3duPC90aXRsZT4NCiAgPHBhdGggZD0iTTE2LDEwLjE1bC0uMzUtLjM1YS43OS43OSwwLDAsMC0xLjA4LDBsLTIuNDMsMi40M0w5LjY5LDkuNzlhLjc4Ljc4LDAsMCwwLTEuMDgsMGwtLjM2LjM2YS43Ni43NiwwLDAsMCwwLDEuMDhsMy4zMiwzLjMyYS43Ni43NiwwLDAsMCwxLjA4LDBMMTYsMTEuMjNhLjc2Ljc2LDAsMCwwLDAtMS4wOFoiLz4NCiAgPHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4NCjwvc3ZnPg0K")}.h5p-hub .h5p-hub-content-type-list:before{content:" ";width:100%;box-shadow:0 0.4em 0.4em -0.2em rgba(79,87,99,0.2) inset,0 -0.4em 0.4em -0.2em rgba(79,87,99,0.2) inset;height:calc(100% - 5.996455834em);position:absolute;pointer-events:none}.h5p-hub .h5p-hub-content-type-list ol{margin:1.25em 0;padding:0;list-style:none}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media{width:100%;padding:0.5em 1.5em 0.5em 1em;box-sizing:border-box;cursor:pointer;overflow:visible;outline:none;margin-top:0}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media:first-child{margin-top:0}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media:hover{background-color:#f5faff}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media:focus{box-shadow:0 0 1px 1px #1a93f4}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media:not(:last-child){border-bottom:1px solid #ececec}.h5p-hub .h5p-hub-content-type-list .h5p-hub-media[tabindex="0"]{background-color:#f5faff}.h5p-hub .h5p-hub-filtering .h5p-hub-content-type-list:before{height:calc(100% - 3.536668484em)}.h5p-hub-no-results{background:no-repeat 4em 0 url(data:image/svg+xml;base64,PHN2ZyBpZD0iTGF5ZXJfMSIgZGF0YS1uYW1lPSJMYXllciAxIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHhtbG5zOnhsaW5rPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5L3hsaW5rIiB2aWV3Qm94PSIwIDAgMjQyLjkxIDk1LjA2Ij4NCiAgPGRlZnM+DQogICAgPHN0eWxlPg0KICAgICAgLmNscy0xIHsNCiAgICAgICAgZmlsbDogbm9uZTsNCiAgICAgIH0NCg0KICAgICAgLmNscy0yIHsNCiAgICAgICAgY2xpcC1wYXRoOiB1cmwoI2NsaXAtcGF0aCk7DQogICAgICB9DQoNCiAgICAgIC5jbHMtMyB7DQogICAgICAgIGZpbGw6ICNjY2NjZDU7DQogICAgICB9DQogICAgPC9zdHlsZT4NCiAgICA8Y2xpcFBhdGggaWQ9ImNsaXAtcGF0aCI+DQogICAgICA8cmVjdCBjbGFzcz0iY2xzLTEiIHg9IjAuMTciIHk9Ii0wLjAyIiB3aWR0aD0iMjQ0LjQiIGhlaWdodD0iOTUuNzgiLz4NCiAgICA8L2NsaXBQYXRoPg0KICA8L2RlZnM+DQogIDx0aXRsZT5uby1yZXN1bHRzPC90aXRsZT4NCiAgPGcgY2xhc3M9ImNscy0yIj4NCiAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMDguOTIsNzguNDVWOTMuNzhhMS4yOCwxLjI4LDAsMCwxLTEuMjgsMS4yOEg4OS43NWExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjcyLjQ4YTEuMjgsMS4yOCwwLDAsMSwxLjI4LTEuMjhoMTEuOTJhMy41NywzLjU3LDAsMCwxLDIuMTguOTFMMTA4LDc2LjI2QTMuNTcsMy41NywwLDAsMSwxMDguOTIsNzguNDVabS0xLjcsMS4yOGgtNS41NGExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjcyLjkxSDkwLjE4VjkzLjM1aDE3Wk05NCw4MS40M2g5LjM3YS40Mi40MiwwLDAsMSwuNDIuNDN2Ljg1YS40Mi40MiwwLDAsMS0uNDIuNDNIOTRhLjQyLjQyLDAsMCwxLS40My0uNDN2LS44NUEuNDIuNDIsMCwwLDEsOTQsODEuNDNabTkuNzksMy44M3YuODVhLjQyLjQyLDAsMCwxLS40Mi40M0g5NGEuNDIuNDIsMCwwLDEtLjQzLS40M3YtLjg1YS40Mi40MiwwLDAsMSwuNDMtLjQzaDkuMzdBLjQyLjQyLDAsMCwxLDEwMy44MSw4NS4yNlptMCwzLjQxdi44NWEuNDIuNDIsMCwwLDEtLjQyLjQzSDk0YS40Mi40MiwwLDAsMS0uNDMtLjQzdi0uODVhLjQyLjQyLDAsMCwxLC40My0uNDNoOS4zN0EuNDIuNDIsMCwwLDEsMTAzLjgxLDg4LjY3Wk0xMDIuMSw3OGg1YTEuNzEsMS43MSwwLDAsMC0uMjktLjU1bC00LjE3LTQuMTdhMS42OSwxLjY5LDAsMCwwLS41NS0uMjlaIi8+DQogICAgPHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMjE4Ljg3LDg1LjE5LDIxNC45NSw5MGE0LjgsNC44LDAsMCwxLTMuNDEsMS42MkgxOTcuMDZhMywzLDAsMCwxLTMtM1Y3NS44OWEzLDMsMCwwLDEsMy0zaDQuMjZhMywzLDAsMCwxLDMsM3YuNDNoNy4yNGEzLDMsMCwwLDEsMywzdjIuMTNoMi41NmEyLjM3LDIuMzcsMCwwLDEsMi4yMSwxLjI2LDIuMDksMi4wOSwwLDAsMSwuMi45QTIuNjIsMi42MiwwLDAsMSwyMTguODcsODUuMTlabS02LjA2LTMuNzdWNzkuM0ExLjI4LDEuMjgsMCwwLDAsMjExLjU0LDc4aC03LjY3YTEuMjgsMS4yOCwwLDAsMS0xLjI4LTEuMjh2LS44NWExLjI4LDEuMjgsMCwwLDAtMS4yOC0xLjI4aC00LjI2YTEuMjgsMS4yOCwwLDAsMC0xLjI4LDEuMjhWODcuMjRMMTk5LjE5LDgzYTQuNzUsNC43NSwwLDAsMSwzLjQxLTEuNjJabTQuMjYsMS43SDIwMi42YTMuMDcsMy4wNywwLDAsMC0yLjA5LDFsLTMuOTEsNC44M2EuOTIuOTIsMCwwLDAtLjI0LjUzYzAsLjM3LjQxLjQ3LjcxLjQ3aDE0LjQ4YTMsMywwLDAsMCwyLjA5LTFsMy45MS00LjgzYS44NS44NSwwLDAsMCwuMjQtLjUyQzIxNy43OCw4My4yMiwyMTcuMzcsODMuMTMsMjE3LjA4LDgzLjEzWiIvPg0KICAgIDxnPg0KICAgICAgPHJlY3QgY2xhc3M9ImNscy0zIiB4PSIxMTcuNzQiIHk9IjgxLjA2IiB3aWR0aD0iOSIgaGVpZ2h0PSI5IiByeD0iMS43IiByeT0iMS43Ii8+DQogICAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xMzEuNDksODEuNDNhLjM1LjM1LDAsMCwwLS4yNi4xMmwtMy40OCwzLjU0djEuMmwzLjQ4LDMuNTRhLjM5LjM5LDAsMCwwLC4yOC4xMmMuMDUsMCwwLDAsLjA2LDBzLjE3LS4yMy4xNy0uNFY4MS44NWMwLS4xNywwLS4zMy0uMTgtLjRTMTMxLjU0LDgxLjQzLDEzMS40OSw4MS40M1oiLz4NCiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEzMy43NCw3OS44NFY5My4wNmgtMTdWNzkuMjFjLTEtLjE3LTItLjM2LTItLjU2VjkzLjc4YTEuNCwxLjQsMCwwLDAsMS40MSwxLjI4SDEzNWMuNzEsMCwuNzEtLjU4LjcxLTEuMjhWNzkuNEMxMzUuNzQsNzkuNTUsMTMzLjc0LDc5LjcxLDEzMy43NCw3OS44NFoiLz4NCiAgICA8L2c+DQogICAgPHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMjAuNDQsNy4yNFYyMi41N2ExLjI4LDEuMjgsMCwwLDEtMS4yOCwxLjI4SDEuMjhBMS4yOCwxLjI4LDAsMCwxLDAsMjIuNTdWMS4yOEExLjI4LDEuMjgsMCwwLDEsMS4yOCwwSDEzLjJhMy41NywzLjU3LDAsMCwxLDIuMTguOTFsNC4xNSw0LjE1QTMuNTcsMy41NywwLDAsMSwyMC40NCw3LjI0Wm0tMS43LDEuMjhIMTMuMmExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjEuN0gxLjdWMjIuMTVoMTdabS0xMy4yLDEuN2g5LjM3YS40Mi40MiwwLDAsMSwuNDMuNDN2Ljg1YS40Mi40MiwwLDAsMS0uNDMuNDNINS41NGEuNDIuNDIsMCwwLDEtLjQzLS40M3YtLjg1QS40Mi40MiwwLDAsMSw1LjU0LDEwLjIyWm05LjgsMy44M3YuODVhLjQyLjQyLDAsMCwxLS40My40M0g1LjU0YS40Mi40MiwwLDAsMS0uNDMtLjQzdi0uODVhLjQyLjQyLDAsMCwxLC40My0uNDNoOS4zN0EuNDIuNDIsMCwwLDEsMTUuMzMsMTQuMDVabTAsMy40MXYuODVhLjQyLjQyLDAsMCwxLS40My40M0g1LjU0YS40Mi40MiwwLDAsMS0uNDMtLjQzdi0uODVBLjQyLjQyLDAsMCwxLDUuNTQsMTdoOS4zN0EuNDIuNDIsMCwwLDEsMTUuMzMsMTcuNDZaTTEzLjYzLDYuODFoNWExLjcsMS43LDAsMCwwLS4yOS0uNTVMMTQuMTcsMi4xYTEuNywxLjcsMCwwLDAtLjU1LS4yOVoiLz4NCiAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik00Ni44NCw3LjI0VjIyLjU3YTEuMjgsMS4yOCwwLDAsMS0xLjI4LDEuMjhIMjcuNjhhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYxLjI4QTEuMjgsMS4yOCwwLDAsMSwyNy42OCwwSDM5LjZhMy41NywzLjU3LDAsMCwxLDIuMTguOTFsNC4xNSw0LjE1QTMuNTcsMy41NywwLDAsMSw0Ni44NCw3LjI0Wm0tMS43LDEuMjhIMzkuNmExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjEuN0gyOC4xVjIyLjE1aDE3Wm0tNi44MSwzLjQxVjE3YTEuNzIsMS43MiwwLDAsMS0xLjcsMS43SDMxLjUxYTEuNzIsMS43MiwwLDAsMS0xLjctMS43VjExLjkyYTEuNzIsMS43MiwwLDAsMSwxLjctMS43aDUuMTFBMS43MiwxLjcyLDAsMCwxLDM4LjMzLDExLjkyWm01LjExLTEuMjh2Ny42N2EuNDQuNDQsMCwwLDEtLjI3LjRsLS4xNiwwYS40NS40NSwwLDAsMS0uMzEtLjEybC0zLjUzLTMuNTR2LTEuMmwzLjUzLTMuNTRhLjQ1LjQ1LDAsMCwxLC4zMS0uMTJsLjE2LDBBLjQ0LjQ0LDAsMCwxLDQzLjQ0LDEwLjY1Wk00MCw2LjgxaDVhMS42OSwxLjY5LDAsMCwwLS4yOS0uNTVMNDAuNTcsMi4xQTEuNywxLjcsMCwwLDAsNDAsMS44MVoiLz4NCiAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik03My4yNCw3LjI0VjIyLjU3QTEuMjgsMS4yOCwwLDAsMSw3MiwyMy44NUg1NC4wOGExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjEuMjhBMS4yOCwxLjI4LDAsMCwxLDU0LjA4LDBINjZhMy41NywzLjU3LDAsMCwxLDIuMTguOTFsNC4xNSw0LjE1QTMuNTcsMy41NywwLDAsMSw3My4yNCw3LjI0Wm0tMS43LDEuMjhINjZhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYxLjdINTQuNVYyMi4xNWgxN1pNNjEuMzIsMTEuNzFWMTlhLjQ0LjQ0LDAsMCwxLS4yNy40bC0uMTYsMGEuNDcuNDcsMCwwLDEtLjMxLS4xMkw1OC4zOCwxN0g1Ni42M2EuNDIuNDIsMCwwLDEtLjQzLS40M1YxNC4wNWEuNDIuNDIsMCwwLDEsLjQzLS40M2gxLjc0bDIuMjEtMi4yMmEuNDMuNDMsMCwwLDEsLjczLjMxWm0zLjEsNi41M2E0LjI1LDQuMjUsMCwwLDAsMC01LjgzLjg1Ljg1LDAsMSwwLTEuMjQsMS4xNywyLjU0LDIuNTQsMCwwLDEsMCwzLjQ5Ljg2Ljg2LDAsMCwwLDAsMS4yMS45Mi45MiwwLDAsMCwuNTkuMjNBLjg5Ljg5LDAsMCwwLDY0LjQyLDE4LjI1Wm0yLjg1LDEuOTJhNy42NSw3LjY1LDAsMCwwLDAtOS42Ni44NS44NSwwLDEsMC0xLjMyLDEuMDgsNiw2LDAsMCwxLDAsNy41MS44NC44NCwwLDAsMCwuMTIsMS4yLjgzLjgzLDAsMCwwLC41My4yQS44NC44NCwwLDAsMCw2Ny4yNywyMC4xNlpNNjYuNDMsNi44MWg1YTEuNjksMS42OSwwLDAsMC0uMjktLjU1TDY3LDIuMWExLjcsMS43LDAsMCwwLS41NS0uMjlaIi8+DQogICAgPHBhdGggY2xhc3M9ImNscy0zIiBkPSJNOTkuNjQsNy4yNFYyMi41N2ExLjI4LDEuMjgsMCwwLDEtMS4yOCwxLjI4SDgwLjQ4YTEuMjgsMS4yOCwwLDAsMS0xLjI4LTEuMjhWMS4yOEExLjI4LDEuMjgsMCwwLDEsODAuNDgsMEg5Mi40YTMuNTcsMy41NywwLDAsMSwyLjE4LjkxbDQuMTUsNC4xNUEzLjU3LDMuNTcsMCwwLDEsOTkuNjQsNy4yNFptLTEuNywxLjI4SDkyLjRhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYxLjdIODAuOVYyMi4xNWgxN1pNODIuNjEsMTEuMDdhMi41NiwyLjU2LDAsMSwxLDIuNTYsMi41NkEyLjU2LDIuNTYsMCwwLDEsODIuNjEsMTEuMDdabTEzLjYzLDkuMzdIODIuNjFWMTcuODlsMi41Ni0yLjU2LDEuNywxLjdMOTIsMTEuOTJsNC4yNiw0LjI2Wk05Mi44Myw2LjgxaDVhMS42OSwxLjY5LDAsMCwwLS4yOS0uNTVMOTMuMzcsMi4xYTEuNywxLjcsMCwwLDAtLjU1LS4yOVoiLz4NCiAgICA8Zz4NCiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTYwLjgxLDQxLjIxVjU2LjU0YTEuMjgsMS4yOCwwLDAsMS0xLjI4LDEuMjhINDEuNjVhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYzNS4yNEExLjI4LDEuMjgsMCwwLDEsNDEuNjUsMzRINTMuNTdhMy41NywzLjU3LDAsMCwxLDIuMTguOTFMNTkuOTEsMzlBMy41NywzLjU3LDAsMCwxLDYwLjgxLDQxLjIxWm0tMS43LDEuMjhINTMuNTdhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYzNS42N0g0Mi4wOFY1Ni4xMWgxN1ptLTEzLjIsMS43aDkuMzdhLjQyLjQyLDAsMCwxLC40My40M3YuODVhLjQyLjQyLDAsMCwxLS40My40M0g0NS45MWEuNDIuNDIsMCwwLDEtLjQzLS40M3YtLjg1QS40Mi40MiwwLDAsMSw0NS45MSw0NC4xOVpNNTUuNyw0OHYuODVhLjQyLjQyLDAsMCwxLS40My40M0g0NS45MWEuNDIuNDIsMCwwLDEtLjQzLS40M1Y0OGEuNDIuNDIsMCwwLDEsLjQzLS40M2g5LjM3QS40Mi40MiwwLDAsMSw1NS43LDQ4Wm0wLDMuNDF2Ljg1YS40Mi40MiwwLDAsMS0uNDMuNDNINDUuOTFhLjQyLjQyLDAsMCwxLS40My0uNDN2LS44NWEuNDIuNDIsMCwwLDEsLjQzLS40M2g5LjM3QS40Mi40MiwwLDAsMSw1NS43LDUxLjQzWk01NCw0MC43OGg1YTEuNywxLjcsMCwwLDAtLjI5LS41NWwtNC4xNy00LjE3YTEuNjksMS42OSwwLDAsMC0uNTUtLjI5WiIvPg0KICAgICAgPHBhdGggY2xhc3M9ImNscy0zIiBkPSJNODcuMjIsNDEuMjFWNTYuNTRhMS4yOCwxLjI4LDAsMCwxLTEuMjgsMS4yOEg2OC4wNWExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjM1LjI0QTEuMjgsMS4yOCwwLDAsMSw2OC4wNSwzNEg4MGEzLjU3LDMuNTcsMCwwLDEsMi4xOC45MUw4Ni4zMSwzOUEzLjU3LDMuNTcsMCwwLDEsODcuMjIsNDEuMjFabS0xLjcsMS4yOEg4MGExLjI4LDEuMjgsMCwwLDEtMS4yOC0xLjI4VjM1LjY3SDY4LjQ4VjU2LjExaDE3Wk03OC43LDQ1Ljg5VjUxQTEuNzIsMS43MiwwLDAsMSw3Nyw1Mi43SDcxLjg4YTEuNzIsMS43MiwwLDAsMS0xLjctMS43VjQ1Ljg5YTEuNzIsMS43MiwwLDAsMSwxLjctMS43SDc3QTEuNzIsMS43MiwwLDAsMSw3OC43LDQ1Ljg5Wm01LjExLTEuMjh2Ny42N2EuNDQuNDQsMCwwLDEtLjI3LjRsLS4xNiwwYS40NC40NCwwLDAsMS0uMzEtLjEyTDc5LjU1LDQ5di0xLjJsMy41My0zLjU0YS40NC40NCwwLDAsMSwuMzEtLjEybC4xNiwwQS40NC40NCwwLDAsMSw4My44MSw0NC42MVpNODAuNCw0MC43OGg1YTEuNjksMS42OSwwLDAsMC0uMjktLjU1bC00LjE3LTQuMTdhMS42OSwxLjY5LDAsMCwwLS41NS0uMjlaIi8+DQogICAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xODUuMTUsNDEuMjFWNTYuNTRhMS4yOCwxLjI4LDAsMCwxLTEuMjgsMS4yOEgxNjZhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYzNS4yNEExLjI4LDEuMjgsMCwwLDEsMTY2LDM0aDExLjkyYTMuNTcsMy41NywwLDAsMSwyLjE4LjkxTDE4NC4yNCwzOUEzLjU3LDMuNTcsMCwwLDEsMTg1LjE1LDQxLjIxWm0tMS43LDEuMjhoLTUuNTRhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYzNS42N0gxNjYuNDFWNTYuMTFoMTdabS0xMC4yMiwzLjE5djcuMjRhLjQ0LjQ0LDAsMCwxLS4yNy40bC0uMTYsMGEuNDcuNDcsMCwwLDEtLjMxLS4xMkwxNzAuMjgsNTFoLTEuNzRhLjQyLjQyLDAsMCwxLS40My0uNDNWNDhhLjQyLjQyLDAsMCwxLC40My0uNDNoMS43NGwyLjIxLTIuMjJhLjQzLjQzLDAsMCwxLC43My4zMVptMy4xLDYuNTNhNC4yNSw0LjI1LDAsMCwwLDAtNS44My44NS44NSwwLDEsMC0xLjI0LDEuMTcsMi41NCwyLjU0LDAsMCwxLDAsMy40OS44Ni44NiwwLDAsMCwwLDEuMjEuOTIuOTIsMCwwLDAsLjU5LjIzQS44OS44OSwwLDAsMCwxNzYuMzMsNTIuMjFabTIuODUsMS45MmE3LjY1LDcuNjUsMCwwLDAsMC05LjY2Ljg1Ljg1LDAsMSwwLTEuMzIsMS4wOCw2LDYsMCwwLDEsMCw3LjUxLjg0Ljg0LDAsMCwwLC4xMiwxLjIuODMuODMsMCwwLDAsLjUzLjJBLjg0Ljg0LDAsMCwwLDE3OS4xNyw1NC4xM1ptLS44NC0xMy4zNWg1YTEuNjksMS42OSwwLDAsMC0uMjktLjU1bC00LjE3LTQuMTdhMS42OSwxLjY5LDAsMCwwLS41NS0uMjlaIi8+DQogICAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0yMTEuNTUsNDEuMjFWNTYuNTRhMS4yOCwxLjI4LDAsMCwxLTEuMjgsMS4yOEgxOTIuMzlhMS4yOCwxLjI4LDAsMCwxLTEuMjgtMS4yOFYzNS4yNEExLjI4LDEuMjgsMCwwLDEsMTkyLjM5LDM0aDExLjkyYTMuNTcsMy41NywwLDAsMSwyLjE4LjkxTDIxMC42NSwzOUEzLjU3LDMuNTcsMCwwLDEsMjExLjU1LDQxLjIxWm0tMS43LDEuMjhoLTUuNTRBMS4yOCwxLjI4LDAsMCwxLDIwMyw0MS4yMVYzNS42N0gxOTIuODFWNTYuMTFoMTdaTTE5NC41Miw0NWEyLjU2LDIuNTYsMCwxLDEsMi41NiwyLjU2QTIuNTYsMi41NiwwLDAsMSwxOTQuNTIsNDVabTEzLjYzLDkuMzdIMTk0LjUyVjUxLjg1bDIuNTYtMi41NiwxLjcsMS43LDUuMTEtNS4xMSw0LjI2LDQuMjZabS0zLjQxLTEzLjYzaDVhMS42OSwxLjY5LDAsMCwwLS4yOS0uNTVsLTQuMTctNC4xN2ExLjY5LDEuNjksMCwwLDAtLjU1LS4yOVoiLz4NCiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTI0Mi4zLDQ4bC0zLjkzLDQuODNBNC44LDQuOCwwLDAsMSwyMzUsNTQuNDFIMjIwLjQ5YTMsMywwLDAsMS0zLTNWMzguNjVhMywzLDAsMCwxLDMtM2g0LjI2YTMsMywwLDAsMSwzLDN2LjQzSDIzNWEzLDMsMCwwLDEsMywzdjIuMTNoMi41NmEyLjM3LDIuMzcsMCwwLDEsMi4yMSwxLjI2LDIuMDgsMi4wOCwwLDAsMSwuMi45QTIuNjIsMi42MiwwLDAsMSwyNDIuMyw0OFptLTYuMDYtMy43N1Y0Mi4wNkExLjI4LDEuMjgsMCwwLDAsMjM1LDQwLjc4SDIyNy4zQTEuMjgsMS4yOCwwLDAsMSwyMjYsMzkuNXYtLjg1YTEuMjgsMS4yOCwwLDAsMC0xLjI4LTEuMjhoLTQuMjZhMS4yOCwxLjI4LDAsMCwwLTEuMjgsMS4yOFY1MGwzLjQxLTQuMTlBNC43NSw0Ljc1LDAsMCwxLDIyNiw0NC4xOVptNC4yNiwxLjdIMjI2YTMuMDcsMy4wNywwLDAsMC0yLjA5LDFMMjIwLDUxLjcxYS45Mi45MiwwLDAsMC0uMjQuNTNjMCwuMzcuNDEuNDcuNzEuNDdIMjM1YTMsMywwLDAsMCwyLjA5LTFMMjQxLDQ2Ljg4YS44NS44NSwwLDAsMCwuMjQtLjUyQzI0MS4yMSw0NiwyNDAuOCw0NS44OSwyNDAuNTEsNDUuODlaIi8+DQogICAgPC9nPg0KICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEwOCwxOC40OGEuNjYuNjYsMCwwLDEsLjE0LS43NEwxMTIsMTNhMywzLDAsMCwxLDIuMDktLjkySDEyOC42Yy42NCwwLC45LjM5LjQ3LjkybC0uMi4yMWMuNjQsMCwxLjI4LjEsMS45MS4xOGEyLjQxLDIuNDEsMCwwLDAsMC0yLDIuNDQsMi40NCwwLDAsMC0yLjIxLTEuMzVoLTIuODZ2LTJhMi43OSwyLjc5LDAsMCwwLTIuNjgtM2gtNy4zMlY0LjY4YTIuNjQsMi42NCwwLDAsMC0yLjktMi42MmgtNC4yNmEyLjU5LDIuNTksMCwwLDAtMi44NCwyLjYyVjE3LjQ2YTIuOTEsMi45MSwwLDAsMCwuNzgsMi4wN0MxMDcsMTkuMTcsMTA3LjQ2LDE4LjgyLDEwOCwxOC40OFptLS4yMy0xNC4zM2MwLS4xOC4xNC0uMDkuODQtLjA5aDQuMjZjLjcxLDAsLjktLjA4LjkuNjJ2Ljg1YTEuODgsMS44OCwwLDAsMCwxLjY1LDEuNTJoNy42N2MuNzEsMCwuNjguMzMuNjgsMXYyaC05LjYyYTYuNDcsNi40NywwLDAsMC00LjA5LDEuN2wtMi4yOSwzLjczWiIvPg0KICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTEzMC44Nyw0Ny43NGEzLjcyLDMuNzIsMCwwLDAtMS43OCwyLjQ1Ljg3Ljg3LDAsMCwxLS43NC44OUgxMjMuOWMtLjQxLDAtLjY3LS42My0uNjctMXYtLjgzYzAtMi4yNCwyLjIyLTQuMTcsMy44NS00LjkxLDEuNDMtLjY1LDItMS4yNiwyLTIuNDRzLTEuMzUtMi0yLjg1LTJhMy43OSwzLjc5LDAsMCwwLTIsLjU0LDEwLjQ4LDEwLjQ4LDAsMCwwLTIsMi4xMy43Ny43NywwLDAsMS0uNTcuMy44Ni44NiwwLDAsMS0uNDYtLjE1bC0zLTIuMzJhLjczLjczLDAsMCwxLS4xOS0xLDkuNCw5LjQsMCwwLDEsOC41OS00LjkzYzQsMCw4LjQxLDMuMTcsOC40MSw3LjQxQzEzNSw0NS40MSwxMzIuNjMsNDYuNzYsMTMwLjg3LDQ3Ljc0Wm0tMS43LDkuNzFhLjc0Ljc0LDAsMCwxLS43NC43NEgxMjRhLjc0Ljc0LDAsMCwxLS43NC0uNzRWNTNhLjc0Ljc0LDAsMCwxLC43NC0uNzRoNC40NGEuNzQuNzQsMCwwLDEsLjc0Ljc0WiIvPg0KICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTE2Ni40OCw4OWExLjkxLDEuOTEsMCwwLDEtMS4zNC0uNTVsLTE5LjA3LTE5LTIuODQsMmEyOS44NCwyOS44NCwwLDEsMSw3LjY4LTcuNjlsLTIsMi44NSwxOSwxOUEyLDIsMCwwLDEsMTY2LjQ4LDg5Wm0tNDAuMTYtNjhhMjUuNzcsMjUuNzcsMCwxLDAsMjUuNzcsMjUuNzdBMjUuOCwyNS44LDAsMCwwLDEyNi4zMiwyMS4wOFoiLz4NCiAgICA8Zz4NCiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTE1MS42OCw4OS40OWEuOTIuOTIsMCwwLDAsLjU5LjIzLjg5Ljg5LDAsMCwwLC42Mi0uMjcsNC4yNSw0LjI1LDAsMCwwLDAtNS44My44NS44NSwwLDEsMC0xLjI0LDEuMTcsMi41NCwyLjU0LDAsMCwxLDAsMy40OUEuODYuODYsMCwwLDAsMTUxLjY4LDg5LjQ5WiIvPg0KICAgICAgPHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMTU1Ljc2LDg2LjU0YTUuOSw1LjksMCwwLDEtMS4zMywzLjc1Ljg0Ljg0LDAsMCwwLC4xMiwxLjIuODMuODMsMCwwLDAsLjUzLjIuODQuODQsMCwwLDAsLjY3LS4zMiw3LjY4LDcuNjgsMCwwLDAsMS43Mi00LjgzczAtLjA3LDAtLjFsLTIuMTYtMi4xNUE1LjkxLDUuOTEsMCwwLDEsMTU1Ljc2LDg2LjU0WiIvPg0KICAgICAgPHBhdGggY2xhc3M9ImNscy0zIiBkPSJNMTU5Ljc0LDg5djQuMDhoLTE3Vjc2LjI1YzAsLjMyLTEsLjYyLTIsLjkxVjkzLjc4YzAsLjcxLDEuMTEsMS4yOCwxLjgxLDEuMjhoMTcuODlhMS4zLDEuMywwLDAsMCwxLjMtMS4yOFY5MC42OFoiLz4NCiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTE0NS4xMSw4OC4wNmgxLjc0bDIuMjEsMi4zMWEuNTQuNTQsMCwwLDAsLjMxLjE2LjQ1LjQ1LDAsMCwwLC4xMywwLC4zOC4zOCwwLDAsMCwuMjQtLjM4VjgyLjkyYS40MS40MSwwLDAsMC0uMjQtLjRjLS4xNi0uMDctLjMyLS40MS0uNDUtLjI5bC0yLjIsMS44NGgtMS43NGMtLjI0LDAtLjM3LDEtLjM3LDEuMnYyLjU2QzE0NC43NCw4OC4wNSwxNDQuODcsODguMDYsMTQ1LjExLDg4LjA2WiIvPg0KICAgIDwvZz4NCiAgICA8Zz4NCiAgICAgIDxwYXRoIGNsYXNzPSJjbHMtMyIgZD0iTTE4Ny41Myw3Ni4yNmwtNC4zMS0zLjcyYy0uNDktLjQ5LTEuNjMtLjQ4LTIuMzQtLjQ4SDE2OWMtLjcxLDAtMS4yMS0uMjgtMS4yMS40MnY3LjIzbDIsMS43VjczLjA2aDEwdjUuMzhjMCwuNzEuNDMuNjIsMS4xNC42Mmg1Ljg2djE0aC0xN3YtLjgxYTkuMTgsOS4xOCwwLDAsMS0yLC42M3YuODlBMS4yMywxLjIzLDAsMCwwLDE2OSw5NS4wNmgxNy44OWMuNzEsMCwxLjktLjU4LDEuOS0xLjI4Vjc4LjQ1QTQsNCwwLDAsMCwxODcuNTMsNzYuMjZabS01Ljc4LjhWNzNjMCwuMDguMjMuMi4zMy4yOUwxODYuMTMsNzdjLjA5LjA5LjEuMDcuMTguMDdaIi8+DQogICAgICA8cGF0aCBjbGFzcz0iY2xzLTMiIGQ9Ik0xODQuNzQsODcuMzlsLTQuMjctNC4yNi01LjEyLDUuMTEtMS43MS0xLjctMS4zOCwxLjIxYTQuNTYsNC41NiwwLDAsMS0xLjUyLDMuMXYuMjJoMTRaIi8+DQogICAgICA8Y2lyY2xlIGNsYXNzPSJjbHMtMyIgY3g9IjE3My42NCIgY3k9IjgyLjI4IiByPSIyLjU2Ii8+DQogICAgPC9nPg0KICA8L2c+DQo8L3N2Zz4NCg==);background-size:16% 100%;padding:0 1em 0.5em 17em;margin-top:2em}.h5p-hub-no-results-title{margin-bottom:0.4em;font-size:1.2em;font-weight:bold}.h5p-hub-no-results-desc{color:#4d4d4d} .h5p-hub .h5p-hub-panel.h5p-section-content-types{max-height:3.0em;overflow:hidden} .h5p-hub-content-type-detail-button-bar{margin:1.666em 0;text-align:right}.h5p-hub-content-type-detail-button-bar .h5p-hub-button-update,.h5p-hub-content-type-detail-button-bar .h5p-hub-button-updating{margin-right:0.6em}.h5p-hub-content-type-detail-button-bar .h5p-hub-button-install:before,.h5p-hub-content-type-detail-button-bar .h5p-hub-button-installing:before,.h5p-hub-content-type-detail-button-bar .h5p-hub-button-update:before,.h5p-hub-content-type-detail-button-bar .h5p-hub-button-updating:before{display:inline-block;margin-right:0.7em;font-weight:normal;font-size:0.9em}.h5p-hub-content-type-detail-button-bar .h5p-hub-button-install:before{font-family:'h5p-hub';content:"";transform:rotate(-90deg)}.h5p-hub-content-type-detail-button-bar .h5p-hub-button-update:before{font-family:'h5p-hub';content:""}.h5p-hub-content-type-detail-button-bar .h5p-hub-button-installing:before,.h5p-hub-content-type-detail-button-bar .h5p-hub-button-updating:before{font-family:'h5p-hub';content:"";-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite} .h5p-hub .h5p-hub-content-type-detail{background-color:white;padding:1.3em;display:inherit;position:absolute;top:0;left:0;visibility:hidden;outline:none;overflow:auto;width:100%;height:100%;box-sizing:border-box;transform:translateX(100%);transition:transform 0.2s ease-out, visibility 0s linear 0.2s;box-shadow:0 0.4em 0.4em -0.2em rgba(79,87,99,0.2) inset,0 -0.4em 0.4em -0.2em rgba(79,87,99,0.2) inset}.h5p-hub .h5p-hub-content-type-detail::-webkit-scrollbar{background-color:#F3F3F3;width:0.750em}.h5p-hub .h5p-hub-content-type-detail::-webkit-scrollbar-thumb{background:#5e6978 url("data:image/svg+xml;base64,PHN2ZyBpZD0ic2Nyb2xsYmFyX2hhbmRsZSIgZGF0YS1uYW1lPSJzY3JvbGxiYXIgaGFuZGxlIiB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogIDxkZWZzPg0KICAgIDxzdHlsZT4NCiAgICAgIC5jbHMtMSB7DQogICAgICAgIGZpbGw6ICNjZWQ2ZTM7DQogICAgICB9DQoNCiAgICAgIC5jbHMtMiB7DQogICAgICAgIGZpbGw6IG5vbmU7DQogICAgICB9DQogICAgPC9zdHlsZT4NCiAgPC9kZWZzPg0KICA8dGl0bGU+c2Nyb2xsYmFyLWJhcnMtaWNvbjwvdGl0bGU+DQogIDxwYXRoIGNsYXNzPSJjbHMtMSIgZD0iTTE1LjI4LDguNWMwLC4yNC0uMS40My0uMjQuNDNIOS42MmMtLjE0LDAtLjI0LS4xOS0uMjQtLjQzVjcuNjVjMC0uMjQuMS0uNDMuMjQtLjQzSDE1Yy4xNCwwLC4yNC4xOS4yNC40M1ptMCwzLjQxYzAsLjI0LS4xLjQzLS4yNC40M0g5LjYyYy0uMTQsMC0uMjQtLjE5LS4yNC0uNDN2LS44NWMwLS4yNC4xLS40My4yNC0uNDNIMTVjLjE0LDAsLjI0LjE5LjI0LjQzWm0wLDMuNDNjMCwuMjQtLjEuNDMtLjI0LjQzSDkuNjJjLS4xNCwwLS4yNC0uMTktLjI0LS40M3YtLjg1YzAtLjI0LjEtLjQzLjI0LS40M0gxNWMuMTQsMCwuMjQuMTkuMjQuNDNaIi8+DQogIDxyZWN0IGNsYXNzPSJjbHMtMiIgd2lkdGg9IjI0IiBoZWlnaHQ9IjI0Ii8+DQo8L3N2Zz4NCg==") no-repeat center;background-size:24px 100%}.h5p-hub .h5p-hub-content-type-detail::-webkit-scrollbar-button:vertical{background-size:20px 20px;background-position-x:-4px;background-position-y:-3px;background-color:#5e6978;background-repeat:no-repeat}.h5p-hub .h5p-hub-content-type-detail::-webkit-scrollbar-button:vertical:decrement{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQoJPHN0eWxlIHR5cGU9InRleHQvY3NzIj4qIHtmaWxsOiAjY2VkNmUzO30gLnN0MHtmaWxsOm5vbmU7fTwvc3R5bGU+DQoJPHRpdGxlPmFycm93LXVwPC90aXRsZT4NCgk8cGF0aCBkPSJNOCAxMy45bDAuNCAwLjRjMC4zIDAuMyAwLjggMC4zIDEuMSAwbDIuNC0yLjQgMi40IDIuNGMwLjMgMC4zIDAuOCAwLjMgMS4xIDBsMC40LTAuNGMwLjMtMC4zIDAuMy0wLjggMC0xLjEgMCAwIDAgMCAwIDBsLTMuMy0zLjNjLTAuMy0wLjMtMC44LTAuMy0xLjEgMCAwIDAgMCAwIDAgMEw4IDEyLjhDNy43IDEzLjEgNy43IDEzLjUgOCAxMy45IDggMTMuOCA4IDEzLjggOCAxMy45eiIvPg0KCTxyZWN0IGNsYXNzPSJzdDAiIHdpZHRoPSIyNCIgaGVpZ2h0PSIyNCIvPg0KPC9zdmc+")}.h5p-hub .h5p-hub-content-type-detail::-webkit-scrollbar-button:vertical:increment{background-image:url("data:image/svg+xml;base64,PHN2ZyB4bWxucz0iaHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmciIHZpZXdCb3g9IjAgMCAyNCAyNCI+DQogICAgPHN0eWxlPioge2ZpbGw6ICNjZWQ2ZTM7fSAuY2xzLTEge2ZpbGw6IG5vbmU7fTwvc3R5bGU+DQogIDx0aXRsZT5hcnJvdy1kb3duPC90aXRsZT4NCiAgPHBhdGggZD0iTTE2LDEwLjE1bC0uMzUtLjM1YS43OS43OSwwLDAsMC0xLjA4LDBsLTIuNDMsMi40M0w5LjY5LDkuNzlhLjc4Ljc4LDAsMCwwLTEuMDgsMGwtLjM2LjM2YS43Ni43NiwwLDAsMCwwLDEuMDhsMy4zMiwzLjMyYS43Ni43NiwwLDAsMCwxLjA4LDBMMTYsMTEuMjNhLjc2Ljc2LDAsMCwwLDAtMS4wOFoiLz4NCiAgPHJlY3QgY2xhc3M9ImNscy0xIiB3aWR0aD0iMjQiIGhlaWdodD0iMjQiLz4NCjwvc3ZnPg0K")}.h5p-hub .h5p-hub-content-type-detail.h5p-hub-show{transform:translateX(0);visibility:visible;transition:transform 0.2s ease-out, visibility 0s linear 0s}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-panel[aria-hidden="false"]{display:none}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-container{max-width:100%;margin-left:auto;margin-right:auto;margin-bottom:1.666em;padding-bottom:1em}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-container:after{content:" ";display:block;clear:both}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-image-wrapper{width:100%;float:left;margin-left:0;margin-right:0}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-title{outline:0}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-text-details{width:100%;float:left;margin-left:0;margin-right:0}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-text-details h2{margin-top:0}@media (min-width: 576px){.h5p-hub .h5p-hub-content-type-detail .h5p-hub-image-wrapper{width:32.20339%;float:left;margin-right:1.69492%}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-text-details{width:66.10169%;float:right;margin-right:0}}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-button-bar{margin:1.666em 0;text-align:right}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-button-bar .h5p-hub-button-update,.h5p-hub .h5p-hub-content-type-detail .h5p-hub-button-bar .h5p-hub-button-updating{margin-right:0.6em}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-button-bar .h5p-hub-button-update:before{font-family:'h5p-hub';content:"";margin-right:0.5em;font-weight:normal;font-size:0.9em}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-back-button{color:#474f5a;font-size:1.3em;display:inline-block;background:transparent;border:none;text-decoration:none;outline:none;transform:rotate(180deg)}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-back-button:hover{color:#000}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-back-button:focus{box-shadow:0 0 1px 1px #1a93f4}.h5p-hub .h5p-hub-content-type-detail .h5p-hub-back-button.h5p-hub-icon-arrow-thick:before{cursor:pointer}.h5p-hub-lightbox-inner.h5p-hub-license{background:#fff;text-align:left;max-height:calc(100% - 5em);width:calc(100% - 5em)}.h5p-hub-lightbox-inner.h5p-hub-license :not(.h5p-hub-loading) .h5p-hub-modal-content{max-height:50em;overflow-y:auto}.h5p-hub-lightbox-inner.h5p-hub-license .h5p-hub-loading:after{font-family:'h5p-hub';content:"";font-size:3em;line-height:1;width:1em;height:1em;padding:.833em;display:block;color:#7c8696;-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;width:1em;margin:0 auto}.h5p-hub-lightbox-inner.h5p-hub-license .h5p-hub-lightbox-close{top:-0.8em;right:-0.8em;color:#333}.h5p-hub-lightbox-inner.h5p-hub-license .h5p-hub-modal-header{font-weight:400;font-size:1.6em;margin-bottom:1em}.h5p-hub-lightbox-inner.h5p-hub-license .h5p-hub-modal-title{font-weight:700} .h5p-hub .h5p-hub-upload-wrapper{padding:1em 2em 2em 2em}.h5p-hub .h5p-hub-upload-wrapper .h5p-hub-message{margin-top:0}.h5p-hub .h5p-hub-upload-wrapper .h5p-hub-upload-throbber{outline:0;height:10em}.h5p-hub .h5p-hub-upload-wrapper .h5p-hub-upload-throbber.h5p-hub-hidden{display:none}.h5p-hub .h5p-hub-upload-wrapper .h5p-hub-upload-throbber:before{font-family:'h5p-hub';content:"";font-size:4em;line-height:1;width:1em;height:1em;padding:.833em;display:block;color:#7c8696;-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;margin:auto}.h5p-hub .h5p-hub-upload-wrapper a:focus{outline:auto}.h5p-hub h1.h5p-hub-upload-instruction-header{font-size:1.25em;margin-top:.833em;margin-bottom:.833em}.h5p-hub p.h5p-hub-upload-instruction-description{font-size:1.042em} .h5p-hub .h5p-hub-upload-form .h5p-hub-input-wrapper{display:inline-block}.h5p-hub .h5p-hub-upload-form .h5p-hub-input-wrapper input[type="file"]{display:none}.h5p-hub .h5p-hub-upload-form [aria-hidden="true"]{display:none}.h5p-hub .h5p-hub-upload-form .h5p-hub-upload-button{background:transparent;color:#697585;border:0.125em solid #697585;margin-left:0.5em}.h5p-hub .h5p-hub-upload-form .h5p-hub-use-button{background:#697585;color:white;margin-left:0.5em}.h5p-hub .h5p-hub-upload-form button[disabled]{opacity:0.5}.h5p-hub .h5p-hub-upload-form .h5p-hub-upload-path{display:inline-block;min-width:14em;padding:10px;padding-left:1.5em;margin-bottom:1em;border:0.125em solid #ced6e3;border-radius:1.375em;outline:0;color:#697585;cursor:pointer}.h5p-hub .h5p-hub-upload-form .h5p-hub-upload-path[disabled]{cursor:default}@media (min-width: 576px){.h5p-hub .h5p-hub-upload-form .h5p-hub-upload-path{width:60%}} .h5p-hub{font-family:'Open Sans', sans-serif;padding-top:1px;padding-bottom:.833em;position:relative;overflow:hidden}.h5p-hub .h5p-hub-panel{border:1px solid #697585;background:#fff}.h5p-hub .h5p-hub-panel.h5p-hub-section-content-types{border-color:#0a78d1}.h5p-hub .h5p-hub-panel.h5p-hub-section-reuse{border-color:#db6f28}.h5p-hub .h5p-hub-panel.h5p-hub-section-upload{border-color:#ced6e3}.h5p-hub .h5p-hub-ssection-content-types.open{max-height:58.65em}.h5p-hub .h5p-hub-button-install [class^="icon-"]{margin-right:.4165em;display:inline-block}.h5p-hub .h5p-hub-button-install .h5p-hub-icon-arrow-thick{transform:rotate(-90deg)}.h5p-hub .h5p-hub-content-type-section{position:relative;overflow:hidden}.h5p-hub .h5p-hub-content-type-section.h5p-hub-height-limit{height:34em}.h5p-hub .h5p-hub-content-type-section-view>.h5p-hub-message{margin:0;padding:0.5em 3.5em 0.7em 2.292em}.h5p-hub .h5p-hub-error .h5p-hub-button.h5p-hub-retry-button{margin:0.5em 0 0.75em;border-width:2px}.h5p-hub .h5p-hub-error .h5p-hub-button.h5p-hub-retry-button:hover,.h5p-hub .h5p-hub-error .h5p-hub-button.h5p-hub-retry-button:active{background-color:#c64750;border-color:#c64750;color:#fff}.h5p-hub .h5p-hub-error .h5p-hub-button.h5p-hub-retry-button:focus{box-shadow:0.06em 0 0.6em 0.1em #c64750}.h5p-hub .h5p-hub-error .h5p-hub-button.h5p-hub-retry-button[disabled]{box-shadow:none;background-color:#c64750;border-color:#c64750;color:#fff;opacity:0.5;padding-left:3em}.h5p-hub .h5p-hub-error .h5p-hub-button.h5p-hub-retry-button[disabled]:before{font-family:'h5p-hub';content:"";font-size:1em;line-height:1;width:1em;height:1em;padding:.833em;display:block;color:#7c8696;-webkit-animation:spin 2s linear infinite;animation:spin 2s linear infinite;position:absolute;margin-left:-2.35em;margin-top:-0.8em;color:#fff}.h5p-hub.h5p-hub-hidden{display:none}.h5p-hub-client-container-using-mouse [role=button]{outline:none} PK*\1d5h5plib/v127/joubel/editor/styles/css/cke-contents.cssnu[@import url(../../ckeditor/contents.css);code{color:#3d3d3d;background:#e0e0e0;border-radius:2px;padding:0 5px}pre>code{background-color:#fafafa;padding:5px;display:block;line-height:normal;border:1px solid #c7c7c7;border-left-width:4px;max-width:100%;white-space:pre;overflow:auto} PK*\><3h5plib/v127/joubel/editor/styles/css/libs/icons.pngnu[PNG  IHDR6WPLTE|||||||||FFFWtRNSaff.Jȍ6弖*,IDATHn0 ]hO ea@CqɧsSG(*_A+C^TT,%*(/ f]YpLK>G~8N'[ƺ,k_A둼,/)Q@y-hpѕǴs׉$m*@Pu}^U%WЊq-_[$h{D,f7Iz .field { margin-bottom: 0; width: 100%; } > .field-name-license { width: 49%; margin-right: 1%; } > .field-name-licenseVersion { width: 49%; margin-left: 1%; } > .field-name-yearFrom { width: 24%; margin-right: 1%; white-space: nowrap; .h5peditor-text { width: 100%; } } > .field-name-yearTo { width: 23%; margin-right: 1%; margin-left: 1%; .h5peditor-text { width: 100%; } } > .field-name-source { width: 49%; margin-left: 1%; } .field-name-title label { justify-content: space-between; .a11y-title-toggle { background: none; border: none; cursor: pointer; &:before { font-family: 'h5p-metadata-icons'; content: "\e905"; margin-right: 0.5em; font-size: 1.5em; vertical-align: middle; } &:focus, &:active, &:hover { border: none; } &:hover .h5p-a11y-title-text { text-decoration: underline; } } } .field-name-a11yTitle { transition: max-height 0.2s, margin 0.2s; overflow: hidden; &.hide { max-height: 0; margin: 0; } &.hidden { display: none; } } } .field.group { > .title { font-weight: 400; background: #F6F6F6; color: #323232; border: solid 1px #ced6e3; border-radius: 0.208em; } &.expanded > .title { border-radius: 0.208em 0.208em 0 0; } > .title:focus { border-color: rgb(77, 144, 254); } > .content { border: solid 1px #ced6e3; border-radius: 0 0 0.208em 0.208em ; padding: 20px; border-top: 0; } } } .h5p-metadata-additional-information { width: 100%; margin-top: 1em; .content.h5peditor-single { min-height: 2em; border: 1px solid #d0d0d1; border-top: none; background: #fff; } .title { font-weight: 400; background: #F6F6F6; color: #323232; border: solid 1px #ced6e3; border-radius: 0.208em; } .title:focus { border-color: rgb(77, 144, 254); } } PK*\kC&666h5plib/v127/joubel/editor/styles/scss/_copy-paste.scssnu[.h5peditor-copypaste-wrap { float: right; } .h5peditor > .h5peditor-copypaste-wrap { /* Make sure buttons are visible when Tutorial and Example is missing */ margin-bottom: 14px; } .h5peditor-copypaste-wrap.hidden { display: none; } .h5peditor-clearfix { clear: both; } .h5peditor-paste-button, .h5peditor-copy-button { border: 1px solid #deeeec; padding: 0.5em 0.75em 0.75em 0.5em; margin-left: 0.5em; border-radius: 0.25em; cursor: pointer; background: #f2faff; line-height: 0.5em; &:hover { border-color: #bbdae8; } &:active { background-color: #deeffb } &.disabled { color: #707070; background-color: #f5f5f5; border-color: #ededed; cursor: not-allowed; } } .h5peditor-copy-button:before, .h5peditor-paste-button:before { font-family: $icon-font-family; margin-right: 5px; font-size: 1.5em; position: relative; top: 0.2em; color: #2372b3; } .h5peditor-copy-button:before { content: "\e90e"; } .h5peditor-paste-button:before { content: "\e910"; } .h5peditor-copy-button.disabled:before, .h5peditor-paste-button.disabled:before { color: #707070; } .h5peditor-copy-button.disabled:before { content: "\e90f"; } .h5peditor-paste-button.disabled:before { content: "\e911"; } .h5p-hub .h5peditor-paste-button { font-family: $font-family; color: #fff; border: solid 1px #9fc8f4; padding: 0 0.75em 0.5em 0.75em; background: transparent; line-height: 1; height: auto; margin-top: 0.675em; margin-right: 0.675em; &:hover { background: #4b5460; border-color: #606a78; } &:active { background: #434b55; } &.disabled { border-color: #30353d; background: #30353d; color: #c2c2c2; } } .h5p-hub .h5peditor-paste-button:before { color: #9fc8f4; } .h5p-hub .h5peditor-paste-button.disabled:before { color: #c3c3c3; } PK*\>552h5plib/v127/joubel/editor/styles/scss/_mixins.scssnu[@mixin button-background($background, $highlight) { background: $background; background-image: linear-gradient($highlight 50%, transparent 50%, transparent); } @mixin field-margin($margin) { margin: $margin 0; &:first-child { margin-top: 0; } &:last-child { margin-bottom: 0; } } PK*\5)$xx6h5plib/v127/joubel/editor/styles/scss/_deprecated.scssnu[@import 'variables'; // This styling is here for backwards compatibility between releases, and can be removed later /* START HFP-409 @deprecated (can be removed after May 2017) Styling that lets old vtabs styling work with the editor upgrade, in Dec 2016 release */ .h5p-vtab-wrapper > .h5p-vtab-forms .h5p-remove:after { color: $form-border-color; } /* END HFP-409 */ PK*\ 6h5plib/v127/joubel/editor/styles/scss/_form-field.scssnu[@import 'variables'; @import 'mixins'; .field { @include field-margin($padding); font-size: $font-size-normal; padding: 0; // Assumes last group is `Behavioural settings`, which should // be grouped with the bottom group `Settings and texts`. .tree > &.group:last-child { margin-bottom: 0; } .fields > &.group { @include field-margin($min-padding); } &.boolean .h5peditor-label { display: inline; } .h5p-editor-image-buttons { float: left; clear: both; } .library { border: 0; } &.importance-high > .h5peditor-label-wrapper > .h5peditor-label { font-size: $font-size-large; color: #356593; } .h5p-dialog-anchor { position: relative; margin: -16px; } } .common-fields-library-wrapper { @include field-margin($padding); border: none; margin: 0; padding: 0; .common-field-legend { display: none; } } PK*\i;HH1h5plib/v127/joubel/editor/styles/scss/_utils.scssnu[ul.list-unstyled { list-style: none; padding-left: 0; margin: 0; }PK*\;ߺBh5plib/v127/joubel/editor/styles/scss/_metadata-author-widget.scssnu[.h5p-metadata-author-widget { display: flex; flex-direction: column; border: solid 1px #ced6e3; border-radius: 0.208em; width: 100%; padding: 1em; margin-top: 1em; .h5p-save-author { border: solid 2px #0a715e; color: #fff; background-color: #0a715e; } .h5p-save-author:hover { border-color: #0d826c; color: #fff; background-color: #0d826c; } .h5p-save-author:active { border-color: #095345; color: #fff; background-color: #095345; } .h5p-author-data { display: flex; flex-direction: row; flex-wrap: nowrap; &>.field { margin-bottom: 0; } } .field-name-name { flex-grow: 1; margin-right: 2%; overflow: hidden; white-space: nowrap; min-width: 49%; } .field-name-role { margin-top: 0; margin-right: 2%; width: 25%; flex-grow: 1; overflow: hidden; white-space: nowrap; } .authorList { margin-top: 1.5em; white-space: nowrap; li { display: inline; margin-right: 0.5em; span { margin-right: 1em; font-style: italic; } } } .h5p-author-list-wrapper { margin-top: 0.5em; ul { margin: 0; padding: 0; } li { display: inline-block; margin-right: 2em; list-style: none; font-weight: bold; font-size: 0.8em; } .h5p-metadata-role { font-style: italic; margin: 0 0.6em; font-weight: normal; font-size: 0.85em; color: #757575; } button { &:after { font-family: 'h5p-metadata-icons'; content: "\e902"; font-size: 1em; position: relative; top: -0.1em; } } } } PK*\&vv6h5plib/v127/joubel/editor/styles/scss/application.scssnu[@import "variables"; @import "mixins"; @import "utils"; @import "form-field"; @import "form-groups"; @import "h5peditor-image-edit"; @import "h5peditor-image-edit-popup"; @import "deprecated"; html, body { margin: 0; padding: 0; color: $text-color; font-family: $font-family; max-width: 960px; position: relative; } a { text-decoration: none; } .offsite { left: -9999px; opacity: 0; position: absolute; top: 0; } .h5peditor { font-size: 16px; .h5p-more-libraries { font-size: 0.875em; margin-top: 0.4em; } .h5peditor-single > .field.library { border: 0; padding: 0; } .cke_dialog_background_cover { width: 100% !important; height: 100% !important; } .errors p, .h5p-errors { color: #da0001; white-space: normal; } textarea { resize: vertical; } .h5p-editor-flex-wrapper { display: flex; flex-direction: row; &.has-button-collapse { align-items: flex-end; margin-bottom: 0.5rem; width: 100%; &.has-label { justify-content: space-between; gap: 0.5rem; } &:not(.has-label) { justify-content: flex-end; } } .h5peditor-button-collapse { align-items: center; background-color:$group-collapse-button-color; background-image:none; border: 3px solid $group-collapse-button-color; border-radius:0.4rem; box-sizing: border-box; display: grid; font-size:0.815rem; font-weight: bold; grid-template-columns: auto 1fr; height: 2.6rem; line-height: 1.2rem; margin: 0; padding: 0 0.6rem 0 0.2rem; .label { white-space: nowrap; } &.collapsed .icon::before { content:"\e942"; font-family:"H5P"; font-size: 1.2rem; font-weight: normal; padding: 0 0.2rem 0 0.2rem; vertical-align: middle; } &:not(.collapsed) .icon::before { content:"\e941"; font-family:"H5P"; font-size: 1.2rem; font-weight: normal; padding: 0 0.2rem 0 0.2rem; vertical-align: middle; } &:hover:not([disabled]) { background-color: $group-collapse-button-color; background-image:none; border: 3px solid $group-collapse-button-color-light; } &.no-label { grid-template-columns: auto; padding: 0 0.2rem; width: auto; .label { display: none; } } } } .h5peditor-label-wrapper { display: flex; flex-direction: row; } .has-important-description { .h5peditor-field-description { display: none; } .h5peditor-label-wrapper { float: left; } } .important-description-visible { .h5peditor-field-important-description { display: block; } .h5peditor-label-wrapper { float: none; } .important-description-show { display: none; } } textarea, .h5peditor-text, .ckeditor { box-shadow: $form-input-box-shadow; box-sizing: border-box; margin: 0; padding: $min-padding; min-height: 40px; border: 1px solid $form-border-color; background: $form-input-color; outline: none; font-size: 16px; word-wrap: break-word; a { text-decoration: underline; } /* The figure around the table */ figure.table { display: table; table-layout: fixed; margin: 0 auto; padding: 0; float: left; /* The actual table */ table { border-collapse: collapse; height: 100%; width: 100%; border-spacing: 0; border-width: 1px; border-color: #494949; td, th { padding: 1px; border-color: #494949; border-bottom-style: solid; } td { border-width: 0.083em; } th { border-width: .167em; } tr:last-child > td { border-bottom-style: none; } } figcaption { background-color: transparent; caption-side: top; color: #333; display: table-caption; font-size: .75em; outline-offset: -1px; padding: .6em; text-align: center; word-break: break-word; } } .table-overflow-protection { clear: both; } &.error { border-color: red; } } // Inside ckeditor, needed for changes to default .ck-content figure.table { float: left; table { border-width: 1px; border-color: #494949; border-style: none; td, th { padding: 1px; border-style: none; border-color: #494949; border-bottom-style: solid; } td { border-width: 0.083em; } th { border-width: .167em; background-color: transparent; } tr:last-child > td { border-bottom-style: none; } } figcaption { background-color: transparent; } } .h5peditor-text, textarea { width: 100%; box-sizing: border-box; &.error { border-color: red; } } // The actual ck editor .ck { a { text-decoration: underline; } .ck-font-size-dropdown .ck-dropdown__panel, .ck-text-fragment-language-dropdown .ck-dropdown__panel { max-height: 20em; overflow-y: scroll; } .ck-fontsize-option .ck-button__label { line-height: normal !important; } .ck-content pre { background: initial; border: initial; border-radius: initial; padding: 0; } } /* Placeholders - need to be on separate lines. If not, the browsers will invalidate them */ textarea:focus::-webkit-input-placeholder, input:focus::-webkit-input-placeholder { color: $form-input-focus-placeholder-color; } textarea:focus:-moz-placeholder, input:focus:-moz-placeholder { color: $form-input-focus-placeholder-color; } textarea:focus::-moz-placeholder, input:focus::-moz-placeholder { color: $form-input-focus-placeholder-color; } textarea:focus:-ms-input-placeholder, input:focus:-ms-input-placeholder { color: $form-input-focus-placeholder-color; } textarea:focus.h5peditor-ckeditor-placeholder, input:focus.h5peditor-ckeditor-placeholder { color: $form-input-focus-placeholder-color; } ::-webkit-input-placeholder { color: $form-input-placeholder-color; } :-moz-placeholder { color: $form-input-placeholder-color; } ::-moz-placeholder { color: $form-input-placeholder-color; } :-ms-input-placeholder { color: $form-input-placeholder-color; } .h5peditor-ckeditor-placeholder { color: $form-input-placeholder-color; } & > select, .h5peditor-language-switcher select, h5peditor-select, .field > select { padding: 10px 30px 10px 8px; font-family: $font-family; font-size: 16px; border: 1px solid $form-border-color; background: $form-input-color url('../../images/down.png') no-repeat; background-position: calc(100% - 10px); box-shadow: $form-input-box-shadow; -moz-appearance: none; -webkit-appearance: none; &:disabled { background-color: #efefef; } } & > select { margin-bottom: 13px; margin-right: 20px; } select::-ms-expand { display: none; } a:focus { outline: none; } textarea:focus, .h5peditor-text:focus { outline: none; background-color: $white; border-color: #53a0ff; } .h5p-ul { padding: 0; margin: 0; list-style: none; .h5p-li { @include field-margin($min-padding); padding: 0; list-style: none; &.placeholder { box-sizing: border-box; background: #e8f2fa; border: dashed 2px #2782d1; } &:hover { text-decoration: none; } &:nth-child(2).moving { margin-top: 0; } &:nth-last-child(2).placeholder { margin-bottom: 0; } } } .dimensions input, .coordinates input, .number input { width: 75px; } .number input[type="range"] { width: 300px; float: left; margin: 7px 8px 0 0; } .h5p-errors { clear: both; } .h5p-add-file { float: left; position: relative; background: transparent; border: 2px dashed #dddddd; color: #dddddd; margin: 0.5em; width: 6em; height: 4.5em; cursor: pointer; outline: none; box-sizing: border-box; -moz-box-sizing: border-box; &:focus, &:hover { color: #999; border-color: #999; } &.hidden { visibility: hidden; } } .h5p-add-file:after { position: absolute; content: "+"; font-size: 2em; line-height: 2.2em; width: 100%; height: 100%; text-align: center; } .h5p-add-dialog { position: absolute; z-index: 1; visibility: hidden; opacity: 0; background: #fff; left: 1em; right: 1em; top: 1em; border: 1px solid #cdcdcd; box-sizing: border-box; -moz-box-sizing: border-box; box-shadow: 0 0 8px #666; transition: visibility 0s 0.2s, opacity 0.2s; &.h5p-open { visibility: visible; opacity: 1; transition: visibility 0s 0s, opacity 0.2s; } .h5p-add-dialog-table { overflow: hidden; .av-tablist { overflow: hidden; margin: 1em 1em 0 1em; } .av-tab { cursor: pointer; float: left; padding: 0.5em 0.75em; border-top: 1px solid #ccc; border-right: 1px solid #ccc; font-weight: bold; font-size: 15px; color: #666; background: #f5f5f5; &:first-child { border-left: 1px solid #ccc; } &.selected { color: #333; background: #fff; } } .av-tabpanel { border: 1px solid #ccc; margin: 0 1em 1em 1em; overflow: hidden; padding: 1em; h3 { margin: 0 0 1em 0; } .h5p-file-drop-upload { width: 90px; margin: 0; } } .h5p-dialog-box { float: left; padding: 0; width: 60%; margin-right: 5%; margin-left: 4%; text-align: left; margin-top: 30px; &:first-child { width: 22%; margin-left: 3%; margin-right: 1%; h3 { text-align: center; } } } h3 { color: #666; font-size: 1em; margin: 1.2em 0; line-height: 1.1em; } .h5peditor-field-description { color: #bbb; } .h5p-file-url-wrapper { background-color: #f5f5f5; border: 1px solid #bbb; padding: 15px 15px 15px 60px; position: relative; &:before { font-family: 'H5P'; position: absolute; left: 0; top: 0.083em; font-size: 3.8em; line-height: 1; } &.video:before { content: "\e904"; color: #dd0505; } &.audio:before { content: "\e913"; color: #747275; } input { border-color: #bbb; text-align: left; padding-left: 20px; } } .h5p-file-drop-upload { position: relative; width: 70%; height: 90px; margin: 0 15%; float: left; background-color: #f5f5f5; text-align: center; cursor: pointer; border: 1px solid #bbb; .h5p-file-drop-upload-inner { border: 2px dashed #bbb; background-color: white; position: absolute; top: 3px; bottom: 3px; left: 3px; right: 3px; &:after { font-family: "H5P"; line-height: 1.4em; font-size: 3.5em; color: #bbb; } &.video:after { content: "\e903"; } &.audio:after { content: "\e914"; } } &:hover, &.over { .h5p-file-drop-upload-inner:after { color: #999; } } } .h5p-or-vertical { float: left; position: relative; width: 5%; height: 250px; } } .h5p-dialog-box { text-align: center; padding: 1em 0.5em; } .h5p-buttons { padding: 0.5em; border-top: 1px solid #cdcdcd; background: #ddd; text-align: right; } } .h5p-or { border-bottom: 1px solid #cdcdcd; padding: 0; margin: 0 1em; text-align: center; height: 0.5em; line-height: 1em; & > span { background: #fff; padding: 0 0.5em; } } .h5p-or-vertical { float: left; position: relative; width: 50px; height: 80px; .h5p-or-vertical-line { position: absolute; margin: 10px 0; left: 49%; top: 0; bottom: 0; width: 1px; background: #ccc; z-index: 1; } .h5p-or-vertical-word-wrapper { text-align: center; height: 18px; position: absolute; left: 0; right: 0; top: 22%; margin-top: -12px; z-index: 2; .h5p-or-vertical-word { color: #999; font-weight: bold; font-size: 18px; padding: 3px; background: #fff; } } } .h5p-file-url { text-align: center; } .h5p-thumbnail { margin: 0.5em; width: 6em; height: 4.5em; display: block; float: left; position: relative; box-shadow: 0 0 10px 0 #666666; border: 1px solid #fff; box-sizing: border-box; -moz-box-sizing: border-box; .h5p-remove { position: absolute; top: 0; right: 0; cursor: pointer; outline: none; width: 1.6em; height: 1.6em; line-height: 1.6em; overflow: hidden; text-indent: -0.4em; padding: 0.065em; opacity: 0.6; } .h5p-remove:hover, .h5p-remove:focus { opacity: 1; } .h5p-remove:after { font-family: $icon-font-family; font-size: 2em; color: #fff; content: "\e890"; opacity: 0.6; } } .h5p-type { position: absolute; width: 100%; height: 100%; font-size: 1.1em; line-height: 4em; display: block; text-align: center; background: #000; color: #fff; cursor: pointer; } .file { position: relative; float: left; margin-bottom: 0; max-width: 100%; &.authorList { float: none; } &.field { float: none; } .thumbnail { display: inline-block; margin: 10px 10px 10px 0; box-shadow: 0 0 10px 0 #666666; border: 1px solid #fff; cursor: pointer; max-width: 100%; min-width: 1em; min-height: 1em; background: $form-input-color url('../../images/transparent-background.png') repeat; } .thumbnail:focus { box-shadow: 0 0 10px 0 #222; } .add { display: inline-block; cursor: pointer; padding: 0.5em 1.5em 0.5em 3em; background: linear-gradient(to bottom, #fbfbfb 0, #f2f2f2 100%); border: 1px solid #d0d0d1; border-radius: 0.25em; color: #222222; font-weight: bold; line-height: normal; &:hover { background: #ededed; } &:focus { box-shadow: 0 0 16px 0 rgba(133,188,255,0.84); } .h5peditor-field-file-upload-text:before { font-family: $icon-font-family; content: "\e902"; line-height: 1; color: #39c943; font-size: 2em; position: absolute; left: 0.3em; top: 0.1em; } } .remove { display: block; position: absolute; top: 7px; right: 7px; cursor: pointer; } .remove:focus:before { opacity: 1; } .remove:before { font-family: $icon-font-family; font-size: 1.4em; color: #fff; content: "\e890"; opacity: 0.6; text-shadow: rgba(black, 0.4) 0 0 4px, rgba(black, 0.4) 0 0 4px, rgba(black, 0.4) 0 0 4px; } .remove:hover { text-decoration: none; } .remove:hover:before { color: #fff; opacity: 1; text-shadow: rgba(black, 0.4) 0 0 4px, rgba(black, 0.4) 0 0 4px, rgba(black, 0.4) 0 0 4px; } img { max-width: 100%; vertical-align: bottom; max-height: 100px; } .h5p-av-row { overflow: auto; margin-bottom: 0.5em; .h5p-thumbnail { display: table-cell; } .h5p-video-quality { display: table-cell; overflow: hidden; width: 10000px; padding-left: 1em; input.h5peditor-text { width: 100%; } } } .h5p-av-cell { overflow: auto; float: left; } } .video .file, .audio .file { position: static; overflow: visible; .thumbnail, .add { float: left; } .add { margin-top: 8px; } .thumbnail { overflow: visible; position: relative; cursor: auto; } .remove { top: -3px; right: -5px; } .type { padding: 16px 8px 4px; background: #000; color: #fff; font-size: 10px; } .h5peditor-uploading { float: left; margin: 0.5em; } } .libwrap { margin-top: $padding; &.no-margin, &:empty { margin-top: 0; } } input[type="checkbox"] { margin: 4px 4px 4px 0; vertical-align: bottom; } .moving { position: absolute; z-index: 1; opacity: 0.8; -webkit-transform: translateZ(0); .h5peditor-label { cursor: grabbing; cursor: -moz-grabbing; cursor: -webkit-grabbing; } } .h5peditor-uploading, .h5peditor-loading { padding-top: 10px; padding-bottom: 6px; font-size: 14px; } .h5peditor-loading { padding: 0.875em 0 1em 3.25em; font-style: italic; } .h5p-copyright-button { border-radius: 0.25em; height: 30px; background: linear-gradient(to bottom, #fff 0, #f2f2f2 100%); border: 1px solid $form-border-color; color: $black; font-size: $font-size-small; line-height: $form-item-height-small; padding-right: $padding; padding-left: 0; clear: both; font-weight: normal; &:before { font-family: $icon-font-family; content: "\e88f"; color: #666; padding: 0 0.25em 0 0.25em; vertical-align: middle; font-size: 1.5em; line-height: 0.9; } &:hover:not([disabled]) { background: linear-gradient(to bottom, #fff 0, #d0d0d1 100%); text-decoration: none; border-color: #999; } } .h5p-copyright-button:focus { box-shadow: 0 0 16px 0 rgba(133, 188, 255, 0.84); } /* Copyright button for video & audio */ .field.file > .h5p-copyright-button, .field.video > .h5p-copyright-button, .field.audio > .h5p-copyright-button { float: left; } .h5p-editor-dialog { position: absolute; z-index: 2; margin: 5.5em 0 1em; visibility: hidden; opacity: 0; height: 0; overflow: hidden; background: #fff; box-shadow: 0 0 8px #666; transition: visibility 0s 0.2s, height 0s 0.2s, opacity 0.2s, margin-top 0.2s; &.h5p-open { margin-top: 3.5em; visibility: visible; opacity: 1; height: auto; transition: visibility 0s 0s, height 0s 0s, opacity 0.2s, margin-top 0.2s; } & > .field { margin: 0; border: 0; box-shadow: none; } .content { border: none; background: $white; .h5peditor-label { font-size: $font-size-large; font-weight: 600; } } .h5p-close { color: #494949; &:before { font-size: 2em; right: -0.125em; top: 0; position: absolute; z-index: 1; font-family: $icon-font-family; content: "\e894"; line-height: 1em; transition: scale 0.2s; } &:hover:before { scale: 1.1, 1.1; } } } .h5p-li > .content > .library { border: 0; padding: 0; } } .ck-powered-by-balloon { display: none !important; } .h5p-editor-dialog.h5p-dialog-wide { width: 90%; border-radius: 0.208em; } /* Placed this outside of .h5peditor context above. Don't want it to be more specific than neccessary (because of overriding) */ .h5peditor-button-textual { border-radius: 0.25em; @include button-background( $form-item-importance-medium-background, $form-item-importance-medium-background-highlight); display: inline-block; width: auto; margin: $min-padding 0 0 0; padding: 0 $padding; box-sizing: border-box; height: $form-item-height-normal; border: 1px solid $form-border-color; font-size: $font-size-normal; font-family: $font-family; line-height: $form-item-height-normal; color: $white; cursor: pointer; font-weight: 600; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; &:focus { box-shadow: 0 0 16px 0 rgba(133, 188, 255, 0.84); } &:before, &:after { color: $white; } .h5p-editing-image-button:before { font-family: $icon-font-family; content: "\e900"; color: #666; padding-right: 0.25em; vertical-align: middle; font-size: 1.5em; line-height: 0.9; } &:hover:not([disabled]) { @include button-background( $form-item-importance-medium-background-hover, $form-item-importance-medium-background-hover-highlight); text-decoration: none; } &.importance-high { @include button-background( $form-item-importance-high-background, $form-item-importance-high-background-highlight); border-color: $form-item-importance-high-border-color; text-transform: uppercase; height: $form-item-height-large; line-height: $form-item-height-large; &:hover:not([disabled]) { @include button-background( $form-item-importance-high-background-hover, $form-item-importance-high-background-hover-highlight); border-color: $form-item-importance-high-background-hover; } } &.importance-low { @include button-background( $form-item-importance-low-background, $form-item-importance-low-background-highlight); border-color: $form-item-importance-low-border-color; color: $black; &:before, &:after { color: $black; } &:hover:not([disabled]) { @include button-background( $form-item-importance-low-background-hover, $form-item-importance-low-background-hover-highlight); border-color: $form-item-importance-low-background-hover; } } &[disabled], &[aria-disabled="true"] { background: #f5f5f5; color: #707171; border-color: #eeeeee; cursor: not-allowed; &:before { font-family: $icon-font-family; content: "\e912"; color: #707171; margin-right: 0.5em; vertical-align: top; } } } .h5peditor-field-description, .h5p-help-text { font-size: 12px; margin-top: 0.3em; margin-bottom: 1em; font-weight: 500; color: #434446; line-height: 15px; letter-spacing: 0.5px; } .h5peditor-field-important-description { position: relative; padding: 1.5em 2.2em 2em 2.2em; font-size: 0.9em; margin: 0 0 20px 0; border: 1px solid #ffde78; background-color: #f9f9d8; color: #000; display: none; .important-description-close { position: absolute; font-size: 0.9em; line-height: 2em; right: 1.5em; top: 1em; user-select: none; cursor: pointer; &:before { font-family: $icon-font-family; content: "\e894"; vertical-align: top; font-size: 1.6em; } } .h5p-info-icon { font-size: 0.75em; &:before { font-family: $icon-font-family; content: "\e909"; font-size: 2.3em; line-height: 0.94em; margin-left: -0.3em; vertical-align: middle; } } .important-description-title { font-weight: bold; font-size: 1.2em; vertical-align: bottom; } .important-description-content { ul { padding: 0; line-height: 2em; margin-top: 20px; li { line-height: 1.8em; margin-left: 1.5em; } } } .important-description-example { border: 1px solid #bbde98; background-color: #d9fac3; display: flex; margin-top: 20px; .important-description-example-title { padding: 15px; font-weight: bold; } .important-description-example-text { padding: 15px; width: 100%; background-color: #f6fef1; } } } .h5peditor-form { position: relative; background: $form-background; border: 1px solid $form-border-color; &.h5peditor-form-manager { > .tree, > .common, > .field { max-width: 918px; margin: 20px auto; padding: 0 20px; } } &.h5peditor-semi-fullscreen { margin: 0; position: fixed; overflow-y: scroll; margin-top: 40px; padding-bottom: 40px; box-sizing: border-box; background: #fff; height: calc(100% - 40px); } } .h5peditor-label { display: block; margin-bottom: 6px; font-weight: 600; font-size: $font-size-normal; color: $form-label; } .h5peditor-label-button { background: transparent; border: none; color: $form-label; cursor: pointer; display: flex; flex-direction: row; font-family: inherit; font-weight: 600; font-size: $font-size-normal; padding: 0 0 0 10px; text-align: left; &.collapsed .icon::before { content: "\e566"; font-family: $icon-font-family; margin-right: calc($min-padding / 2); } &:not(.collapsed) .icon::before { content: "\e565"; font-family: $icon-font-family; margin-right: calc($min-padding / 2); } } #h5peditor-uploader { position: absolute; width: 1px; height: 1px; top: -1px; border: 0; overflow: hidden; } @import "tutorial-and-example-links"; .h5peditor-widget-select { display: flex; flex-direction: row-reverse; justify-content: end; overflow: hidden; margin: 0 0 -1px; padding: 0; list-style: none; } .h5peditor-widget-option { border: 1px solid #ccc; margin-left: 0.5em; padding: 0.6em 1em; color: #0E1A25; font-size: 0.875em; background: #f5f5f5; line-height: 1.285714286em; cursor: pointer; outline: none; } .h5peditor-widget-option:hover { color: #000; } .h5peditor-widget-option:active { color: #8e636a; /* Pink chocolate */ } .h5peditor-widget-active { background: #fff; line-height: 1.357142857em; border-bottom: 0; } .h5peditor-widgets > .h5peditor-widget-wrapper { border: 1px solid #ccc; margin: 0 0 0.25em; padding: 0.5em; } .h5peditor-widgets > .h5peditor-label, .h5peditor-widgets > .h5peditor-label-button { float: left; margin-top: 5px; } .h5p-editor-iframe { margin-bottom: 1em; } .h5peditor-required:after { content: "*"; color: #da0001; margin-left: 0.2em; position: relative; top: -0.2em; } /* Help CKEditor blend into the H5PEditor */ .h5peditor .cke_bottom, .h5peditor .cke_top { background: #d0d0d1; } .h5peditor .cke_chrome { border: 1px solid #f5f5f5; background: #d0d0d1; } .h5peditor .cke_contents, .h5peditor .cke_toolgroup, .h5peditor .cke_combo_button { border: 1px solid #f5f5f5; } /* The show important description button */ .important-description-show { background: #f3d55a; padding: 0.2em 0.5em 0.2em 1.7em; margin-bottom: 0.5em; font-size: 0.9em; cursor: pointer; float: right; position: relative; line-height: normal; font-style: italic; font-weight: bold; &:before { font-family: $icon-font-family; font-style: normal; font-weight: normal; content: "\e909"; font-size: 1.8em; position: absolute; left: 0em; top: 0em; line-height: 0.85em; vertical-align: top; } } .important-description-clear-right { display: block; clear: right; } .h5peditor fieldset.common-fields-library-wrapper { width: 100%; padding: 0 1em 1em; box-sizing: border-box; height: 20px; border: solid 1px #e2e5ee; border-radius: 4px; margin-bottom: 1em; & > * { display: none; } & > legend { display: block; cursor: pointer; outline: none; color: #363b42; background-color: #fff; padding: 10px; font-weight: bold; font-size: 0.875em; &:before { font-family: "H5P"; content: "\e566"; margin-right: 0.5em; } &:focus:before { outline: 1px dotted #666; } } &.expanded { height: auto; & > * { display: block; } & > legend:before { content: "\e565"; } } } @import "metadata-form"; @import "metadata-popup"; @import "metadata-changelog-widget"; @import "metadata-author-widget"; @import "copy-paste"; @import "fullscreen-bar"; .h5peditor .h5peditor-language-switcher { float: right; white-space: nowrap; margin-bottom: 1em; .language-label { padding: 0 10px; font-size: 15px; } select { padding: 6px 30px 6px 8px; font-size: 15px; } } .h5peditor-language-notice { display: none; clear: both; font-size: 14px; background: #dcf6ff; color: #295b7a; padding: 10px 20px 10px 40px; margin: 1em 0; line-height: 1.5; position: relative; &:before { font-family: h5p; content: "\e90c"; position: absolute; left: 15px; font-size: 1.125em; } &.show { display: block; } .first { font-weight: bold; } a { text-decoration: underline; } } .h5p-loader__wrapper { width: 100%; height: 100%; flex: 1; display: flex; align-items: center; padding: 10px; min-width: 180px; .h5p-loader__icon { border: 8px solid #d0cfd4; border-bottom-color: #554e4a; border-radius: 50%; width: 40px; height: 40px; animation: rotation linear 1s infinite; margin: 0 auto; } } @keyframes rotation { 0% { transform: rotate(0deg); } 100% { transform: rotate(360deg); } } .h5p-sr-only { position: absolute; width: 1px; height: 1px; padding: 0; margin: -1px; overflow: hidden; clip: rect(0, 0, 0, 0); white-space: nowrap; border-width: 0; } PK*\#ggFh5plib/v127/joubel/editor/styles/scss/_tutorial-and-example-links.scssnu[$h5p-tutorial-url-label-color: #415702; $h5p-tutorial-icon-color: #eaffab; $h5p-tutorial-icon-bg-color: #749e00; $h5p-example-url-label-color: #422447; $h5p-example-icon-color: #f8d4ff; $h5p-example-icon-bg-color: #8f4f9c; $h5p-tutorial-icon-diameter: 2rem; @mixin h5p-tutorial-focus-shadow() { box-shadow: 0px 0px 5px rgba(22,52,247,1); } .h5p-tutorial-url, .h5p-example-url { font-size: 1em; display: inline-flex; align-items: center; line-height: 1; margin-right: 1em; margin-bottom: 0.5em; margin-left: 0.25em; height: $h5p-tutorial-icon-diameter; border-radius: calc($h5p-tutorial-icon-diameter / 2); &:focus { @include h5p-tutorial-focus-shadow; } &:active { border-color: #1C70BA; } &::before { font-family: $icon-font-family; font-size: 1.25em; border-radius: 50%; width: $h5p-tutorial-icon-diameter; height: $h5p-tutorial-icon-diameter; position: absolute; display: flex; justify-content: center; align-items: center; } .h5p-tutorial-url-label, .h5p-example-url-label { font-style: italic; font-weight: bold; text-decoration: underline; margin: 0.25em 0.5em; margin-left: $h5p-tutorial-icon-diameter; padding-left: 0.5em; padding-right: 1em; } } .h5p-tutorial-url { &:active, &:hover { background-color: $h5p-tutorial-icon-color; } &::before { content: "\e93e"; color: $h5p-tutorial-icon-color; background-color: $h5p-tutorial-icon-bg-color; } .h5p-tutorial-url-label { color: $h5p-tutorial-url-label-color; } } .h5p-example-url { &:active, &:hover { background-color: $h5p-example-icon-color; } &::before { content: "\e93d"; font-size: 1em; color: $h5p-example-icon-color; background-color: $h5p-example-icon-bg-color; } .h5p-example-url-label { color: $h5p-example-url-label-color; } } PK*\B~@h5plib/v127/joubel/editor/styles/scss/_h5peditor-image-edit.scssnu[@import 'variables'; .h5peditor { .h5p-editing-image-button { background: linear-gradient(to bottom, #fff 0, #f2f2f2 100%); font-size: $font-size-small; color: $black; line-height: $form-item-height-small; padding-right: $padding; margin-right: 0.5em; height: 30px; padding-left: 0; font-weight: normal; &:hover:not([disabled]) { background: linear-gradient(to bottom, #fff 0, #d0d0d1 100%); border-color: #999; } } .h5p-editing-image-button:before { font-family: $icon-font-family; content: "\e900"; color: #666; padding-right: 0.3em; padding-left: 0.45em; vertical-align: middle; font-size: 1.5em; line-height: 0.9; } .h5p-editing-image-button.loading:before { content: "\e901"; } .h5p-editing-image-button.hidden, .h5p-copyright-button.hidden { display: none !important; } .ui-dialog .h5p-editing-image-button, .ui-dialog .h5p-copyright-button { padding-left: 0.5em; } } PK*\YYEh5plib/v127/joubel/editor/styles/scss/_metadata-changelog-widget.scssnu[.h5p-metadata-changelog { width: 100%; } .h5p-metadata-changelog .field-name-change { &.expanded .content { display: flex; flex-wrap: wrap; } .field-name-date { width: 49%; margin-bottom: 0.5em; margin-right: 1%; margin-top: 0; span { width: 100%; } } .field-name-author { width: 49%; margin-bottom: 0.5em; margin-left: 1%; margin-top: 0; } .field-name-log { width: 100%; } .h5p-add-author:before { content: "+"; margin-right: 0.7em; } .h5p-cancel { margin-right: 10px; } .h5p-metadata-changelog-buttons { width: 100%; } .h5p-metadata-logged-changes { width: 100%; margin-top: 1em; // Hide the change log table while editing &.editing { display: none; } .h5peditor-field-description { margin-bottom: 0; } } .h5p-metadata-log-wrapper { margin-top: 1em; border: solid 1px #ced6e3; border-radius: 0.208em; max-height: 15.917rem; overflow-y: auto; padding: 0 0.5em; } .h5p-metadata-log { display: flex; margin-top: 0.5em; padding-bottom: 0.5em; .h5p-metadata-delete { margin-left: 2em; &:after { font-family: 'h5p-metadata-icons'; content: "\e902"; font-size: 1.2em; } } .h5p-metadata-edit { &:after { font-family: 'h5p-metadata-icons'; content: "\e904"; font-size: 1.2em; } } } .h5p-metadata-log-buttons { min-width: 3em; line-height: 2.5; } .h5p-metadata-log:not(:last-child) { border-bottom: solid 1px #ced6e3; } .h5p-metadata-log-date { min-width: 25%; font-size: 0.85em; font-style: italic; line-height: 2.5; } .h5p-metadata-description-wrapper { flex-grow: 1; font-size: 0.85em; font-style: italic; } .h5p-metadata-description-wrapper { font-weight: bolder; } .h5p-metadata-log-author { font-weight: normal; } .h5p-metadata-new-log-message { width: 100%; background: #C5E7E1; padding: 0.5em; margin-bottom: 1em; color: #0a715e; } } PK*\Jާ Fh5plib/v127/joubel/editor/styles/scss/_h5peditor-image-edit-popup.scssnu[body.h5p-editor-image-popup { position: relative; } .h5p-editing-image-popup-background { position: fixed; top: 0; left: 0; width: 100%; height: 100%; background: rgba(0,0,0,0.8); padding: 3em 1em; box-sizing: border-box; z-index: 102; } #darkroom-icons { top:0; left:0; } .h5p-editing-image-popup-background.hidden { display: none; } .h5p-editing-image-popup { display: inline-block; position: relative; top: 0; background: #fff; -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } .h5p-editing-image-header { padding: 1em 0.75em; } .h5p-editing-image { max-height:100%; max-width:100%; } .h5p-editing-image.hidden { display: none; } .h5p-editing-image-popup { .darkroom-toolbar { position: relative; -webkit-border-radius:0; -moz-border-radius:0; border-radius:0; top:0; } .darkroom-toolbar:before { content: initial; } .darkroom-image-container { padding: 32px 2em; } .darkroom-image-container .canvas-container { box-shadow: 0 0 8px 3px rgba(0, 0, 0, 0.6); margin: auto; } } .h5p-editing-image-header-title { display: inline-block; font-size: 1.25em; } .h5p-editing-image-header-buttons { display: inline-block; float: right; } .h5p-editing-image-loading { padding: 1em; } .h5p-editing-image-loading.hidden { display: none; } .h5p-editing-image-editing-container { background: #666; } .h5p-editing-image-header-buttons { button { padding: 0.5em 1.75em; margin: 0 0 0 1em; border: 1px solid #ccc; border-radius: 0.25em; color: #333; cursor: pointer; background: #f2f2f2; background: -webkit-linear-gradient(top,#fff 0,#f2f2f2 100%); background: -ms-linear-gradient(top,#fff 0,#f2f2f2 100%); } button:hover { background: #ededed; } .h5p-done { color: #fff; border-color: #20588F; background: #3673B5; background: -webkit-linear-gradient(top,#5A94D3 0,#3673B5 100%); background: -ms-linear-gradient(top,#5A94D3 0,#3673B5 100%); } .h5p-done:hover { background: #3275bc; background: -webkit-linear-gradient(top,#3275bc 0,#285585 100%); background: -ms-linear-gradient(top,#3275bc 0,#285585 100%); } .h5p-remove { background: none; border: none; color: #a00; padding-right: 0; padding-left: 0; border-radius: 0; } .h5p-remove:hover { background: none; color: #e40000; } } PK*\le005h5plib/v127/joubel/editor/styles/scss/_variables.scssnu[// General editor $black: #212121; $white: #FFFFFF; $blue: #285c8b; $text-color: $black; $font-family: 'Open Sans', sans-serif; $icon-font-family: 'H5P'; $font-size-large: 18px; $font-size-normal: 16px; $font-size-small: 14px; $min-padding: 10px; $padding: 20px; // Form $form-background: #fcfcfc; $form-border-color: #d0d0d1; $form-content-background: $white; $form-input-color: $white; $form-input-placeholder-color: #858585; $form-input-focus-placeholder-color: #fff; $form-input-box-shadow: inset 0px 0px 5px rgba(0, 0, 0, 0.12); $form-item-importance-high-background: #2579C6; $form-item-importance-high-background-highlight: #3080c9; $form-item-importance-high-border-color: #1f67a8; $form-item-importance-high-background-hover: #1f67a8; $form-item-importance-high-background-hover-highlight: #2a6fac; $form-item-importance-medium-background: #747275; $form-item-importance-medium-background-highlight: #7b797c; $form-item-importance-medium-border-color: #636164; $form-item-importance-medium-background-hover: #636164; $form-item-importance-medium-background-hover-highlight: #6b696c; $form-item-importance-low-background: #f5f5f5; $form-item-importance-low-background-highlight: #eeeeef; $form-item-importance-low-border-color: #d0d0d1; $form-item-importance-low-background-hover: #deddde; $form-item-importance-low-background-hover-highlight: #deddde; $form-item-height-large: 42px; // 44px total with border $form-item-height-normal: 38px; // 40px total with border $form-item-height-small: 28px; // 30px total with border $form-item-buttons-width-large: 74px; $form-item-buttons-width-normal: 54px; $form-item-buttons-width-small: 54px; // Label $form-label: #454347; $form-label-importance-high: #356593; // Group collapse button $group-collapse-button-color: #228380; $group-collapse-button-color-light: #4dc2bf; PK*\A wWW7h5plib/v127/joubel/editor/styles/scss/cke-contents.scssnu[@import "../../ckeditor/contents.css"; code { color: #3d3d3d; background: #e0e0e0; border-radius: 2px; padding: 0 5px; } pre > code { background-color: #fafafa; padding: 5px; display: block; line-height: normal; border: 1px solid #c7c7c7; border-left-width: 4px; max-width: 100%; white-space: pre; overflow: auto; } PK*\6;P:h5plib/v127/joubel/editor/styles/scss/_fullscreen-bar.scssnu[@font-face { font-family: 'h5p-fullscreen-bar'; src: url('../css/fonts/h5p-fullscreen-bar.eot?p850ul'); src: url('../css/fonts/h5p-fullscreen-bar.eot?p850ul#iefix') format('embedded-opentype'), url('../css/fonts/h5p-fullscreen-bar.ttf?p850ul') format('truetype'), url('../css/fonts/h5p-fullscreen-bar.woff?p850ul') format('woff'), url('../css/fonts/h5p-fullscreen-bar.svg?p850ul#h5p') format('svg'); font-weight: normal; font-style: normal; } .h5peditor-form-manager-head { background: #f5f5f5; color: #414141; border-bottom: 1px solid #dfdfdf; height: 41px; line-height: 40px; box-sizing: border-box; position: relative; display: flex; z-index: 3; justify-content: space-between; align-items: flex-start; box-shadow: 0px 2px 2px rgba(128,128,128,0.15); padding: 0 1em 0 0.5em; } .h5peditor-form-manager-button { background: transparent; padding: 0; border: 0; cursor: pointer; color: #414141; position: relative; white-space: nowrap; line-height: normal; } .h5peditor-form-manager-button-inner { display: block; outline: none; } .h5peditor-form-manager-breadcrumb { display: flex; min-width: 0; flex-grow: 1; } .h5peditor-form-manager-proceed { display: none; background: #186df7; color: #fff; font-size: 14px; font-weight: bold; font-family: Open Sans, sans-serif; border-radius: 2px; margin-right: 5px; margin-top: 5px; padding: 5px 10px; &:hover { background: #20588f; } } .h5peditor-form-manager-fullscreen { width: 24px; height: 24px; font-size: 20px; margin-top: 9px; margin-left: 0.25em; .h5peditor-form-manager-button-inner:before { font-family: 'h5p-fullscreen-bar'; content: '\e929'; } &:after { visibility: hidden; position: absolute; top: 120%; right: -10%; z-index: 3; padding: 0.25em 0.75em; background: #212121; color: #fff; white-space: nowrap; font-size: 14px; box-shadow: 0 0 0.5em #858585; text-indent: 0; font-weight: normal; pointer-events: none; outline: none; line-height: normal; content: attr(aria-label); } &:hover:after, &:focus:after { visibility: visible; } } .h5peditor-semi-fullscreen { .h5peditor-form-manager-fullscreen .h5peditor-form-manager-button-inner:before { content: "\e92a"; } .h5peditor-form-manager-proceed { display: block; } .h5peditor-form-manager-head { position: fixed; top: 0; left: 0; right: 0; z-index: 2; } } .form-manager-exit.form-manager-fullscreen .h5peditor-form-manager-button-inner:before { content: "\f066"; } .h5peditor-form-manager-title { position: relative; min-width: 20px; font-weight: bold; font-size: 14px; /* Icons for content types */ &:before { font-family: 'h5p-fullscreen-bar'; content: "\e928"; font-size: 1.2em; position: relative; top: 0.1em; margin-right: 0.25em; speak: none; font-style: normal; font-weight: normal; font-variant: normal; text-transform: none; line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } &.dragtext:before { content: "\e600"; } &.markthewords:before { content: "\e601"; } &.multichoice:before { content: "\e603"; } &.interactivevideo:before { content: "\e900"; } &.audio:before { content: "\e901"; } &.truefalse:before { content: "\e902"; } &.dialogcards:before { content: "\e903"; } &.questionnaire:before { content: "\e904"; } &.coursepresentation:before { content: "\e923"; } &.dragquestion:before { content: "\e991"; } &.summary:before { content: "\e992"; } &.singlechoiceset:before { content: "\e993"; } &.blanks:before { content: "\e994"; } } /* Makes metadata popup behave good in fullscreen */ .h5peditor-semi-fullscreen + .h5p-metadata-popup-overlay { position: fixed; .h5p-metadata-wrapper { margin-top: 20px !important; } } PK*\V"":h5plib/v127/joubel/editor/styles/scss/_metadata-popup.scssnu[.h5p-metadata-popup-overlay { position: absolute; top: 0; left: 0; right: 0; bottom: 0; background-color: rgba(0, 0, 0, 0.85); // Need to be higer than the different z-indexes in the custom editors // Like eg popups in CP, DnD and IV z-index: 101; text-align: center; } PK*\6b!!7h5plib/v127/joubel/editor/styles/scss/_form-groups.scssnu[@import 'variables'; @import 'mixins'; %title-bar-base { visibility: inherit; cursor: pointer; } %title-bar-importance-high { background: $form-item-importance-high-background; border: 1px solid $form-item-importance-high-border-color; height: $form-item-height-large; } %title-bar-text-importance-high { font-size: $font-size-normal; font-weight: 600; line-height: $form-item-height-large; // Fix white text on dark background blockiness -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } %title-bar-importance-medium { background: $form-item-importance-medium-background; border: 1px solid $form-item-importance-medium-border-color; height: $form-item-height-normal; } %title-bar-text-importance-medium { font-size: $font-size-normal; font-weight: 600; color: $white; line-height: $form-item-height-normal; // Fix white text on dark background blockiness -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; } %title-bar-importance-low { background: $form-item-importance-low-background; height: $form-item-height-normal; border: 1px solid $form-border-color; } %title-bar-text-importance-low { font-size: $font-size-normal; font-weight: 400; color: $text-color; line-height: $form-item-height-normal; } .group { border: none; & > .title { @extend %title-bar-base; @extend %title-bar-importance-medium; @extend %title-bar-text-importance-medium; padding: 0 $min-padding; outline: none; } & > .content { position: relative; display: none; margin: 0; padding: $padding; border: 1px solid $form-border-color; border-top: none; background: $form-content-background; } &.importance-high > .title { @extend %title-bar-importance-high; @extend %title-bar-text-importance-high; color: $white; } &.importance-low > .title { @extend %title-bar-importance-low; @extend %title-bar-text-importance-low; color: $text-color; &:focus:before { outline: 1px dashed; } } } // Zebra pattern for lists and groups .common, .content { .content { background-color: $form-background; .content { background-color: $white; .content { background-color: $form-background; .content { background-color: $white; .content { background-color: $form-background; .content { background-color: $white; } } } } } } } .h5p-li > .list-item-title-bar { @extend %title-bar-base; @extend %title-bar-importance-medium; color: $white; & > .h5peditor-label { @extend %title-bar-text-importance-medium; overflow: hidden; margin: 0 $form-item-buttons-width-normal 0 0; padding: 0 $min-padding; white-space: nowrap; line-height: $form-item-height-normal; outline: none; text-overflow: ellipsis; } &.importance-high > .h5peditor-label { @extend %title-bar-text-importance-high; } &.importance-medium > .h5peditor-label { @extend %title-bar-text-importance-medium; } &.importance-low > .h5peditor-label { @extend %title-bar-text-importance-low; } & > .list-actions { height: 100%; float: right; position: relative; } .remove { cursor: pointer; width: 1.25em; height: $form-item-height-normal; font-size: 1.75em; display: inline-block; &:hover { opacity: 1; text-decoration: none; } } .remove:after { font-family: $icon-font-family; content: "\e890"; opacity: 0.7; display: inline-block; line-height: $form-item-height-normal; } .remove:hover:after { opacity: 1; } .order-group { text-align: center; float: right; background: $form-item-importance-medium-border-color; font-size: $font-size-normal; cursor: pointer; } .order-up, .order-down { width: calc($form-item-height-normal / 2); height: calc($form-item-height-normal / 2); line-height: calc($form-item-height-normal / 2); &:hover { background: $form-item-importance-medium-background-hover; } &:after { font-family: $icon-font-family; content: "\e58e"; display: inline-block; } } .order-down:after { content: "\e58f"; } &.importance-high { @extend %title-bar-importance-high; & > .title { @extend %title-bar-text-importance-high; border: none; margin: 0 $form-item-buttons-width-large 0 0; } .remove { height: $form-item-height-large; line-height: $form-item-height-large; font-size: 40px; &:after { line-height: $form-item-height-large; opacity: 0.7; } &:hover:after { opacity: 1; } } .order-group { background: $form-item-importance-high-border-color; font-size: $font-size-large; } .order-up, .order-down { width: calc($form-item-height-large / 2); height: calc($form-item-height-large / 2); line-height: calc($form-item-height-large / 2); &:hover { background: $form-item-importance-high-background-hover; } } } &.importance-low { @extend %title-bar-importance-low; & > .title { @extend %title-bar-text-importance-low; border: none; margin: 0 $form-item-buttons-width-normal 0 0; &:before { color: $text-color; } &:focus:before { outline: 1px dashed $text-color; } } .remove { height: $form-item-height-normal; line-height: $form-item-height-normal; font-size: 30px; &:after { line-height: $form-item-height-normal; } } .remove:after { color: $text-color; opacity: 0.7; } .remove:hover:after { opacity: 1; } .order-up, .order-down { width: calc($form-item-height-normal / 2); height: calc($form-item-height-normal / 2); background: $form-item-importance-low-border-color; font-size: $font-size-normal; line-height: calc($form-item-height-normal / 2); &:hover { background: $form-item-importance-low-background-hover; } &:after { color: $text-color; } } } } .group.expanded, .listgroup.expanded { & > .content { display: block; } } .listgroup > .list-item-title-bar > .h5peditor-label { cursor: pointer; } .list-item-title-bar > .title, .group > .title { &:before { content: "\e566"; font-family: $icon-font-family; margin-right: calc($min-padding / 2); } &:focus:before { outline: 1px dashed $white; } } .listgroup.expanded > .list-item-title-bar > .h5peditor-label:before, .expanded > .title:before { content: "\e565"; } .listgroup > .group.field { margin: 0; padding: 0; min-width: 0; } .content { display: block; margin: 0; padding: $padding; border: 1px solid $form-border-color; border-top: none; background: $form-content-background; } .common { margin-top: $padding; & > .h5peditor-label { @extend %title-bar-base; @extend %title-bar-importance-low; @extend %title-bar-text-importance-low; margin: 0; padding: 0 $min-padding; cursor: pointer; font-size: 1em; & > .icon:before { content: "\e565"; font-family: $icon-font-family; margin-right: 5px; } &:hover > .icon { opacity: 1; } &:focus { outline: none; } &:focus > .icon:before { outline: 1px dashed; } } & > .fields { min-height: 2em; padding: $padding; border: 1px solid $form-border-color; border-top: none; background: $form-content-background; position: relative; & > .desc { margin: 0; font-size: 0.875em; color: #666; float: left; } p:first-child { margin-bottom: $padding; } } &.collapsed { & > .h5peditor-label > .icon:before { content: "\e566"; } & > .fields { display: none; } } &.hidden { display: none; } } .h5peditor-button[aria-label] { &:before { content: attr(aria-label); visibility: hidden; position: absolute; top: 115%; right: -10%; z-index: 2; padding: 0.25em 0.75em; background: $text-color; color: $white; white-space: nowrap; font-size: $font-size-small; line-height: 1.5; box-shadow: 0 0 0.5em $form-input-placeholder-color; } &:hover:before { visibility: visible; } &[aria-disabled="true"]:before { display: none; } } PK*\<( ( -h5plib/v127/joubel/editor/ckeditor5/README.mdnu[# CKEditor 5 editor generated with the online builder This repository presents a CKEditor 5 editor build generated by the [Online builder tool](https://ckeditor.com/ckeditor-5/online-builder) ## Quick start 1. Open the `sample/index.html` page in the browser. 2. Fill the prompt with the license key. If you do not have the license key yet [contact us](https://ckeditor.com/contact/). ## Configuring build Changes like changing toolbar items, changing order of icons or customizing plugin configurations should be relatively easy to make. Open the `sample/index.html` file and edit the script that initialized the CKEditor 5. Save the file and refresh the browser. That's all. *Note:* If you have any problems with browser caching use the `Ctrl + R` or `Cmd + R` shortcut depending on your system. However if you want to remove or add a plugin to the build you need to follow the next step of this guide. Note that it is also possible to go back to the [Online builder tool](https://ckeditor.com/ckeditor-5/online-builder) and pick other set of plugins. But we encourage you to try the harder way and to learn the principles of Node.js and CKEditor 5 ecosystems that will allow you to do more cool things in the future! ### Installation In order to rebuild the application you need to install all dependencies first. To do it, open the terminal in the project directory and type: ``` npm install ``` Make sure that you have the `node` and `npm` installed first. If not, then follow the instructions on the [Node.js documentation page](https://nodejs.org/en/). ### Adding or removing plugins Now you can install additional plugin in the build. Just follow the [Adding a plugin to an editor tutorial](https://ckeditor.com/docs/ckeditor5/latest/builds/guides/integration/installing-plugins.html#adding-a-plugin-to-an-editor) ### Rebuilding editor If you have already done the [Installation](#installation) and [Adding or removing plugins](#adding-or-removing-plugins) steps, you're ready to rebuild the editor by running the following command: ``` npm run build ``` This will build the CKEditor 5 to the `build` directory. You can open your browser and you should be able to see the changes you've made in the code. If not, then try to refresh also the browser cache by typing `Ctrl + R` or `Cmd + R` depending on your system. ## What's next? Follow the guides available on https://ckeditor.com/docs/ckeditor5/latest/framework/index.html and enjoy the document editing. ## FAQ | Where is the place to report bugs and feature requests? You can create an issue on https://github.com/ckeditor/ckeditor5/issues including the build id - `9e9snf1zg4kp-d2cnyyo44cbm`. Make sure that the question / problem is unique, please look for a possibly asked questions in the search box. Duplicates will be closed. | Where can I learn more about the CKEditor 5 framework? Here: https://ckeditor.com/docs/ckeditor5/latest/framework/ | Is it possible to use online builder with common frameworks like React, Vue or Angular? Not yet, but it these integrations will be available at some point in the future. PK*\5Juu5h5plib/v127/joubel/editor/ckeditor5/webpack.config.jsnu[/** * @license Copyright (c) 2014-2023, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ 'use strict'; /* eslint-env node */ const path = require( 'path' ); const webpack = require( 'webpack' ); const { bundler, styles } = require( '@ckeditor/ckeditor5-dev-utils' ); const { CKEditorTranslationsPlugin } = require( '@ckeditor/ckeditor5-dev-translations' ); const TerserWebpackPlugin = require( 'terser-webpack-plugin' ); module.exports = { devtool: 'source-map', performance: { hints: false }, entry: path.resolve( __dirname, 'src', 'ckeditor.ts' ), output: { // The name under which the editor will be exported. library: 'ClassicEditor', path: path.resolve( __dirname, '..', 'ckeditor' ), filename: 'ckeditor.js', libraryTarget: 'umd', libraryExport: 'default' }, optimization: { minimizer: [ new TerserWebpackPlugin( { sourceMap: true, terserOptions: { output: { // Preserve CKEditor 5 license comments. comments: /^!/ } }, extractComments: false } ) ] }, plugins: [ new CKEditorTranslationsPlugin( { // UI language. Language codes follow the https://en.wikipedia.org/wiki/ISO_639-1 format. // When changing the built-in language, remember to also change it in the editor's configuration (src/ckeditor.ts). language: 'en', additionalLanguages: 'all' } ), new webpack.BannerPlugin( { banner: bundler.getLicenseBanner(), raw: true } ) ], resolve: { extensions: [ '.ts', '.js', '.json' ] }, module: { rules: [ { test: /\.svg$/, use: [ 'raw-loader' ] }, { test: /\.ts$/, use: 'ts-loader' }, { test: /\.css$/, use: [ { loader: 'style-loader', options: { injectType: 'singletonStyleTag', attributes: { 'data-cke': true } } }, { loader: 'css-loader' }, { loader: 'postcss-loader', options: { postcssOptions: styles.getPostCssConfig( { themeImporter: { themePath: require.resolve( '@ckeditor/ckeditor5-theme-lark' ) }, minify: true } ) } } ] } ] } }; PK*\( 3h5plib/v127/joubel/editor/ckeditor5/src/ckeditor.tsnu[/** * @license Copyright (c) 2014-2023, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic'; import { Alignment } from '@ckeditor/ckeditor5-alignment'; import { Autoformat } from '@ckeditor/ckeditor5-autoformat'; import { Bold, Code, Italic, Strikethrough, Subscript, Superscript, Underline } from '@ckeditor/ckeditor5-basic-styles'; import { BlockQuote } from '@ckeditor/ckeditor5-block-quote'; import { CodeBlock } from '@ckeditor/ckeditor5-code-block'; import type { EditorConfig } from '@ckeditor/ckeditor5-core'; import { Essentials } from '@ckeditor/ckeditor5-essentials'; import { FontBackgroundColor, FontColor, FontFamily, FontSize } from '@ckeditor/ckeditor5-font'; import { Heading } from '@ckeditor/ckeditor5-heading'; import { Highlight } from '@ckeditor/ckeditor5-highlight'; import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line'; import { GeneralHtmlSupport } from '@ckeditor/ckeditor5-html-support'; import { Image, ImageCaption, ImageStyle, ImageToolbar, ImageUpload } from '@ckeditor/ckeditor5-image'; import { Indent, IndentBlock } from '@ckeditor/ckeditor5-indent'; import { AutoLink, Link } from '@ckeditor/ckeditor5-link'; import { List } from '@ckeditor/ckeditor5-list'; import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed'; import { Paragraph } from '@ckeditor/ckeditor5-paragraph'; import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office'; import { RemoveFormat } from '@ckeditor/ckeditor5-remove-format'; import { SelectAll } from '@ckeditor/ckeditor5-select-all'; import { Table, TableCaption, TableCellProperties, TableColumnResize, TableProperties, TableToolbar } from '@h5p/ckeditor5-table'; import { TextTransformation } from '@ckeditor/ckeditor5-typing'; // You can read more about extending the build with additional plugins in the "Installing plugins" guide. // See https://ckeditor.com/docs/ckeditor5/latest/installation/plugins/installing-plugins.html for details. class Editor extends ClassicEditor { public static override builtinPlugins = [ Alignment, AutoLink, Autoformat, BlockQuote, Bold, Code, CodeBlock, Essentials, FontBackgroundColor, FontColor, FontFamily, FontSize, GeneralHtmlSupport, Heading, Highlight, HorizontalLine, Image, ImageCaption, ImageStyle, ImageToolbar, ImageUpload, Indent, IndentBlock, Italic, Link, List, MediaEmbed, Paragraph, PasteFromOffice, RemoveFormat, SelectAll, Strikethrough, Subscript, Superscript, Table, TableCaption, TableCellProperties, TableColumnResize, TableProperties, TableToolbar, TextTransformation, Underline ]; public static override defaultConfig: EditorConfig = { toolbar: { items: [ 'heading', '|', 'bold', 'italic', 'underline', 'link', '|', 'bulletedList', 'numberedList', '|', 'outdent', 'indent', '|', 'imageUpload', 'blockQuote', 'insertTable', 'undo', 'redo' ] }, language: 'en', image: { toolbar: [ 'imageTextAlternative', 'toggleImageCaption', 'imageStyle:inline', 'imageStyle:block', 'imageStyle:side' ] }, table: { contentToolbar: [ 'toggleTableCaption', 'tableColumn', 'tableRow', 'mergeTableCells', 'tableCellProperties', 'tableProperties' ] } }; } export default Editor; PK*\.m7h5plib/v127/joubel/editor/ckeditor5/tsconfig.types.jsonnu[{ "extends": "./tsconfig.json", "compilerOptions": { "declaration": true, "emitDeclarationOnly": true, "declarationDir": "build", "stripInternal": true } } PK*\(=UU0h5plib/v127/joubel/editor/ckeditor5/package.jsonnu[{ "name": "ckeditor5-custom-build", "author": "CKSource", "description": "A custom CKEditor 5 build made by the CKEditor 5 online builder.", "version": "0.0.1", "license": "SEE LICENSE IN LICENSE.md", "private": true, "main": "./build/ckeditor.js", "types": "./build/ckeditor.d.ts", "dependencies": { "@ckeditor/ckeditor5-alignment": "^43.0.0", "@ckeditor/ckeditor5-autoformat": "^43.0.0", "@ckeditor/ckeditor5-basic-styles": "^43.0.0", "@ckeditor/ckeditor5-block-quote": "^43.0.0", "@ckeditor/ckeditor5-code-block": "^43.0.0", "@ckeditor/ckeditor5-editor-classic": "^43.0.0", "@ckeditor/ckeditor5-essentials": "^43.0.0", "@ckeditor/ckeditor5-font": "^43.0.0", "@ckeditor/ckeditor5-heading": "^43.0.0", "@ckeditor/ckeditor5-highlight": "^43.0.0", "@ckeditor/ckeditor5-horizontal-line": "^43.0.0", "@ckeditor/ckeditor5-html-support": "^43.0.0", "@ckeditor/ckeditor5-image": "^43.0.0", "@ckeditor/ckeditor5-indent": "^43.0.0", "@ckeditor/ckeditor5-link": "^43.0.0", "@ckeditor/ckeditor5-list": "^43.0.0", "@ckeditor/ckeditor5-media-embed": "^43.0.0", "@ckeditor/ckeditor5-paragraph": "^43.0.0", "@ckeditor/ckeditor5-paste-from-office": "^43.0.0", "@ckeditor/ckeditor5-remove-format": "^43.0.0", "@ckeditor/ckeditor5-select-all": "^43.0.0", "@ckeditor/ckeditor5-typing": "^43.0.0", "@h5p/ckeditor5-table": "github:h5p/h5p-ckeditor-table#0.0.12" }, "devDependencies": { "@ckeditor/ckeditor5-core": "^43.0.0", "@ckeditor/ckeditor5-dev-translations": "^32.1.2", "@ckeditor/ckeditor5-dev-utils": "^32.1.2", "@ckeditor/ckeditor5-theme-lark": "^43.0.0", "css-loader": "^5.2.7", "postcss": "^8.4.29", "postcss-loader": "^4.3.0", "raw-loader": "^4.0.2", "style-loader": "^2.0.0", "terser-webpack-plugin": "^4.2.3", "ts-loader": "^9.4.4", "typescript": "5.0.4", "webpack": "^5.88.2", "webpack-cli": "^4.10.0" }, "scripts": { "build": "webpack --mode production", "postbuild": "tsc --declaration --declarationDir build --stripInternal --emitDeclarationOnly" } } PK*\fC"NN5h5plib/v127/joubel/editor/ckeditor5/package-lock.jsonnu[{ "name": "ckeditor5-custom-build", "version": "0.0.1", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "ckeditor5-custom-build", "version": "0.0.1", "license": "SEE LICENSE IN LICENSE.md", "dependencies": { "@ckeditor/ckeditor5-alignment": "^43.0.0", "@ckeditor/ckeditor5-autoformat": "^43.0.0", "@ckeditor/ckeditor5-basic-styles": "^43.0.0", "@ckeditor/ckeditor5-block-quote": "^43.0.0", "@ckeditor/ckeditor5-code-block": "^43.0.0", "@ckeditor/ckeditor5-editor-classic": "^43.0.0", "@ckeditor/ckeditor5-essentials": "^43.0.0", "@ckeditor/ckeditor5-font": "^43.0.0", "@ckeditor/ckeditor5-heading": "^43.0.0", "@ckeditor/ckeditor5-highlight": "^43.0.0", "@ckeditor/ckeditor5-horizontal-line": "^43.0.0", "@ckeditor/ckeditor5-html-support": "^43.0.0", "@ckeditor/ckeditor5-image": "^43.0.0", "@ckeditor/ckeditor5-indent": "^43.0.0", "@ckeditor/ckeditor5-link": "^43.0.0", "@ckeditor/ckeditor5-list": "^43.0.0", "@ckeditor/ckeditor5-media-embed": "^43.0.0", "@ckeditor/ckeditor5-paragraph": "^43.0.0", "@ckeditor/ckeditor5-paste-from-office": "^43.0.0", "@ckeditor/ckeditor5-remove-format": "^43.0.0", "@ckeditor/ckeditor5-select-all": "^43.0.0", "@ckeditor/ckeditor5-typing": "^43.0.0", "@h5p/ckeditor5-table": "github:h5p/h5p-ckeditor-table#0.0.12" }, "devDependencies": { "@ckeditor/ckeditor5-core": "^43.0.0", "@ckeditor/ckeditor5-dev-translations": "^32.1.2", "@ckeditor/ckeditor5-dev-utils": "^32.1.2", "@ckeditor/ckeditor5-theme-lark": "^43.0.0", "css-loader": "^5.2.7", "postcss": "^8.4.29", "postcss-loader": "^4.3.0", "raw-loader": "^4.0.2", "style-loader": "^2.0.0", "terser-webpack-plugin": "^4.2.3", "ts-loader": "^9.4.4", "typescript": "5.0.4", "webpack": "^5.88.2", "webpack-cli": "^4.10.0" } }, "node_modules/@babel/code-frame": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz", "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==", "dev": true, "license": "MIT", "dependencies": { "@babel/highlight": "^7.24.7", "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/generator": { "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.25.6.tgz", "integrity": "sha512-VPC82gr1seXOpkjAAKoLhP50vx4vGNlF4msF64dSFq1P8RfB+QAuJWGHPXXPc8QyfVWwwB/TNNU4+ayZmHNbZw==", "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.25.6", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^2.5.1" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-string-parser": { "version": "7.24.8", "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.24.8.tgz", "integrity": "sha512-pO9KhhRcuUyGnJWwyEgnRJTSIZHiT+vMD0kPeD+so0l7mxkMT19g3pjY9GTnHySck/hDzq+dtW/4VgnMkippsQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/helper-validator-identifier": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.24.7.tgz", "integrity": "sha512-rR+PBcQ1SMQDDyF6X0wxtG8QyLCgUB0eRAGguqRLfkCA87l7yAP7ehq8SNj96OOGTO8OBV70KhuFYcIkHXOg0w==", "dev": true, "license": "MIT", "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight": { "version": "7.24.7", "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz", "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-validator-identifier": "^7.24.7", "chalk": "^2.4.2", "js-tokens": "^4.0.0", "picocolors": "^1.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/highlight/node_modules/ansi-styles": { "version": "3.2.1", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^1.9.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/chalk": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz", "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^3.2.1", "escape-string-regexp": "^1.0.5", "supports-color": "^5.3.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/color-convert": { "version": "1.9.3", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", "dev": true, "license": "MIT", "dependencies": { "color-name": "1.1.3" } }, "node_modules/@babel/highlight/node_modules/color-name": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==", "dev": true, "license": "MIT" }, "node_modules/@babel/highlight/node_modules/has-flag": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/@babel/highlight/node_modules/supports-color": { "version": "5.5.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^3.0.0" }, "engines": { "node": ">=4" } }, "node_modules/@babel/parser": { "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.25.6.tgz", "integrity": "sha512-trGdfBdbD0l1ZPmcJ83eNxB9rbEax4ALFTF7fN386TMYbeCQbyme5cOEXQhbGXKebwGaB/J52w1mrklMcbgy6Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/types": "^7.25.6" }, "bin": { "parser": "bin/babel-parser.js" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@babel/template": { "version": "7.25.0", "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.0.tgz", "integrity": "sha512-aOOgh1/5XzKvg1jvVz7AVrx2piJ2XBi227DHmbY6y+bM9H2FlN+IfecYu4Xl0cNiiVejlsCri89LUsbj8vJD9Q==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/parser": "^7.25.0", "@babel/types": "^7.25.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/traverse": { "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.6.tgz", "integrity": "sha512-9Vrcx5ZW6UwK5tvqsj0nGpp/XzqthkT0dqIc9g1AdtygFToNtTF67XzYS//dm+SAK9cp3B9R4ZO/46p63SCjlQ==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.24.7", "@babel/generator": "^7.25.6", "@babel/parser": "^7.25.6", "@babel/template": "^7.25.0", "@babel/types": "^7.25.6", "debug": "^4.3.1", "globals": "^11.1.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@babel/types": { "version": "7.25.6", "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.25.6.tgz", "integrity": "sha512-/l42B1qxpG6RdfYf343Uw1vmDjeNhneUXtzhojE7pDgfpEypmRhI6j1kr17XCVv4Cgl9HdAiQY2x0GwKm7rWCw==", "dev": true, "license": "MIT", "dependencies": { "@babel/helper-string-parser": "^7.24.8", "@babel/helper-validator-identifier": "^7.24.7", "to-fast-properties": "^2.0.0" }, "engines": { "node": ">=6.9.0" } }, "node_modules/@ckeditor/ckeditor5-adapter-ckfinder": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-adapter-ckfinder/-/ckeditor5-adapter-ckfinder-43.0.0.tgz", "integrity": "sha512-pwhr46NNLOEyF2Qob/x4+Mwt6Bqi9i/j/4JaI5fSdhml8CZQHw5levJB3NRrOUX1zOw4cjZXQDU+j4TAN+l3xw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-upload": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-alignment": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-alignment/-/ckeditor5-alignment-43.0.0.tgz", "integrity": "sha512-GxLw0l/l+CnqDavcHciegjmKsR4nZCMlrIdlvxPrQXAZOU2/EEEQE95UPVwbJCvIX4BB3LgF31FBbiDMWT3jbg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-autoformat": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autoformat/-/ckeditor5-autoformat-43.0.0.tgz", "integrity": "sha512-wCPNWhgnUQctU7c8JdDVbf9m8Ai1dugvnFnR7xTLY3SLh7LvUCF0q0QQ4CysHdNVGSoGVJBmdjU7Qg3qNwD9Ng==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-autosave": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-autosave/-/ckeditor5-autosave-43.0.0.tgz", "integrity": "sha512-tqOH9ihcSpErDD9tYCDuIBnWNkAlti3b9gknpNj1cc3JSFbIcyX9KAsSFP49qMgaA1An95UyNTo7YunZgOp5sw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-basic-styles": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-basic-styles/-/ckeditor5-basic-styles-43.0.0.tgz", "integrity": "sha512-L3kMP+uDvmkoAtkZO/cvJz4zvbnES1OQYmSipkq2YKZfyAtajj2FWHJ9Xy58D6TRN7RlgoN4WeM4jA0VghNcXQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-block-quote": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-block-quote/-/ckeditor5-block-quote-43.0.0.tgz", "integrity": "sha512-FispEZZOZTpau6L3ft+hbpOqi1nDSrPRdEl4oObcHXdisHEYrTdfPXUtGDlcCcaU5mekNzVt4BNRikx2wNP9oQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-ckbox": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckbox/-/ckeditor5-ckbox-43.0.0.tgz", "integrity": "sha512-dvTgYbn1+EObVoW93rOrLJHlIwAy0/4trLibTTIuwjhKU3IeVW1vH4/UIgXV8Q45CCi5vypLBxzU5V9/bzzcDg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-upload": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "blurhash": "2.0.5", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-ckfinder": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ckfinder/-/ckeditor5-ckfinder-43.0.0.tgz", "integrity": "sha512-YZv2AO9my3HBv/J6pOSjkMgVxl6fkUuT7Ify6Wp6ixQFCy1nPPR7s3W3WQX4+d0BPEXcz602A1PylCESYWwFfA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-clipboard": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-clipboard/-/ckeditor5-clipboard-43.0.0.tgz", "integrity": "sha512-z0A800Acmd1bfY2bi69OB2xBVNZFeqRNRfWyIX+kdP3+kA+tkb6ypMhAc0XMC2cstBcTKUSPEk7HufgD0k8gTw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-cloud-services": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-cloud-services/-/ckeditor5-cloud-services-43.0.0.tgz", "integrity": "sha512-cJ0nwSZNRyX69Ky0M8xIjLzxTJz7E1JJ52TBkzGogV1D2XogiC2eXUMHZDi6zoiBP5KyB84d4trBIxUs0ElaEQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-code-block": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-code-block/-/ckeditor5-code-block-43.0.0.tgz", "integrity": "sha512-gQJaMQdEvHtqG7KsCpWawSnVJeH+aLzgETYEuiWxWkJPXqKpE/gzq/XSRxqoyIoda6YWz2gfxCDZckVAHXa9Pg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-core": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-core/-/ckeditor5-core-43.0.0.tgz", "integrity": "sha512-UbOnWwB8RIjipDTuFCPVqJtSnIhuCf5DCUa+05JqMdKzlqj3pJC+iBsvGbxtk6DdzSr8q1CUHwhJxlXfs3BSLg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-watchdog": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-dev-translations": { "version": "32.1.2", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-dev-translations/-/ckeditor5-dev-translations-32.1.2.tgz", "integrity": "sha512-TudMnRaiYMTNuDMWExeBh0Mk96GySWzgnh4fkXfoqiABQzd9Pp/Fcl40q0LJl4jtyS3qhQGFz88GxzkxAXXU9Q==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@babel/parser": "^7.18.9", "@babel/traverse": "^7.18.9", "chalk": "^4.0.0", "pofile": "^1.0.9", "rimraf": "^3.0.2", "webpack-sources": "^2.0.1" }, "engines": { "node": ">=14.0.0", "npm": ">=5.7.1" } }, "node_modules/@ckeditor/ckeditor5-dev-utils": { "version": "32.1.2", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-dev-utils/-/ckeditor5-dev-utils-32.1.2.tgz", "integrity": "sha512-C9c6EnWhOElN5c56xhJ7mYA9AsgZbaME6d8hTGJ43J5ZG6wg7MFwVlRpv0u2unu8whLO6vsjrW7yeqBrFvo65Q==", "dev": true, "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-dev-translations": "^32.1.2", "chalk": "^3.0.0", "cli-cursor": "^3.1.0", "cli-spinners": "^2.6.1", "cssnano": "^5.0.0", "del": "^5.0.0", "fs-extra": "^8.1.0", "is-interactive": "^1.0.0", "javascript-stringify": "^1.6.0", "postcss": "^8.4.12", "postcss-import": "^14.1.0", "postcss-loader": "^4.3.0", "postcss-mixins": "^9.0.2", "postcss-nesting": "^10.1.4", "raw-loader": "^4.0.1", "shelljs": "^0.8.1", "style-loader": "^2.0.0", "terser-webpack-plugin": "^4.2.3", "through2": "^3.0.1", "ts-loader": "^9.3.0" }, "engines": { "node": ">=14.0.0", "npm": ">=5.7.1" }, "peerDependencies": { "webpack": "^4.43.0 || ^5.24.0" } }, "node_modules/@ckeditor/ckeditor5-dev-utils/node_modules/chalk": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz", "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=8" } }, "node_modules/@ckeditor/ckeditor5-easy-image": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-easy-image/-/ckeditor5-easy-image-43.0.0.tgz", "integrity": "sha512-iT+g9lrBvKreHjRP7tc8P/LrzHEtipBQ488eJdtmaNvMUIQvFnjhZOIcYd7Lr+a4M7+qJl8tSwJOQvM/KiXDeQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-upload": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-editor-balloon": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-balloon/-/ckeditor5-editor-balloon-43.0.0.tgz", "integrity": "sha512-D8tJ/ZKezsc0m75/kzSS783VB8tRiWabmzJUOtlFGss8RwD3QZqHCabP/boZW95vEm/sk5UZt2COL43jlNN4TA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-editor-classic": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-classic/-/ckeditor5-editor-classic-43.0.0.tgz", "integrity": "sha512-VUewScFqwQxm5tu2YPMNzX6pVb3HaXGyEL1PbKo8gBtmo8eimsfNS6WbW2gn4RhQKyu2BzFKXeaNi9Dj0aTZLA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-editor-decoupled": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-decoupled/-/ckeditor5-editor-decoupled-43.0.0.tgz", "integrity": "sha512-BVrMPXCrHMDaxxEuLiUhma4Kx2huSnp7u5EoWaDxAVOXjpb3ZRlboGV5smpt87BmjP5Zt58SrUsDoHnLPfN6eA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-editor-inline": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-inline/-/ckeditor5-editor-inline-43.0.0.tgz", "integrity": "sha512-II77SDB23t02Kbapf74W0gR8QpNCeVm7g7IT6NvGF1OW3RlTwDJQsfdyOgvHQoU4FkdRoOIEOoeFbJxgToJORw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-editor-multi-root": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-editor-multi-root/-/ckeditor5-editor-multi-root-43.0.0.tgz", "integrity": "sha512-9J48bxr8H0iD98QYEdBrfyIGXcX1v0jQN3w9kuT2Una/GgnBRM+EiN2N9vM+xu6arBSA30aZCqU5u0mv2DPAGg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-engine": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-engine/-/ckeditor5-engine-43.0.0.tgz", "integrity": "sha512-0CcNbxxNjrmxytBPjh49ZELwyoE8lFSCFx+44CGRicY+GYeg45+sIUiyY0rWiBaxukfVajl1sYlctDVGezP9Bg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-utils": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-enter": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-enter/-/ckeditor5-enter-43.0.0.tgz", "integrity": "sha512-E6ay1zfYOThTQoBISXL3Ez13dKsJXWz6AZV1z5tAq77N+pD0hBjX4uwwxhQ95Yto56Ifhy3l4zwNJTjePAD1TA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-essentials": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-essentials/-/ckeditor5-essentials-43.0.0.tgz", "integrity": "sha512-UGXxAhmod1QSM6t5ZEPklqBpoAHFqS2ZWXhGZdQaEVzt13MR+tZanug/+3XTs46yhM5401jKT7BGhfkUZwQnVA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-select-all": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-undo": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-find-and-replace": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-find-and-replace/-/ckeditor5-find-and-replace-43.0.0.tgz", "integrity": "sha512-/kD4gypGzuPqtun9IWA0ywNKJKJ9sllurqjRHOXagU5L19pakBr+KpuD7vKNN+NYN3gzyI9REMP6CEXSBb+c3A==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-font": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-font/-/ckeditor5-font-43.0.0.tgz", "integrity": "sha512-/B5Txk17+av2AsD3naq+yqOw6vdj2n8jA4+Zm0J8TerCRbwYELRyA9vBCwsGvVKkl56RfjzSNInFD/gKAn5Uzw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-heading": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-heading/-/ckeditor5-heading-43.0.0.tgz", "integrity": "sha512-15h4KH4LmH8h0udTI9Apvw4YuEopjx+srt/++Uxv/AasLfNSOMfZ8lIjhqieuqWjeCGotnV8sG3TPJDi55JOZw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-paragraph": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-highlight": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-highlight/-/ckeditor5-highlight-43.0.0.tgz", "integrity": "sha512-lzlIXS0/lB2eUCygzUJbNOU6YDXiIyAnZoFqx/qw4heU9DL33Omh+cSfBpSkm462OWbExUWoOkqHFtE3R8Qs8g==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-horizontal-line": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-horizontal-line/-/ckeditor5-horizontal-line-43.0.0.tgz", "integrity": "sha512-yYsfSjEPW0enbXKntf8OA9G4xQGEKp6m+Dph8asuCIakpET21oUkeVYWDgRlf5in0Qabk5Ymv/UkSWdUaPiVew==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-html-embed": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-embed/-/ckeditor5-html-embed-43.0.0.tgz", "integrity": "sha512-KWjZkw9leOzO81xYLqHqhJK7DhrW1qxrfQ2blD3XRI4aXcFQXniLCDXugkLOTzjkbWUhXUbyWt6tM3gPqgX1jQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-html-support": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-html-support/-/ckeditor5-html-support-43.0.0.tgz", "integrity": "sha512-Ji5zaG17wgJRSpXe3FNBD1rEmqLb6Jh1+RJX2/+rIV3ph0ZhP5FKESz8PPw48bPjns5sjd5RCdalv9UIKpz5eQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-image": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-image/-/ckeditor5-image-43.0.0.tgz", "integrity": "sha512-UeO1yaDigz1md+xBt9wP1pp9ncotVL8TFkx3nxXvOqVG8FxWS+HdHZ5JwdG+yCrYiIJOPDJt2YiZ6HSkktF/6A==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-undo": "43.0.0", "@ckeditor/ckeditor5-upload": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-indent": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-indent/-/ckeditor5-indent-43.0.0.tgz", "integrity": "sha512-GnG9LsVWXE8Otyxt3ZN4Ild4yYNHy06sQwcRSuByPePKzFb34l/0AfH8IqLJv8SQT/z35Tb7K64zKOriZFX53g==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-language": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-language/-/ckeditor5-language-43.0.0.tgz", "integrity": "sha512-NcVmgB9YXyrHqbj5QUpKJZztj/eEN5k1RkLOhQNA4IDw6UvNp5uSkum5AxtpwcjDaE10UHQIYDBQIwGSRAUL5g==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-link": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-link/-/ckeditor5-link-43.0.0.tgz", "integrity": "sha512-BAkjg+bfiYCPOvK7WLLlqL2Hy0tcNVgspWLRNr3RJWhCSZMEbtgF8DR97mRA/vWkzTR/htNGKXlbp7OOmBk2Pw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-list": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-list/-/ckeditor5-list-43.0.0.tgz", "integrity": "sha512-pBEI7UNNmO8egc97f1oNHZZvDzZn0TAVzxpYifQcUsVwnsobFk9pojQIpEdJjKoPWcIMJO6SfHe+DYvrB2kqPg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-markdown-gfm": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-markdown-gfm/-/ckeditor5-markdown-gfm-43.0.0.tgz", "integrity": "sha512-4TjnTugDEMoxLej/dmiUxqKEwGqmPACuwU1SnSR15E5X7MR+0SHAdXg/sQfJcbmwrjle/6tSp4NVK7XKPi7Sug==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "ckeditor5": "43.0.0", "marked": "4.0.12", "turndown": "7.2.0", "turndown-plugin-gfm": "1.0.2" } }, "node_modules/@ckeditor/ckeditor5-media-embed": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-media-embed/-/ckeditor5-media-embed-43.0.0.tgz", "integrity": "sha512-l+BlHpS88yZ0J25KqfXADgb3AYXuAt5yTzYwN8XCMQ0/HbjKmgb/Hkppo5Bcd/hzSBG+LUh1dygP1F2lkc5N/A==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-undo": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-mention": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-mention/-/ckeditor5-mention-43.0.0.tgz", "integrity": "sha512-B5DNmfj1JbLLx5+6vnneoK+C0BLPjiM+5x1qdpLVAMIWkbr6qJCthZfe5gnGD7WoGpRILIE//cskm42eP26wcQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-minimap": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-minimap/-/ckeditor5-minimap-43.0.0.tgz", "integrity": "sha512-2C59bqoVBOTnbccsgpCyie+sGKTl/J5nIt5Wu1oyINYPT+j+VjUtiSh5yZKPRXTF+Cyba6NyFU/56BJLBnPurQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-page-break": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-page-break/-/ckeditor5-page-break-43.0.0.tgz", "integrity": "sha512-oSHGAPBHrs2pRwAp36ldVn3fy2xySzDmMXNArnpiRbwIScQOZHuf/iqAIPeeZkO27Gfo9bfh/oWbGcUfPBzF6A==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-paragraph": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paragraph/-/ckeditor5-paragraph-43.0.0.tgz", "integrity": "sha512-xt8x4E6Vh0dmFxbCtv89KdKoSM+xB6B8s7q+Mvf/a/gtnV/x1OJgMBBTUj81FRYtMVB5LyQsE8Wo8jNLYzHmTQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-paste-from-office": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-paste-from-office/-/ckeditor5-paste-from-office-43.0.0.tgz", "integrity": "sha512-VMONY8JUdSfWQ0GNjtpjqWvA1BGunIqhDp4dIvbSyiAoK/3p7QQfjdAm9OOxHIwyns5gO5+sBiEHC5GZadgSMg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-remove-format": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-remove-format/-/ckeditor5-remove-format-43.0.0.tgz", "integrity": "sha512-q27Zqie8WJXk9XGp5CFaGZ8JMyLczhdGU/kyeeX9A5FcCDxpR2nYOgtq0BGgt14XTa2Hr0IKM8NIfdyxA29YNA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-restricted-editing": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-restricted-editing/-/ckeditor5-restricted-editing-43.0.0.tgz", "integrity": "sha512-zMX3ONNZ1jKKfT41PERvJOr79ciZYxCQjhBkCHQE6xe1VhU5QFfPibvZRj+KEHI6CBhxGrwo0In0YaLLIHbUuQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-select-all": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-select-all/-/ckeditor5-select-all-43.0.0.tgz", "integrity": "sha512-ABPFd6cVeef5tWXtnv3ZNdCK1WcCEH48Gm8o84S+ZwQ0wW6y3CY3EW6QVCIL1sqBzgLY8NBBCgGvS7Ymn7fv4A==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-show-blocks": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-show-blocks/-/ckeditor5-show-blocks-43.0.0.tgz", "integrity": "sha512-KX0nfY1Hhs++fv/mgy4+lJxT78ekOwSecLURpX3Mzs4j7AAek424D7itlP5r1wPK9e7ozPd7+AmUYHCuesSD4w==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-source-editing": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-source-editing/-/ckeditor5-source-editing-43.0.0.tgz", "integrity": "sha512-Go9lDGoB26d0Rb7D329I54NHO4T28c4grqx6KVjO0R8nmugfcSpITBLdSn/KarDJA1ysIsbN7k/p5guuiVWTMg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-theme-lark": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-special-characters": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-special-characters/-/ckeditor5-special-characters-43.0.0.tgz", "integrity": "sha512-5l2SdmYEBbid15xUo/L/UjzuxFODNEhNvv4mXIZZOX0tkJ6UNlF1jt5wMjFjWrfFUsZdUwj/aC/7FutotWeHrQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-style": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-style/-/ckeditor5-style-43.0.0.tgz", "integrity": "sha512-9obmKXVQWsg/Ly25ggXyO92GrHp3lIcJ8vjEkbQU/8PO2pblhEylLJEPIRWSySNKYkw0d2fsSDKjC5c3Brx/Gg==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-table": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-table/-/ckeditor5-table-43.0.0.tgz", "integrity": "sha512-yHru16jsCG7Zr71hWVvCFyc08ol2dbUNwV4wAZUmM27sYyW8ue6ATML6NQQUiL+7gwbm1xit/Gm9hxuRBtzz+Q==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-theme-lark": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-theme-lark/-/ckeditor5-theme-lark-43.0.0.tgz", "integrity": "sha512-cd66o/cdKFDhjMnhabgtrsl1K1cyRYzsQnS2459Ly7ApxreOF5w8MRQuGIfr7NmjDwu7xTo4CXowCxmRoxf3JQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-ui": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-typing": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-typing/-/ckeditor5-typing-43.0.0.tgz", "integrity": "sha512-OKXpo5NdM2ZAL4hJpL0SXdeEfWzZfcfFwRjmOSFOIhTH06wN2E77OQbdn1E6L3yyup+9iYBanL7BYjDBQL4/cQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-ui": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-ui/-/ckeditor5-ui-43.0.0.tgz", "integrity": "sha512-R77EeM3vbRWmVdCUPbw5ZfqQlz2UiOIrCnjkXEf1GQVFzn5THNejlUzf9QwL51GS8CquOyH8rg1iRPM9gQiGuw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "color-convert": "2.0.1", "color-parse": "1.4.2", "lodash-es": "4.17.21", "vanilla-colorful": "0.7.2" } }, "node_modules/@ckeditor/ckeditor5-undo": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-undo/-/ckeditor5-undo-43.0.0.tgz", "integrity": "sha512-FDLyZqxkcMqhodOHrYP/GTQWQuC3e9n1gg25nQYqR0IgEqrDU6TH+wTBMrvo6YHv3pl88IZsfNr2vj5ZnsKThQ==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-upload": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-upload/-/ckeditor5-upload-43.0.0.tgz", "integrity": "sha512-IXryGBQFjw2wDz04UM8pbwjJETBxYCmyMz0WW7GJsNA04qO3evxlaCVGczb1nheRbbUb9SBU8wpHKPz05xMQdA==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0" } }, "node_modules/@ckeditor/ckeditor5-utils": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-utils/-/ckeditor5-utils-43.0.0.tgz", "integrity": "sha512-xupNfpUX3EGVVRycijYGOZXTaWEebHPwEMAfI5rduYAUAf63AbTpL4s7sakxFaHp1SS3bQWN+j1QiXh/TBhRAw==", "license": "GPL-2.0-or-later", "dependencies": { "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-watchdog": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-watchdog/-/ckeditor5-watchdog-43.0.0.tgz", "integrity": "sha512-sS+mnuWGZWpe04YbpGZWy3MpMzZ2eFDn911jo0+7nGbypuH8cqrFSZBCUZ4DyE7ghsZ2P6CgMTsUtz4G+kjeZw==", "license": "GPL-2.0-or-later", "dependencies": { "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-widget": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-widget/-/ckeditor5-widget-43.0.0.tgz", "integrity": "sha512-jjRzj3jkieUxtTF2fGQVZCFi5Oq2gpkiJ77DaXEINNqyDx01d2mdIl/U0FnQbgfK/2bUf+1wp5qnT3Lwf4q5Jw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@ckeditor/ckeditor5-word-count": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/@ckeditor/ckeditor5-word-count/-/ckeditor5-word-count-43.0.0.tgz", "integrity": "sha512-AiqeuESUTCsNUPCoPzRq1BDAGqPW6e/9vZpZ0B0esDcshLddJ2oQk0bYyjvkpJ4GDNEwAwJyCN1yI7IYXGEBjw==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "ckeditor5": "43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@csstools/selector-specificity": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz", "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==", "dev": true, "license": "CC0-1.0", "engines": { "node": "^14 || ^16 || >=18" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/csstools" }, "peerDependencies": { "postcss-selector-parser": "^6.0.10" } }, "node_modules/@discoveryjs/json-ext": { "version": "0.5.7", "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz", "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==", "dev": true, "license": "MIT", "engines": { "node": ">=10.0.0" } }, "node_modules/@gar/promisify": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "dev": true, "license": "MIT" }, "node_modules/@h5p/ckeditor5-table": { "version": "0.0.12", "resolved": "git+ssh://git@github.com/h5p/h5p-ckeditor-table.git#7946b83c08050217a5962fb8728591737c40f68a", "dependencies": { "ckeditor5": "^43.0.0", "lodash-es": "4.17.21" } }, "node_modules/@jridgewell/gen-mapping": { "version": "0.3.5", "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/set-array": "^1.2.1", "@jridgewell/sourcemap-codec": "^1.4.10", "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/resolve-uri": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/set-array": { "version": "1.2.1", "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "license": "MIT", "engines": { "node": ">=6.0.0" } }, "node_modules/@jridgewell/source-map": { "version": "0.3.6", "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25" } }, "node_modules/@jridgewell/sourcemap-codec": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", "dev": true, "license": "MIT" }, "node_modules/@jridgewell/trace-mapping": { "version": "0.3.25", "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" } }, "node_modules/@mixmark-io/domino": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/@mixmark-io/domino/-/domino-2.2.0.tgz", "integrity": "sha512-Y28PR25bHXUg88kCV7nivXrP2Nj2RueZ3/l/jdx6J9f8J4nsEGcgX0Qe6lt7Pa+J79+kPiJU3LguR6O/6zrLOw==", "license": "BSD-2-Clause" }, "node_modules/@nodelib/fs.scandir": { "version": "2.1.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "2.0.5", "run-parallel": "^1.1.9" }, "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.stat": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/@nodelib/fs.walk": { "version": "1.2.8", "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.scandir": "2.1.5", "fastq": "^1.6.0" }, "engines": { "node": ">= 8" } }, "node_modules/@npmcli/fs": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", "dev": true, "license": "ISC", "dependencies": { "@gar/promisify": "^1.0.1", "semver": "^7.3.5" } }, "node_modules/@npmcli/move-file": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", "deprecated": "This functionality has been moved to @npmcli/fs", "dev": true, "license": "MIT", "dependencies": { "mkdirp": "^1.0.4", "rimraf": "^3.0.2" }, "engines": { "node": ">=10" } }, "node_modules/@trysound/sax": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", "dev": true, "license": "ISC", "engines": { "node": ">=10.13.0" } }, "node_modules/@types/estree": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.5.tgz", "integrity": "sha512-/kYRxGDLWzHOB7q+wtSUQlFrtcdUccpfy+X+9iMBpHK8QLLhx2wIPYuS5DYtR9Wa/YlZAbIovy7qVdB1Aq6Lyw==", "dev": true, "license": "MIT" }, "node_modules/@types/glob": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz", "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==", "dev": true, "license": "MIT", "dependencies": { "@types/minimatch": "*", "@types/node": "*" } }, "node_modules/@types/json-schema": { "version": "7.0.15", "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, "license": "MIT" }, "node_modules/@types/minimatch": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-5.1.2.tgz", "integrity": "sha512-K0VQKziLUWkVKiRVrx4a40iPaxTUefQmjtkQofBkYRcoaaL/8rhwDWww9qWbrgicNOgnpIsMxyNIUM4+n6dUIA==", "dev": true, "license": "MIT" }, "node_modules/@types/node": { "version": "22.5.2", "resolved": "https://registry.npmjs.org/@types/node/-/node-22.5.2.tgz", "integrity": "sha512-acJsPTEqYqulZS/Yp/S3GgeE6GZ0qYODUR8aVr/DkhHQ8l9nd4j5x1/ZJy9/gHrRlFMqkO6i0I3E27Alu4jjPg==", "dev": true, "license": "MIT", "dependencies": { "undici-types": "~6.19.2" } }, "node_modules/@types/parse-json": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz", "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/ast": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz", "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/helper-numbers": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-api-error": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-buffer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz", "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-numbers": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/floating-point-hex-parser": "1.11.6", "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/helper-wasm-section": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz", "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/wasm-gen": "1.12.1" } }, "node_modules/@webassemblyjs/ieee754": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dev": true, "license": "MIT", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dev": true, "license": "Apache-2.0", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { "version": "1.11.6", "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==", "dev": true, "license": "MIT" }, "node_modules/@webassemblyjs/wasm-edit": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz", "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/helper-wasm-section": "1.12.1", "@webassemblyjs/wasm-gen": "1.12.1", "@webassemblyjs/wasm-opt": "1.12.1", "@webassemblyjs/wasm-parser": "1.12.1", "@webassemblyjs/wast-printer": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-gen": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz", "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/leb128": "1.11.6", "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz", "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-buffer": "1.12.1", "@webassemblyjs/wasm-gen": "1.12.1", "@webassemblyjs/wasm-parser": "1.12.1" } }, "node_modules/@webassemblyjs/wasm-parser": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz", "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@webassemblyjs/helper-api-error": "1.11.6", "@webassemblyjs/helper-wasm-bytecode": "1.11.6", "@webassemblyjs/ieee754": "1.11.6", "@webassemblyjs/leb128": "1.11.6", "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { "version": "1.12.1", "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz", "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==", "dev": true, "license": "MIT", "dependencies": { "@webassemblyjs/ast": "1.12.1", "@xtuc/long": "4.2.2" } }, "node_modules/@webpack-cli/configtest": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-1.2.0.tgz", "integrity": "sha512-4FB8Tj6xyVkyqjj1OaTqCjXYULB9FMkqQ8yGrZjRDrYh0nOE+7Lhs45WioWQQMV+ceFlE368Ukhe6xdvJM9Egg==", "dev": true, "license": "MIT", "peerDependencies": { "webpack": "4.x.x || 5.x.x", "webpack-cli": "4.x.x" } }, "node_modules/@webpack-cli/info": { "version": "1.5.0", "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-1.5.0.tgz", "integrity": "sha512-e8tSXZpw2hPl2uMJY6fsMswaok5FdlGNRTktvFk2sD8RjH0hE2+XistawJx1vmKteh4NmGmNUrp+Tb2w+udPcQ==", "dev": true, "license": "MIT", "dependencies": { "envinfo": "^7.7.3" }, "peerDependencies": { "webpack-cli": "4.x.x" } }, "node_modules/@webpack-cli/serve": { "version": "1.7.0", "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-1.7.0.tgz", "integrity": "sha512-oxnCNGj88fL+xzV+dacXs44HcDwf1ovs3AuEzvP7mqXw7fQntqIhQ1BRmynh4qEKQSSSRSWVyXRjmTbZIX9V2Q==", "dev": true, "license": "MIT", "peerDependencies": { "webpack-cli": "4.x.x" }, "peerDependenciesMeta": { "webpack-dev-server": { "optional": true } } }, "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", "dev": true, "license": "BSD-3-Clause" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", "dev": true, "license": "Apache-2.0" }, "node_modules/acorn": { "version": "8.12.1", "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.12.1.tgz", "integrity": "sha512-tcpGyI9zbizT9JbV6oYE477V6mTlXvvi0T0G3SNIYE2apm/G5huBa1+K89VGeovbg+jycCrfhl3ADxErOuO6Jg==", "dev": true, "license": "MIT", "bin": { "acorn": "bin/acorn" }, "engines": { "node": ">=0.4.0" } }, "node_modules/acorn-import-attributes": { "version": "1.9.5", "resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz", "integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==", "dev": true, "license": "MIT", "peerDependencies": { "acorn": "^8" } }, "node_modules/aggregate-error": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "dev": true, "license": "MIT", "dependencies": { "clean-stack": "^2.0.0", "indent-string": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/ajv": { "version": "6.12.6", "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", "dev": true, "license": "MIT", "dependencies": { "fast-deep-equal": "^3.1.1", "fast-json-stable-stringify": "^2.0.0", "json-schema-traverse": "^0.4.1", "uri-js": "^4.2.2" }, "funding": { "type": "github", "url": "https://github.com/sponsors/epoberezkin" } }, "node_modules/ajv-keywords": { "version": "3.5.2", "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz", "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==", "dev": true, "license": "MIT", "peerDependencies": { "ajv": "^6.9.1" } }, "node_modules/ansi-styles": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "dev": true, "license": "MIT", "dependencies": { "color-convert": "^2.0.1" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, "node_modules/array-union": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/balanced-match": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", "dev": true, "license": "MIT" }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==", "dev": true, "license": "MIT", "engines": { "node": "*" } }, "node_modules/blurhash": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/blurhash/-/blurhash-2.0.5.tgz", "integrity": "sha512-cRygWd7kGBQO3VEhPiTgq4Wc43ctsM+o46urrmPOiuAe+07fzlSB9OJVdpgDL0jPqXUVQ9ht7aq7kxOeJHRK+w==", "license": "MIT" }, "node_modules/boolbase": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", "dev": true, "license": "ISC" }, "node_modules/brace-expansion": { "version": "1.1.11", "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dev": true, "license": "MIT", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", "dev": true, "license": "MIT", "dependencies": { "fill-range": "^7.1.1" }, "engines": { "node": ">=8" } }, "node_modules/browserslist": { "version": "4.23.3", "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.3.tgz", "integrity": "sha512-btwCFJVjI4YWDNfau8RhZ+B1Q/VLoUITrm3RlP6y1tYGWIOa+InuYiRGXUBXo8nA1qKmHMyLB/iVQg5TT4eFoA==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "caniuse-lite": "^1.0.30001646", "electron-to-chromium": "^1.5.4", "node-releases": "^2.0.18", "update-browserslist-db": "^1.1.0" }, "bin": { "browserslist": "cli.js" }, "engines": { "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, "node_modules/buffer-from": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", "dev": true, "license": "MIT" }, "node_modules/cacache": { "version": "15.3.0", "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", "dev": true, "license": "ISC", "dependencies": { "@npmcli/fs": "^1.0.0", "@npmcli/move-file": "^1.0.1", "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "glob": "^7.1.4", "infer-owner": "^1.0.4", "lru-cache": "^6.0.0", "minipass": "^3.1.1", "minipass-collect": "^1.0.2", "minipass-flush": "^1.0.5", "minipass-pipeline": "^1.2.2", "mkdirp": "^1.0.3", "p-map": "^4.0.0", "promise-inflight": "^1.0.1", "rimraf": "^3.0.2", "ssri": "^8.0.1", "tar": "^6.0.2", "unique-filename": "^1.1.1" }, "engines": { "node": ">= 10" } }, "node_modules/cacache/node_modules/p-map": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", "dev": true, "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/callsites": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/camelcase-css": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz", "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==", "dev": true, "license": "MIT", "engines": { "node": ">= 6" } }, "node_modules/caniuse-api": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.0.0", "caniuse-lite": "^1.0.0", "lodash.memoize": "^4.1.2", "lodash.uniq": "^4.5.0" } }, "node_modules/caniuse-lite": { "version": "1.0.30001655", "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001655.tgz", "integrity": "sha512-jRGVy3iSGO5Uutn2owlb5gR6qsGngTw9ZTb4ali9f3glshcNmJ2noam4Mo9zia5P9Dk3jNNydy7vQjuE5dQmfg==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/caniuse-lite" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "CC-BY-4.0" }, "node_modules/chalk": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", "dev": true, "license": "MIT", "dependencies": { "ansi-styles": "^4.1.0", "supports-color": "^7.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/chalk?sponsor=1" } }, "node_modules/chownr": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", "dev": true, "license": "ISC", "engines": { "node": ">=10" } }, "node_modules/chrome-trace-event": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz", "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6.0" } }, "node_modules/ckeditor5": { "version": "43.0.0", "resolved": "https://registry.npmjs.org/ckeditor5/-/ckeditor5-43.0.0.tgz", "integrity": "sha512-7amisPZrSPMuaSDRFVAz/BgplV5OzUpWs6jtFP6MNDh98QK/RLyGvm4vhxjEN5n2MCov/ZURphwYsKwStIX68Q==", "license": "GPL-2.0-or-later", "dependencies": { "@ckeditor/ckeditor5-adapter-ckfinder": "43.0.0", "@ckeditor/ckeditor5-alignment": "43.0.0", "@ckeditor/ckeditor5-autoformat": "43.0.0", "@ckeditor/ckeditor5-autosave": "43.0.0", "@ckeditor/ckeditor5-basic-styles": "43.0.0", "@ckeditor/ckeditor5-block-quote": "43.0.0", "@ckeditor/ckeditor5-ckbox": "43.0.0", "@ckeditor/ckeditor5-ckfinder": "43.0.0", "@ckeditor/ckeditor5-clipboard": "43.0.0", "@ckeditor/ckeditor5-cloud-services": "43.0.0", "@ckeditor/ckeditor5-code-block": "43.0.0", "@ckeditor/ckeditor5-core": "43.0.0", "@ckeditor/ckeditor5-easy-image": "43.0.0", "@ckeditor/ckeditor5-editor-balloon": "43.0.0", "@ckeditor/ckeditor5-editor-classic": "43.0.0", "@ckeditor/ckeditor5-editor-decoupled": "43.0.0", "@ckeditor/ckeditor5-editor-inline": "43.0.0", "@ckeditor/ckeditor5-editor-multi-root": "43.0.0", "@ckeditor/ckeditor5-engine": "43.0.0", "@ckeditor/ckeditor5-enter": "43.0.0", "@ckeditor/ckeditor5-essentials": "43.0.0", "@ckeditor/ckeditor5-find-and-replace": "43.0.0", "@ckeditor/ckeditor5-font": "43.0.0", "@ckeditor/ckeditor5-heading": "43.0.0", "@ckeditor/ckeditor5-highlight": "43.0.0", "@ckeditor/ckeditor5-horizontal-line": "43.0.0", "@ckeditor/ckeditor5-html-embed": "43.0.0", "@ckeditor/ckeditor5-html-support": "43.0.0", "@ckeditor/ckeditor5-image": "43.0.0", "@ckeditor/ckeditor5-indent": "43.0.0", "@ckeditor/ckeditor5-language": "43.0.0", "@ckeditor/ckeditor5-link": "43.0.0", "@ckeditor/ckeditor5-list": "43.0.0", "@ckeditor/ckeditor5-markdown-gfm": "43.0.0", "@ckeditor/ckeditor5-media-embed": "43.0.0", "@ckeditor/ckeditor5-mention": "43.0.0", "@ckeditor/ckeditor5-minimap": "43.0.0", "@ckeditor/ckeditor5-page-break": "43.0.0", "@ckeditor/ckeditor5-paragraph": "43.0.0", "@ckeditor/ckeditor5-paste-from-office": "43.0.0", "@ckeditor/ckeditor5-remove-format": "43.0.0", "@ckeditor/ckeditor5-restricted-editing": "43.0.0", "@ckeditor/ckeditor5-select-all": "43.0.0", "@ckeditor/ckeditor5-show-blocks": "43.0.0", "@ckeditor/ckeditor5-source-editing": "43.0.0", "@ckeditor/ckeditor5-special-characters": "43.0.0", "@ckeditor/ckeditor5-style": "43.0.0", "@ckeditor/ckeditor5-table": "43.0.0", "@ckeditor/ckeditor5-theme-lark": "43.0.0", "@ckeditor/ckeditor5-typing": "43.0.0", "@ckeditor/ckeditor5-ui": "43.0.0", "@ckeditor/ckeditor5-undo": "43.0.0", "@ckeditor/ckeditor5-upload": "43.0.0", "@ckeditor/ckeditor5-utils": "43.0.0", "@ckeditor/ckeditor5-watchdog": "43.0.0", "@ckeditor/ckeditor5-widget": "43.0.0", "@ckeditor/ckeditor5-word-count": "43.0.0" } }, "node_modules/clean-stack": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/cli-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", "dev": true, "license": "MIT", "dependencies": { "restore-cursor": "^3.1.0" }, "engines": { "node": ">=8" } }, "node_modules/cli-spinners": { "version": "2.9.2", "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz", "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/clone-deep": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz", "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==", "dev": true, "license": "MIT", "dependencies": { "is-plain-object": "^2.0.4", "kind-of": "^6.0.2", "shallow-clone": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/color-convert": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", "license": "MIT", "dependencies": { "color-name": "~1.1.4" }, "engines": { "node": ">=7.0.0" } }, "node_modules/color-name": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, "node_modules/color-parse": { "version": "1.4.2", "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.2.tgz", "integrity": "sha512-RI7s49/8yqDj3fECFZjUI1Yi0z/Gq1py43oNJivAIIDSyJiOZLfYCRQEgn8HEVAj++PcRe8AnL2XF0fRJ3BTnA==", "license": "MIT", "dependencies": { "color-name": "^1.0.0" } }, "node_modules/colord": { "version": "2.9.3", "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", "dev": true, "license": "MIT" }, "node_modules/colorette": { "version": "2.0.20", "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", "dev": true, "license": "MIT" }, "node_modules/commander": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", "dev": true, "license": "MIT", "engines": { "node": ">= 10" } }, "node_modules/commondir": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==", "dev": true, "license": "MIT" }, "node_modules/concat-map": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", "dev": true, "license": "MIT" }, "node_modules/cosmiconfig": { "version": "7.1.0", "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz", "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==", "dev": true, "license": "MIT", "dependencies": { "@types/parse-json": "^4.0.0", "import-fresh": "^3.2.1", "parse-json": "^5.0.0", "path-type": "^4.0.0", "yaml": "^1.10.0" }, "engines": { "node": ">=10" } }, "node_modules/cross-spawn": { "version": "7.0.3", "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz", "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==", "dev": true, "license": "MIT", "dependencies": { "path-key": "^3.1.0", "shebang-command": "^2.0.0", "which": "^2.0.1" }, "engines": { "node": ">= 8" } }, "node_modules/css-declaration-sorter": { "version": "6.4.1", "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", "dev": true, "license": "ISC", "engines": { "node": "^10 || ^12 || >=14" }, "peerDependencies": { "postcss": "^8.0.9" } }, "node_modules/css-loader": { "version": "5.2.7", "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-5.2.7.tgz", "integrity": "sha512-Q7mOvpBNBG7YrVGMxRxcBJZFL75o+cH2abNASdibkj/fffYD8qWbInZrD0S9ccI6vZclF3DsHE7njGlLtaHbhg==", "dev": true, "license": "MIT", "dependencies": { "icss-utils": "^5.1.0", "loader-utils": "^2.0.0", "postcss": "^8.2.15", "postcss-modules-extract-imports": "^3.0.0", "postcss-modules-local-by-default": "^4.0.0", "postcss-modules-scope": "^3.0.0", "postcss-modules-values": "^4.0.0", "postcss-value-parser": "^4.1.0", "schema-utils": "^3.0.0", "semver": "^7.3.5" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "webpack": "^4.27.0 || ^5.0.0" } }, "node_modules/css-select": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0", "css-what": "^6.0.1", "domhandler": "^4.3.1", "domutils": "^2.8.0", "nth-check": "^2.0.1" }, "funding": { "url": "https://github.com/sponsors/fb55" } }, "node_modules/css-tree": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", "dev": true, "license": "MIT", "dependencies": { "mdn-data": "2.0.14", "source-map": "^0.6.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/css-what": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">= 6" }, "funding": { "url": "https://github.com/sponsors/fb55" } }, "node_modules/cssesc": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, "license": "MIT", "bin": { "cssesc": "bin/cssesc" }, "engines": { "node": ">=4" } }, "node_modules/cssnano": { "version": "5.1.15", "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", "dev": true, "license": "MIT", "dependencies": { "cssnano-preset-default": "^5.2.14", "lilconfig": "^2.0.3", "yaml": "^1.10.2" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/cssnano" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/cssnano-preset-default": { "version": "5.2.14", "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", "dev": true, "license": "MIT", "dependencies": { "css-declaration-sorter": "^6.3.1", "cssnano-utils": "^3.1.0", "postcss-calc": "^8.2.3", "postcss-colormin": "^5.3.1", "postcss-convert-values": "^5.1.3", "postcss-discard-comments": "^5.1.2", "postcss-discard-duplicates": "^5.1.0", "postcss-discard-empty": "^5.1.1", "postcss-discard-overridden": "^5.1.0", "postcss-merge-longhand": "^5.1.7", "postcss-merge-rules": "^5.1.4", "postcss-minify-font-values": "^5.1.0", "postcss-minify-gradients": "^5.1.1", "postcss-minify-params": "^5.1.4", "postcss-minify-selectors": "^5.2.1", "postcss-normalize-charset": "^5.1.0", "postcss-normalize-display-values": "^5.1.0", "postcss-normalize-positions": "^5.1.1", "postcss-normalize-repeat-style": "^5.1.1", "postcss-normalize-string": "^5.1.0", "postcss-normalize-timing-functions": "^5.1.0", "postcss-normalize-unicode": "^5.1.1", "postcss-normalize-url": "^5.1.0", "postcss-normalize-whitespace": "^5.1.1", "postcss-ordered-values": "^5.1.3", "postcss-reduce-initial": "^5.1.2", "postcss-reduce-transforms": "^5.1.0", "postcss-svgo": "^5.1.0", "postcss-unique-selectors": "^5.1.1" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/cssnano-utils": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", "dev": true, "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/csso": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", "dev": true, "license": "MIT", "dependencies": { "css-tree": "^1.1.2" }, "engines": { "node": ">=8.0.0" } }, "node_modules/debug": { "version": "4.3.6", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.6.tgz", "integrity": "sha512-O/09Bd4Z1fBrU4VzkhFqVgpPzaGbw6Sm9FEkBT1A/YBXQFGuuSxa1dN2nxgxS34JmKXqYx8CZAwEVoJFImUXIg==", "dev": true, "license": "MIT", "dependencies": { "ms": "2.1.2" }, "engines": { "node": ">=6.0" }, "peerDependenciesMeta": { "supports-color": { "optional": true } } }, "node_modules/del": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/del/-/del-5.1.0.tgz", "integrity": "sha512-wH9xOVHnczo9jN2IW68BabcecVPxacIA3g/7z6vhSU/4stOKQzeCRK0yD0A24WiAAUJmmVpWqrERcTxnLo3AnA==", "dev": true, "license": "MIT", "dependencies": { "globby": "^10.0.1", "graceful-fs": "^4.2.2", "is-glob": "^4.0.1", "is-path-cwd": "^2.2.0", "is-path-inside": "^3.0.1", "p-map": "^3.0.0", "rimraf": "^3.0.0", "slash": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/dir-glob": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "license": "MIT", "dependencies": { "path-type": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/dom-serializer": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "dev": true, "license": "MIT", "dependencies": { "domelementtype": "^2.0.1", "domhandler": "^4.2.0", "entities": "^2.0.0" }, "funding": { "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, "node_modules/domelementtype": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/fb55" } ], "license": "BSD-2-Clause" }, "node_modules/domhandler": { "version": "4.3.1", "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "domelementtype": "^2.2.0" }, "engines": { "node": ">= 4" }, "funding": { "url": "https://github.com/fb55/domhandler?sponsor=1" } }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "dom-serializer": "^1.0.1", "domelementtype": "^2.2.0", "domhandler": "^4.2.0" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" } }, "node_modules/electron-to-chromium": { "version": "1.5.13", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.13.tgz", "integrity": "sha512-lbBcvtIJ4J6sS4tb5TLp1b4LyfCdMkwStzXPyAgVgTRAsep4bvrAGaBOP7ZJtQMNJpSQ9SqG4brWOroNaQtm7Q==", "dev": true, "license": "ISC" }, "node_modules/emojis-list": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz", "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/enhanced-resolve": { "version": "5.17.1", "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz", "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.4", "tapable": "^2.2.0" }, "engines": { "node": ">=10.13.0" } }, "node_modules/entities": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", "dev": true, "license": "BSD-2-Clause", "funding": { "url": "https://github.com/fb55/entities?sponsor=1" } }, "node_modules/envinfo": { "version": "7.13.0", "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.13.0.tgz", "integrity": "sha512-cvcaMr7KqXVh4nyzGTVqTum+gAiL265x5jUWQIDLq//zOGbW+gSW/C+OWLleY/rs9Qole6AZLMXPbtIFQbqu+Q==", "dev": true, "license": "MIT", "bin": { "envinfo": "dist/cli.js" }, "engines": { "node": ">=4" } }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, "license": "MIT", "dependencies": { "is-arrayish": "^0.2.1" } }, "node_modules/es-module-lexer": { "version": "1.5.4", "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz", "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw==", "dev": true, "license": "MIT" }, "node_modules/escalade": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/escape-string-regexp": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "esrecurse": "^4.3.0", "estraverse": "^4.1.1" }, "engines": { "node": ">=8.0.0" } }, "node_modules/esrecurse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "estraverse": "^5.2.0" }, "engines": { "node": ">=4.0" } }, "node_modules/esrecurse/node_modules/estraverse": { "version": "5.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/estraverse": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", "dev": true, "license": "BSD-2-Clause", "engines": { "node": ">=4.0" } }, "node_modules/events": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.x" } }, "node_modules/fast-deep-equal": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", "dev": true, "license": "MIT" }, "node_modules/fast-glob": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", "dev": true, "license": "MIT", "dependencies": { "@nodelib/fs.stat": "^2.0.2", "@nodelib/fs.walk": "^1.2.3", "glob-parent": "^5.1.2", "merge2": "^1.3.0", "micromatch": "^4.0.4" }, "engines": { "node": ">=8.6.0" } }, "node_modules/fast-json-stable-stringify": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", "dev": true, "license": "MIT" }, "node_modules/fastest-levenshtein": { "version": "1.0.16", "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", "dev": true, "license": "MIT", "engines": { "node": ">= 4.9.1" } }, "node_modules/fastq": { "version": "1.17.1", "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", "dev": true, "license": "ISC", "dependencies": { "reusify": "^1.0.4" } }, "node_modules/fill-range": { "version": "7.1.1", "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", "dev": true, "license": "MIT", "dependencies": { "to-regex-range": "^5.0.1" }, "engines": { "node": ">=8" } }, "node_modules/find-cache-dir": { "version": "3.3.2", "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz", "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==", "dev": true, "license": "MIT", "dependencies": { "commondir": "^1.0.1", "make-dir": "^3.0.2", "pkg-dir": "^4.1.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/avajs/find-cache-dir?sponsor=1" } }, "node_modules/find-up": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", "dev": true, "license": "MIT", "dependencies": { "locate-path": "^5.0.0", "path-exists": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/flat": { "version": "5.0.2", "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz", "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==", "dev": true, "license": "BSD-3-Clause", "bin": { "flat": "cli.js" } }, "node_modules/fs-extra": { "version": "8.1.0", "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-8.1.0.tgz", "integrity": "sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==", "dev": true, "license": "MIT", "dependencies": { "graceful-fs": "^4.2.0", "jsonfile": "^4.0.0", "universalify": "^0.1.0" }, "engines": { "node": ">=6 <7 || >=8" } }, "node_modules/fs-minipass": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-2.1.0.tgz", "integrity": "sha512-V/JgOLFCS+R6Vcq0slCuaeWEdNC3ouDlJMNIsacH2VtALiu9mV4LPrHc5cDl8k5aw6J8jwgWWpiTo5RYhmIzvg==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/fs.realpath": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", "dev": true, "license": "ISC" }, "node_modules/function-bind": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", "dev": true, "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/glob": { "version": "7.2.3", "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", "deprecated": "Glob versions prior to v9 are no longer supported", "dev": true, "license": "ISC", "dependencies": { "fs.realpath": "^1.0.0", "inflight": "^1.0.4", "inherits": "2", "minimatch": "^3.1.1", "once": "^1.3.0", "path-is-absolute": "^1.0.0" }, "engines": { "node": "*" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/glob-parent": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, "license": "ISC", "dependencies": { "is-glob": "^4.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/glob-to-regexp": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz", "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==", "dev": true, "license": "BSD-2-Clause" }, "node_modules/globals": { "version": "11.12.0", "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/globby": { "version": "10.0.2", "resolved": "https://registry.npmjs.org/globby/-/globby-10.0.2.tgz", "integrity": "sha512-7dUi7RvCoT/xast/o/dLN53oqND4yk0nsHkhRgn9w65C4PofCLOoJ39iSOg+qVDdWQPIEj+eszMHQ+aLVwwQSg==", "dev": true, "license": "MIT", "dependencies": { "@types/glob": "^7.1.1", "array-union": "^2.1.0", "dir-glob": "^3.0.1", "fast-glob": "^3.0.3", "glob": "^7.1.3", "ignore": "^5.1.1", "merge2": "^1.2.3", "slash": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/graceful-fs": { "version": "4.2.11", "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", "dev": true, "license": "ISC" }, "node_modules/has-flag": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/hasown": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "dev": true, "license": "MIT", "dependencies": { "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" } }, "node_modules/icss-utils": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", "dev": true, "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, "peerDependencies": { "postcss": "^8.1.0" } }, "node_modules/ignore": { "version": "5.3.2", "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { "node": ">= 4" } }, "node_modules/import-fresh": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz", "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==", "dev": true, "license": "MIT", "dependencies": { "parent-module": "^1.0.0", "resolve-from": "^4.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/import-local": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", "dev": true, "license": "MIT", "dependencies": { "pkg-dir": "^4.2.0", "resolve-cwd": "^3.0.0" }, "bin": { "import-local-fixture": "fixtures/cli.js" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/imurmurhash": { "version": "0.1.4", "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", "dev": true, "license": "MIT", "engines": { "node": ">=0.8.19" } }, "node_modules/indent-string": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/infer-owner": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", "dev": true, "license": "ISC" }, "node_modules/inflight": { "version": "1.0.6", "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", "dev": true, "license": "ISC", "dependencies": { "once": "^1.3.0", "wrappy": "1" } }, "node_modules/inherits": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "dev": true, "license": "ISC" }, "node_modules/interpret": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-1.4.0.tgz", "integrity": "sha512-agE4QfB2Lkp9uICn7BAqoscw4SZP9kTE2hxiFI3jBPmXJfdqiahTbUuKGsMoN2GtqL9AxhYioAcVvgsb1HvRbA==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/is-arrayish": { "version": "0.2.1", "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, "node_modules/is-core-module": { "version": "2.15.1", "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", "dev": true, "license": "MIT", "dependencies": { "hasown": "^2.0.2" }, "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/is-glob": { "version": "4.0.3", "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", "dev": true, "license": "MIT", "dependencies": { "is-extglob": "^2.1.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/is-interactive": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz", "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-number": { "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", "dev": true, "license": "MIT", "engines": { "node": ">=0.12.0" } }, "node_modules/is-path-cwd": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz", "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/is-path-inside": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/is-plain-object": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz", "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==", "dev": true, "license": "MIT", "dependencies": { "isobject": "^3.0.1" }, "engines": { "node": ">=0.10.0" } }, "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", "dev": true, "license": "ISC" }, "node_modules/isobject": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz", "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/javascript-stringify": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-1.6.0.tgz", "integrity": "sha512-fnjC0up+0SjEJtgmmG+teeel68kutkvzfctO/KxE3qJlbunkJYAshgH3boU++gSBHP8z5/r0ts0qRIrHf0RTQQ==", "dev": true, "license": "MIT" }, "node_modules/jest-worker": { "version": "26.6.2", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-26.6.2.tgz", "integrity": "sha512-KWYVV1c4i+jbMpaBC+U++4Va0cp8OisU185o73T1vo99hqi7w8tSJfUXYswwqqrjzwxa6KpRK54WhPvwf5w6PQ==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^7.0.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", "dev": true, "license": "MIT" }, "node_modules/jsesc": { "version": "2.5.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz", "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==", "dev": true, "license": "MIT", "bin": { "jsesc": "bin/jsesc" }, "engines": { "node": ">=4" } }, "node_modules/json-parse-even-better-errors": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz", "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==", "dev": true, "license": "MIT" }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", "dev": true, "license": "MIT" }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==", "dev": true, "license": "MIT", "bin": { "json5": "lib/cli.js" }, "engines": { "node": ">=6" } }, "node_modules/jsonfile": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", "integrity": "sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==", "dev": true, "license": "MIT", "optionalDependencies": { "graceful-fs": "^4.1.6" } }, "node_modules/kind-of": { "version": "6.0.3", "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz", "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/klona": { "version": "2.0.6", "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz", "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==", "dev": true, "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/lilconfig": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", "dev": true, "license": "MIT", "engines": { "node": ">=10" } }, "node_modules/lines-and-columns": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz", "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==", "dev": true, "license": "MIT" }, "node_modules/loader-runner": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "dev": true, "license": "MIT", "engines": { "node": ">=6.11.5" } }, "node_modules/loader-utils": { "version": "2.0.4", "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz", "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==", "dev": true, "license": "MIT", "dependencies": { "big.js": "^5.2.2", "emojis-list": "^3.0.0", "json5": "^2.1.2" }, "engines": { "node": ">=8.9.0" } }, "node_modules/locate-path": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", "dev": true, "license": "MIT", "dependencies": { "p-locate": "^4.1.0" }, "engines": { "node": ">=8" } }, "node_modules/lodash-es": { "version": "4.17.21", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz", "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw==", "license": "MIT" }, "node_modules/lodash.memoize": { "version": "4.1.2", "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==", "dev": true, "license": "MIT" }, "node_modules/lodash.uniq": { "version": "4.5.0", "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==", "dev": true, "license": "MIT" }, "node_modules/lru-cache": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/make-dir": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz", "integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==", "dev": true, "license": "MIT", "dependencies": { "semver": "^6.0.0" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/make-dir/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" } }, "node_modules/marked": { "version": "4.0.12", "resolved": "https://registry.npmjs.org/marked/-/marked-4.0.12.tgz", "integrity": "sha512-hgibXWrEDNBWgGiK18j/4lkS6ihTe9sxtV4Q1OQppb/0zzyPSzoFANBa5MfsG/zgsWklmNnhm0XACZOH/0HBiQ==", "license": "MIT", "bin": { "marked": "bin/marked.js" }, "engines": { "node": ">= 12" } }, "node_modules/mdn-data": { "version": "2.0.14", "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==", "dev": true, "license": "CC0-1.0" }, "node_modules/merge-stream": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz", "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==", "dev": true, "license": "MIT" }, "node_modules/merge2": { "version": "1.4.1", "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz", "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==", "dev": true, "license": "MIT", "engines": { "node": ">= 8" } }, "node_modules/micromatch": { "version": "4.0.8", "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", "dev": true, "license": "MIT", "dependencies": { "braces": "^3.0.3", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, "node_modules/mime-db": { "version": "1.52.0", "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz", "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.6" } }, "node_modules/mime-types": { "version": "2.1.35", "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz", "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==", "dev": true, "license": "MIT", "dependencies": { "mime-db": "1.52.0" }, "engines": { "node": ">= 0.6" } }, "node_modules/mimic-fn": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz", "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/minimatch": { "version": "3.1.2", "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, "license": "ISC", "dependencies": { "brace-expansion": "^1.1.7" }, "engines": { "node": "*" } }, "node_modules/minipass": { "version": "3.3.6", "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz", "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==", "dev": true, "license": "ISC", "dependencies": { "yallist": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/minipass-collect": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/minipass-collect/-/minipass-collect-1.0.2.tgz", "integrity": "sha512-6T6lH0H8OG9kITm/Jm6tdooIbogG9e0tLgpY6mphXSm/A9u8Nq1ryBG+Qspiub9LjWlBPsPS3tWQ/Botq4FdxA==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/minipass-flush": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/minipass-flush/-/minipass-flush-1.0.5.tgz", "integrity": "sha512-JmQSYYpPUqX5Jyn1mXaRwOda1uQ8HP5KAT/oDSLCzt1BYRhQU0/hDtsB1ufZfEEzMZ9aAVmsBw8+FWsIXlClWw==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/minipass-pipeline": { "version": "1.2.4", "resolved": "https://registry.npmjs.org/minipass-pipeline/-/minipass-pipeline-1.2.4.tgz", "integrity": "sha512-xuIq7cIOt09RPRJ19gdi4b+RiNvDFYe5JH+ggNvBqGqpQXcru3PcRmOZuHBKWK1Txf9+cQ+HMVN4d6z46LZP7A==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", "integrity": "sha512-bAxsR8BVfj60DWXHE3u30oHzfl4G7khkSuPW+qvpd7jFRHm7dLxOjUk1EHACJ/hxLY8phGJ0YhYHZo7jil7Qdg==", "dev": true, "license": "MIT", "dependencies": { "minipass": "^3.0.0", "yallist": "^4.0.0" }, "engines": { "node": ">= 8" } }, "node_modules/mkdirp": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-1.0.4.tgz", "integrity": "sha512-vVqVZQyf3WLx2Shd0qJ9xuvqgAyKPLAiqITEtqW0oIUjzo3PePDd6fW9iFz30ef7Ysp/oiWqbhszeGWW2T6Gzw==", "dev": true, "license": "MIT", "bin": { "mkdirp": "bin/cmd.js" }, "engines": { "node": ">=10" } }, "node_modules/ms": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==", "dev": true, "license": "MIT" }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "bin": { "nanoid": "bin/nanoid.cjs" }, "engines": { "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" } }, "node_modules/neo-async": { "version": "2.6.2", "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz", "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true, "license": "MIT" }, "node_modules/node-releases": { "version": "2.0.18", "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true, "license": "MIT" }, "node_modules/normalize-url": { "version": "6.1.0", "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/nth-check": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "boolbase": "^1.0.0" }, "funding": { "url": "https://github.com/fb55/nth-check?sponsor=1" } }, "node_modules/once": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", "dev": true, "license": "ISC", "dependencies": { "wrappy": "1" } }, "node_modules/onetime": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", "dev": true, "license": "MIT", "dependencies": { "mimic-fn": "^2.1.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-limit": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz", "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==", "dev": true, "license": "MIT", "dependencies": { "yocto-queue": "^0.1.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-locate": { "version": "4.1.0", "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", "dev": true, "license": "MIT", "dependencies": { "p-limit": "^2.2.0" }, "engines": { "node": ">=8" } }, "node_modules/p-locate/node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", "dev": true, "license": "MIT", "dependencies": { "p-try": "^2.0.0" }, "engines": { "node": ">=6" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/p-map": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-3.0.0.tgz", "integrity": "sha512-d3qXVTF/s+W+CdJ5A29wywV2n8CQQYahlgz2bFiA+4eVNJbHJodPZ+/gXwPGh0bOqA+j8S+6+ckmvLGPk1QpxQ==", "dev": true, "license": "MIT", "dependencies": { "aggregate-error": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/p-try": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz", "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==", "dev": true, "license": "MIT", "dependencies": { "callsites": "^3.0.0" }, "engines": { "node": ">=6" } }, "node_modules/parse-json": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz", "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==", "dev": true, "license": "MIT", "dependencies": { "@babel/code-frame": "^7.0.0", "error-ex": "^1.3.1", "json-parse-even-better-errors": "^2.3.0", "lines-and-columns": "^1.1.6" }, "engines": { "node": ">=8" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/path-exists": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz", "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-is-absolute": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/path-key": { "version": "3.1.1", "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz", "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/path-parse": { "version": "1.0.7", "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==", "dev": true, "license": "MIT" }, "node_modules/path-type": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz", "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/picocolors": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==", "dev": true, "license": "ISC" }, "node_modules/picomatch": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "dev": true, "license": "MIT", "engines": { "node": ">=8.6" }, "funding": { "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pify": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", "dev": true, "license": "MIT", "engines": { "node": ">=0.10.0" } }, "node_modules/pkg-dir": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", "dev": true, "license": "MIT", "dependencies": { "find-up": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/pofile": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/pofile/-/pofile-1.1.4.tgz", "integrity": "sha512-r6Q21sKsY1AjTVVjOuU02VYKVNQGJNQHjTIvs4dEbeuuYfxgYk/DGD2mqqq4RDaVkwdSq0VEtmQUOPe/wH8X3g==", "dev": true, "license": "MIT" }, "node_modules/postcss": { "version": "8.4.44", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.44.tgz", "integrity": "sha512-Aweb9unOEpQ3ezu4Q00DPvvM2ZTUitJdNKeP/+uQgr1IBIqu574IaZoURId7BKtWMREwzKa9OgzPzezWGPWFQw==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/postcss" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "nanoid": "^3.3.7", "picocolors": "^1.0.1", "source-map-js": "^1.2.0" }, "engines": { "node": "^10 || ^12 || >=14" } }, "node_modules/postcss-calc": { "version": "8.2.4", "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", "dev": true, "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.9", "postcss-value-parser": "^4.2.0" }, "peerDependencies": { "postcss": "^8.2.2" } }, "node_modules/postcss-colormin": { "version": "5.3.1", "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", "colord": "^2.9.1", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-convert-values": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-discard-comments": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", "dev": true, "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-discard-duplicates": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", "dev": true, "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-discard-empty": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", "dev": true, "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-discard-overridden": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", "dev": true, "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-import": { "version": "14.1.0", "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-14.1.0.tgz", "integrity": "sha512-flwI+Vgm4SElObFVPpTIT7SU7R3qk2L7PyduMcokiaVKuWv9d/U+Gm/QAd8NDLuykTWTkcrjOeD2Pp1rMeBTGw==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.0.0", "read-cache": "^1.0.0", "resolve": "^1.1.7" }, "engines": { "node": ">=10.0.0" }, "peerDependencies": { "postcss": "^8.0.0" } }, "node_modules/postcss-js": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz", "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==", "dev": true, "license": "MIT", "dependencies": { "camelcase-css": "^2.0.1" }, "engines": { "node": "^12 || ^14 || >= 16" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, "peerDependencies": { "postcss": "^8.4.21" } }, "node_modules/postcss-loader": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-4.3.0.tgz", "integrity": "sha512-M/dSoIiNDOo8Rk0mUqoj4kpGq91gcxCfb9PoyZVdZ76/AuhxylHDYZblNE8o+EQ9AMSASeMFEKxZf5aU6wlx1Q==", "dev": true, "license": "MIT", "dependencies": { "cosmiconfig": "^7.0.0", "klona": "^2.0.4", "loader-utils": "^2.0.0", "schema-utils": "^3.0.0", "semver": "^7.3.4" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "postcss": "^7.0.0 || ^8.0.1", "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/postcss-merge-longhand": { "version": "5.1.7", "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0", "stylehacks": "^5.1.1" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-merge-rules": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0", "cssnano-utils": "^3.1.0", "postcss-selector-parser": "^6.0.5" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-minify-font-values": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-minify-gradients": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", "dev": true, "license": "MIT", "dependencies": { "colord": "^2.9.1", "cssnano-utils": "^3.1.0", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-minify-params": { "version": "5.1.4", "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "cssnano-utils": "^3.1.0", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-minify-selectors": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", "dev": true, "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.5" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-mixins": { "version": "9.0.4", "resolved": "https://registry.npmjs.org/postcss-mixins/-/postcss-mixins-9.0.4.tgz", "integrity": "sha512-XVq5jwQJDRu5M1XGkdpgASqLk37OqkH4JCFDXl/Dn7janOJjCTEKL+36cnRVy7bMtoBzALfO7bV7nTIsFnUWLA==", "dev": true, "license": "MIT", "dependencies": { "fast-glob": "^3.2.11", "postcss-js": "^4.0.0", "postcss-simple-vars": "^7.0.0", "sugarss": "^4.0.1" }, "engines": { "node": ">=14.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, "peerDependencies": { "postcss": "^8.2.14" } }, "node_modules/postcss-modules-extract-imports": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz", "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==", "dev": true, "license": "ISC", "engines": { "node": "^10 || ^12 || >= 14" }, "peerDependencies": { "postcss": "^8.1.0" } }, "node_modules/postcss-modules-local-by-default": { "version": "4.0.5", "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz", "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==", "dev": true, "license": "MIT", "dependencies": { "icss-utils": "^5.0.0", "postcss-selector-parser": "^6.0.2", "postcss-value-parser": "^4.1.0" }, "engines": { "node": "^10 || ^12 || >= 14" }, "peerDependencies": { "postcss": "^8.1.0" } }, "node_modules/postcss-modules-scope": { "version": "3.2.0", "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz", "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==", "dev": true, "license": "ISC", "dependencies": { "postcss-selector-parser": "^6.0.4" }, "engines": { "node": "^10 || ^12 || >= 14" }, "peerDependencies": { "postcss": "^8.1.0" } }, "node_modules/postcss-modules-values": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", "dev": true, "license": "ISC", "dependencies": { "icss-utils": "^5.0.0" }, "engines": { "node": "^10 || ^12 || >= 14" }, "peerDependencies": { "postcss": "^8.1.0" } }, "node_modules/postcss-nesting": { "version": "10.2.0", "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz", "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==", "dev": true, "license": "CC0-1.0", "dependencies": { "@csstools/selector-specificity": "^2.0.0", "postcss-selector-parser": "^6.0.10" }, "engines": { "node": "^12 || ^14 || >=16" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/csstools" }, "peerDependencies": { "postcss": "^8.2" } }, "node_modules/postcss-normalize-charset": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", "dev": true, "license": "MIT", "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-display-values": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-positions": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-repeat-style": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-string": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-timing-functions": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-unicode": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-url": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", "dev": true, "license": "MIT", "dependencies": { "normalize-url": "^6.0.1", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-normalize-whitespace": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-ordered-values": { "version": "5.1.3", "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", "dev": true, "license": "MIT", "dependencies": { "cssnano-utils": "^3.1.0", "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-reduce-initial": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "caniuse-api": "^3.0.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-reduce-transforms": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-selector-parser": { "version": "6.1.2", "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", "dev": true, "license": "MIT", "dependencies": { "cssesc": "^3.0.0", "util-deprecate": "^1.0.2" }, "engines": { "node": ">=4" } }, "node_modules/postcss-simple-vars": { "version": "7.0.1", "resolved": "https://registry.npmjs.org/postcss-simple-vars/-/postcss-simple-vars-7.0.1.tgz", "integrity": "sha512-5GLLXaS8qmzHMOjVxqkk1TZPf1jMqesiI7qLhnlyERalG0sMbHIbJqrcnrpmZdKCLglHnRHoEBB61RtGTsj++A==", "dev": true, "license": "MIT", "engines": { "node": ">=14.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, "peerDependencies": { "postcss": "^8.2.1" } }, "node_modules/postcss-svgo": { "version": "5.1.0", "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", "dev": true, "license": "MIT", "dependencies": { "postcss-value-parser": "^4.2.0", "svgo": "^2.7.0" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-unique-selectors": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", "dev": true, "license": "MIT", "dependencies": { "postcss-selector-parser": "^6.0.5" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/postcss-value-parser": { "version": "4.2.0", "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==", "dev": true, "license": "MIT" }, "node_modules/promise-inflight": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz", "integrity": "sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==", "dev": true, "license": "ISC" }, "node_modules/punycode": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz", "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT" }, "node_modules/randombytes": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "^5.1.0" } }, "node_modules/raw-loader": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/raw-loader/-/raw-loader-4.0.2.tgz", "integrity": "sha512-ZnScIV3ag9A4wPX/ZayxL/jZH+euYb6FcUinPcgiQW0+UBtEv0O6Q3lGd3cqJ+GHH+rksEv3Pj99oxJ3u3VIKA==", "dev": true, "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==", "dev": true, "license": "MIT", "dependencies": { "pify": "^2.3.0" } }, "node_modules/readable-stream": { "version": "3.6.2", "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz", "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==", "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.3", "string_decoder": "^1.1.1", "util-deprecate": "^1.0.1" }, "engines": { "node": ">= 6" } }, "node_modules/rechoir": { "version": "0.6.2", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.6.2.tgz", "integrity": "sha512-HFM8rkZ+i3zrV+4LQjwQ0W+ez98pApMGM3HUrN04j3CqzPOzl9nmP15Y8YXNm8QHGv/eacOVEjqhmWpkRV0NAw==", "dev": true, "dependencies": { "resolve": "^1.1.6" }, "engines": { "node": ">= 0.10" } }, "node_modules/resolve": { "version": "1.22.8", "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "dev": true, "license": "MIT", "dependencies": { "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/resolve-cwd": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", "dev": true, "license": "MIT", "dependencies": { "resolve-from": "^5.0.0" }, "engines": { "node": ">=8" } }, "node_modules/resolve-cwd/node_modules/resolve-from": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/restore-cursor": { "version": "3.1.0", "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", "dev": true, "license": "MIT", "dependencies": { "onetime": "^5.1.0", "signal-exit": "^3.0.2" }, "engines": { "node": ">=8" } }, "node_modules/reusify": { "version": "1.0.4", "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz", "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==", "dev": true, "license": "MIT", "engines": { "iojs": ">=1.0.0", "node": ">=0.10.0" } }, "node_modules/rimraf": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz", "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==", "deprecated": "Rimraf versions prior to v4 are no longer supported", "dev": true, "license": "ISC", "dependencies": { "glob": "^7.1.3" }, "bin": { "rimraf": "bin.js" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, "node_modules/run-parallel": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz", "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT", "dependencies": { "queue-microtask": "^1.2.2" } }, "node_modules/safe-buffer": { "version": "5.2.1", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "dev": true, "funding": [ { "type": "github", "url": "https://github.com/sponsors/feross" }, { "type": "patreon", "url": "https://www.patreon.com/feross" }, { "type": "consulting", "url": "https://feross.org/support" } ], "license": "MIT" }, "node_modules/schema-utils": { "version": "3.3.0", "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz", "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==", "dev": true, "license": "MIT", "dependencies": { "@types/json-schema": "^7.0.8", "ajv": "^6.12.5", "ajv-keywords": "^3.5.2" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" } }, "node_modules/semver": { "version": "7.6.3", "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz", "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==", "dev": true, "license": "ISC", "bin": { "semver": "bin/semver.js" }, "engines": { "node": ">=10" } }, "node_modules/serialize-javascript": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-5.0.1.tgz", "integrity": "sha512-SaaNal9imEO737H2c05Og0/8LUXG7EnsZyMa8MzkmuHoELfT6txuj0cMqRj6zfPKnmQ1yasR4PCJc8x+M4JSPA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/shallow-clone": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz", "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==", "dev": true, "license": "MIT", "dependencies": { "kind-of": "^6.0.2" }, "engines": { "node": ">=8" } }, "node_modules/shebang-command": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz", "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==", "dev": true, "license": "MIT", "dependencies": { "shebang-regex": "^3.0.0" }, "engines": { "node": ">=8" } }, "node_modules/shebang-regex": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz", "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/shelljs": { "version": "0.8.5", "resolved": "https://registry.npmjs.org/shelljs/-/shelljs-0.8.5.tgz", "integrity": "sha512-TiwcRcrkhHvbrZbnRcFYMLl30Dfov3HKqzp5tO5b4pt6G/SezKcYhmDg15zXVBswHmctSAQKznqNW2LO5tTDow==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "glob": "^7.0.0", "interpret": "^1.0.0", "rechoir": "^0.6.2" }, "bin": { "shjs": "bin/shjs" }, "engines": { "node": ">=4" } }, "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "dev": true, "license": "ISC" }, "node_modules/slash": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz", "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=8" } }, "node_modules/source-list-map": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz", "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==", "dev": true, "license": "MIT" }, "node_modules/source-map": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-js": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.0.tgz", "integrity": "sha512-itJW8lvSA0TXEphiRoawsCksnlf8SyvmFzIhltqAHluXd88pkCd+cXJVHTDwdCr0IzwptSm035IHQktUu1QUMg==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">=0.10.0" } }, "node_modules/source-map-support": { "version": "0.5.21", "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { "buffer-from": "^1.0.0", "source-map": "^0.6.0" } }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", "integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==", "dev": true, "license": "ISC", "dependencies": { "minipass": "^3.1.1" }, "engines": { "node": ">= 8" } }, "node_modules/stable": { "version": "0.1.8", "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility", "dev": true, "license": "MIT" }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==", "dev": true, "license": "MIT", "dependencies": { "safe-buffer": "~5.2.0" } }, "node_modules/style-loader": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-2.0.0.tgz", "integrity": "sha512-Z0gYUJmzZ6ZdRUqpg1r8GsaFKypE+3xAzuFeMuoHgjc9KZv3wMyCRjQIWEbhoFSq7+7yoHXySDJyyWQaPajeiQ==", "dev": true, "license": "MIT", "dependencies": { "loader-utils": "^2.0.0", "schema-utils": "^3.0.0" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/stylehacks": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", "dev": true, "license": "MIT", "dependencies": { "browserslist": "^4.21.4", "postcss-selector-parser": "^6.0.4" }, "engines": { "node": "^10 || ^12 || >=14.0" }, "peerDependencies": { "postcss": "^8.2.15" } }, "node_modules/sugarss": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/sugarss/-/sugarss-4.0.1.tgz", "integrity": "sha512-WCjS5NfuVJjkQzK10s8WOBY+hhDxxNt/N6ZaGwxFZ+wN3/lKKFSaaKUNecULcTTvE4urLcKaZFQD8vO0mOZujw==", "dev": true, "license": "MIT", "engines": { "node": ">=12.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/postcss/" }, "peerDependencies": { "postcss": "^8.3.3" } }, "node_modules/supports-color": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=8" } }, "node_modules/supports-preserve-symlinks-flag": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/svgo": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", "dev": true, "license": "MIT", "dependencies": { "@trysound/sax": "0.2.0", "commander": "^7.2.0", "css-select": "^4.1.3", "css-tree": "^1.1.3", "csso": "^4.2.0", "picocolors": "^1.0.0", "stable": "^0.1.8" }, "bin": { "svgo": "bin/svgo" }, "engines": { "node": ">=10.13.0" } }, "node_modules/tapable": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "dev": true, "license": "MIT", "engines": { "node": ">=6" } }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", "integrity": "sha512-DZ4yORTwrbTj/7MZYq2w+/ZFdI6OZ/f9SFHR+71gIVUZhOQPHzVCLpvRnPgyaMpfWxxk/4ONva3GQSyNIKRv6A==", "dev": true, "license": "ISC", "dependencies": { "chownr": "^2.0.0", "fs-minipass": "^2.0.0", "minipass": "^5.0.0", "minizlib": "^2.1.1", "mkdirp": "^1.0.3", "yallist": "^4.0.0" }, "engines": { "node": ">=10" } }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", "integrity": "sha512-3FnjYuehv9k6ovOEbyOswadCDPX1piCfhV8ncmYtHOjuPwylVWsghTLo7rabjC3Rx5xD4HDx8Wm1xnMF7S5qFQ==", "dev": true, "license": "ISC", "engines": { "node": ">=8" } }, "node_modules/terser": { "version": "5.31.6", "resolved": "https://registry.npmjs.org/terser/-/terser-5.31.6.tgz", "integrity": "sha512-PQ4DAriWzKj+qgehQ7LK5bQqCFNMmlhjR2PFFLuqGCpuCAauxemVBWwWOxo3UIwWQx8+Pr61Df++r76wDmkQBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "@jridgewell/source-map": "^0.3.3", "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, "bin": { "terser": "bin/terser" }, "engines": { "node": ">=10" } }, "node_modules/terser-webpack-plugin": { "version": "4.2.3", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-4.2.3.tgz", "integrity": "sha512-jTgXh40RnvOrLQNgIkwEKnQ8rmHjHK4u+6UBEi+W+FPmvb+uo+chJXntKe7/3lW5mNysgSWD60KyesnhW8D6MQ==", "dev": true, "license": "MIT", "dependencies": { "cacache": "^15.0.5", "find-cache-dir": "^3.3.1", "jest-worker": "^26.5.0", "p-limit": "^3.0.2", "schema-utils": "^3.0.0", "serialize-javascript": "^5.0.1", "source-map": "^0.6.1", "terser": "^5.3.4", "webpack-sources": "^1.4.3" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "webpack": "^4.0.0 || ^5.0.0" } }, "node_modules/terser-webpack-plugin/node_modules/webpack-sources": { "version": "1.4.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz", "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==", "dev": true, "license": "MIT", "dependencies": { "source-list-map": "^2.0.0", "source-map": "~0.6.1" } }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==", "dev": true, "license": "MIT" }, "node_modules/through2": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/through2/-/through2-3.0.2.tgz", "integrity": "sha512-enaDQ4MUyP2W6ZyT6EsMzqBPZaM/avg8iuo+l2d3QCs0J+6RaqkHV/2/lOwDTueBHeJ/2LG9lrLW3d5rWPucuQ==", "dev": true, "license": "MIT", "dependencies": { "inherits": "^2.0.4", "readable-stream": "2 || 3" } }, "node_modules/to-fast-properties": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz", "integrity": "sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog==", "dev": true, "license": "MIT", "engines": { "node": ">=4" } }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==", "dev": true, "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, "engines": { "node": ">=8.0" } }, "node_modules/ts-loader": { "version": "9.5.1", "resolved": "https://registry.npmjs.org/ts-loader/-/ts-loader-9.5.1.tgz", "integrity": "sha512-rNH3sK9kGZcH9dYzC7CewQm4NtxJTjSEVRJ2DyBZR7f8/wcta+iV44UPCXc5+nzDzivKtlzV6c9P4e+oFhDLYg==", "dev": true, "license": "MIT", "dependencies": { "chalk": "^4.1.0", "enhanced-resolve": "^5.0.0", "micromatch": "^4.0.0", "semver": "^7.3.4", "source-map": "^0.7.4" }, "engines": { "node": ">=12.0.0" }, "peerDependencies": { "typescript": "*", "webpack": "^5.0.0" } }, "node_modules/ts-loader/node_modules/source-map": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "license": "BSD-3-Clause", "engines": { "node": ">= 8" } }, "node_modules/turndown": { "version": "7.2.0", "resolved": "https://registry.npmjs.org/turndown/-/turndown-7.2.0.tgz", "integrity": "sha512-eCZGBN4nNNqM9Owkv9HAtWRYfLA4h909E/WGAWWBpmB275ehNhZyk87/Tpvjbp0jjNl9XwCsbe6bm6CqFsgD+A==", "license": "MIT", "dependencies": { "@mixmark-io/domino": "^2.2.0" } }, "node_modules/turndown-plugin-gfm": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/turndown-plugin-gfm/-/turndown-plugin-gfm-1.0.2.tgz", "integrity": "sha512-vwz9tfvF7XN/jE0dGoBei3FXWuvll78ohzCZQuOb+ZjWrs3a0XhQVomJEb2Qh4VHTPNRO4GPZh0V7VRbiWwkRg==", "license": "MIT" }, "node_modules/typescript": { "version": "5.0.4", "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.0.4.tgz", "integrity": "sha512-cW9T5W9xY37cc+jfEnaUvX91foxtHkza3Nw3wkoF4sSlKn0MONdkdEndig/qPBWXNkmplh3NzayQzCiHM4/hqw==", "dev": true, "license": "Apache-2.0", "bin": { "tsc": "bin/tsc", "tsserver": "bin/tsserver" }, "engines": { "node": ">=12.20" } }, "node_modules/undici-types": { "version": "6.19.8", "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "dev": true, "license": "MIT" }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==", "dev": true, "license": "ISC", "dependencies": { "unique-slug": "^2.0.0" } }, "node_modules/unique-slug": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz", "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4" } }, "node_modules/universalify": { "version": "0.1.2", "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==", "dev": true, "license": "MIT", "engines": { "node": ">= 4.0.0" } }, "node_modules/update-browserslist-db": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.0.tgz", "integrity": "sha512-EdRAaAyk2cUE1wOf2DkEhzxqOQvFOoRJFNS6NeyJ01Gp2beMRpBAINjM2iDXE3KCuKhwnvHIQCJm6ThL2Z+HzQ==", "dev": true, "funding": [ { "type": "opencollective", "url": "https://opencollective.com/browserslist" }, { "type": "tidelift", "url": "https://tidelift.com/funding/github/npm/browserslist" }, { "type": "github", "url": "https://github.com/sponsors/ai" } ], "license": "MIT", "dependencies": { "escalade": "^3.1.2", "picocolors": "^1.0.1" }, "bin": { "update-browserslist-db": "cli.js" }, "peerDependencies": { "browserslist": ">= 4.21.0" } }, "node_modules/uri-js": { "version": "4.4.1", "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz", "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==", "dev": true, "license": "BSD-2-Clause", "dependencies": { "punycode": "^2.1.0" } }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==", "dev": true, "license": "MIT" }, "node_modules/vanilla-colorful": { "version": "0.7.2", "resolved": "https://registry.npmjs.org/vanilla-colorful/-/vanilla-colorful-0.7.2.tgz", "integrity": "sha512-z2YZusTFC6KnLERx1cgoIRX2CjPRP0W75N+3CC6gbvdX5Ch47rZkEMGO2Xnf+IEmi3RiFLxS18gayMA27iU7Kg==", "license": "MIT" }, "node_modules/watchpack": { "version": "2.4.2", "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz", "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==", "dev": true, "license": "MIT", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" }, "engines": { "node": ">=10.13.0" } }, "node_modules/webpack": { "version": "5.94.0", "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.94.0.tgz", "integrity": "sha512-KcsGn50VT+06JH/iunZJedYGUJS5FGjow8wb9c0v5n1Om8O1g4L6LjtfxwlXIATopoQu+vOXXa7gYisWxCoPyg==", "dev": true, "license": "MIT", "dependencies": { "@types/estree": "^1.0.5", "@webassemblyjs/ast": "^1.12.1", "@webassemblyjs/wasm-edit": "^1.12.1", "@webassemblyjs/wasm-parser": "^1.12.1", "acorn": "^8.7.1", "acorn-import-attributes": "^1.9.5", "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", "enhanced-resolve": "^5.17.1", "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.2.11", "json-parse-even-better-errors": "^2.3.1", "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", "schema-utils": "^3.2.0", "tapable": "^2.1.1", "terser-webpack-plugin": "^5.3.10", "watchpack": "^2.4.1", "webpack-sources": "^3.2.3" }, "bin": { "webpack": "bin/webpack.js" }, "engines": { "node": ">=10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependenciesMeta": { "webpack-cli": { "optional": true } } }, "node_modules/webpack-cli": { "version": "4.10.0", "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-4.10.0.tgz", "integrity": "sha512-NLhDfH/h4O6UOy+0LSso42xvYypClINuMNBVVzX4vX98TmTaTUxwRbXdhucbFMd2qLaCTcLq/PdYrvi8onw90w==", "dev": true, "license": "MIT", "dependencies": { "@discoveryjs/json-ext": "^0.5.0", "@webpack-cli/configtest": "^1.2.0", "@webpack-cli/info": "^1.5.0", "@webpack-cli/serve": "^1.7.0", "colorette": "^2.0.14", "commander": "^7.0.0", "cross-spawn": "^7.0.3", "fastest-levenshtein": "^1.0.12", "import-local": "^3.0.2", "interpret": "^2.2.0", "rechoir": "^0.7.0", "webpack-merge": "^5.7.3" }, "bin": { "webpack-cli": "bin/cli.js" }, "engines": { "node": ">=10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "webpack": "4.x.x || 5.x.x" }, "peerDependenciesMeta": { "@webpack-cli/generators": { "optional": true }, "@webpack-cli/migrate": { "optional": true }, "webpack-bundle-analyzer": { "optional": true }, "webpack-dev-server": { "optional": true } } }, "node_modules/webpack-cli/node_modules/interpret": { "version": "2.2.0", "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", "dev": true, "license": "MIT", "engines": { "node": ">= 0.10" } }, "node_modules/webpack-cli/node_modules/rechoir": { "version": "0.7.1", "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz", "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==", "dev": true, "license": "MIT", "dependencies": { "resolve": "^1.9.0" }, "engines": { "node": ">= 0.10" } }, "node_modules/webpack-merge": { "version": "5.10.0", "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz", "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==", "dev": true, "license": "MIT", "dependencies": { "clone-deep": "^4.0.1", "flat": "^5.0.2", "wildcard": "^2.0.0" }, "engines": { "node": ">=10.0.0" } }, "node_modules/webpack-sources": { "version": "2.3.1", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-2.3.1.tgz", "integrity": "sha512-y9EI9AO42JjEcrTJFOYmVywVZdKVUfOvDUPsJea5GIr1JOEGFVqwlY2K098fFoIjOkDzHn2AjRvM8dsBZu+gCA==", "dev": true, "license": "MIT", "dependencies": { "source-list-map": "^2.0.1", "source-map": "^0.6.1" }, "engines": { "node": ">=10.13.0" } }, "node_modules/webpack/node_modules/jest-worker": { "version": "27.5.1", "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz", "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==", "dev": true, "license": "MIT", "dependencies": { "@types/node": "*", "merge-stream": "^2.0.0", "supports-color": "^8.0.0" }, "engines": { "node": ">= 10.13.0" } }, "node_modules/webpack/node_modules/serialize-javascript": { "version": "6.0.2", "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", "dev": true, "license": "BSD-3-Clause", "dependencies": { "randombytes": "^2.1.0" } }, "node_modules/webpack/node_modules/supports-color": { "version": "8.1.1", "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz", "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==", "dev": true, "license": "MIT", "dependencies": { "has-flag": "^4.0.0" }, "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/chalk/supports-color?sponsor=1" } }, "node_modules/webpack/node_modules/terser-webpack-plugin": { "version": "5.3.10", "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dev": true, "license": "MIT", "dependencies": { "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", "schema-utils": "^3.1.1", "serialize-javascript": "^6.0.1", "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" }, "funding": { "type": "opencollective", "url": "https://opencollective.com/webpack" }, "peerDependencies": { "webpack": "^5.1.0" }, "peerDependenciesMeta": { "@swc/core": { "optional": true }, "esbuild": { "optional": true }, "uglify-js": { "optional": true } } }, "node_modules/webpack/node_modules/webpack-sources": { "version": "3.2.3", "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "dev": true, "license": "MIT", "engines": { "node": ">=10.13.0" } }, "node_modules/which": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz", "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==", "dev": true, "license": "ISC", "dependencies": { "isexe": "^2.0.0" }, "bin": { "node-which": "bin/node-which" }, "engines": { "node": ">= 8" } }, "node_modules/wildcard": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz", "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==", "dev": true, "license": "MIT" }, "node_modules/wrappy": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==", "dev": true, "license": "ISC" }, "node_modules/yallist": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "dev": true, "license": "ISC" }, "node_modules/yaml": { "version": "1.10.2", "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "dev": true, "license": "ISC", "engines": { "node": ">= 6" } }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } } } } PK*\|߰`ww.h5plib/v127/joubel/editor/ckeditor5/LICENSE.mdnu[Software License Agreement ========================== Copyright (c) 2014-2023, CKSource Holding sp. z o.o. All rights reserved. Online builder code samples are licensed under the terms of the MIT License (see Appendix A): http://en.wikipedia.org/wiki/MIT_License CKEditor 5 collaboration features are only available under a commercial license. [Contact us](https://ckeditor.com/contact/) for more details. Free 30-days trials of CKEditor 5 collaboration features are available: * https://ckeditor.com/collaboration/ - Real-time collaboration (with all features). * https://ckeditor.com/collaboration/comments/ - Inline comments feature (without real-time collaborative editing). * https://ckeditor.com/collaboration/track-changes/ - Track changes feature (without real-time collaborative editing). Trademarks ---------- CKEditor is a trademark of CKSource Holding sp. z o.o. All other brand and product names are trademarks, registered trademarks or service marks of their respective holders. --- Appendix A: The MIT License --------------------------- The MIT License (MIT) Copyright (c) 2014-2023, CKSource Holding sp. z o.o. 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. PK*\ .h5plib/v127/joubel/editor/ckeditor5/.gitignorenu[node_modules PK*\8 8 7h5plib/v127/joubel/editor/ckeditor5/build/ckeditor.d.tsnu[/** * @license Copyright (c) 2014-2023, CKSource Holding sp. z o.o. All rights reserved. * For licensing, see LICENSE.md or https://ckeditor.com/legal/ckeditor-oss-license */ import { ClassicEditor } from '@ckeditor/ckeditor5-editor-classic'; import { Alignment } from '@ckeditor/ckeditor5-alignment'; import { Autoformat } from '@ckeditor/ckeditor5-autoformat'; import { Bold, Code, Italic, Strikethrough, Subscript, Superscript, Underline } from '@ckeditor/ckeditor5-basic-styles'; import { BlockQuote } from '@ckeditor/ckeditor5-block-quote'; import { CodeBlock } from '@ckeditor/ckeditor5-code-block'; import type { EditorConfig } from '@ckeditor/ckeditor5-core'; import { Essentials } from '@ckeditor/ckeditor5-essentials'; import { FontBackgroundColor, FontColor, FontFamily, FontSize } from '@ckeditor/ckeditor5-font'; import { Heading } from '@ckeditor/ckeditor5-heading'; import { Highlight } from '@ckeditor/ckeditor5-highlight'; import { HorizontalLine } from '@ckeditor/ckeditor5-horizontal-line'; import { GeneralHtmlSupport } from '@ckeditor/ckeditor5-html-support'; import { Image, ImageCaption, ImageStyle, ImageToolbar, ImageUpload } from '@ckeditor/ckeditor5-image'; import { Indent, IndentBlock } from '@ckeditor/ckeditor5-indent'; import { AutoLink, Link } from '@ckeditor/ckeditor5-link'; import { List } from '@ckeditor/ckeditor5-list'; import { MediaEmbed } from '@ckeditor/ckeditor5-media-embed'; import { Paragraph } from '@ckeditor/ckeditor5-paragraph'; import { PasteFromOffice } from '@ckeditor/ckeditor5-paste-from-office'; import { RemoveFormat } from '@ckeditor/ckeditor5-remove-format'; import { SelectAll } from '@ckeditor/ckeditor5-select-all'; import { Table, TableCaption, TableCellProperties, TableColumnResize, TableProperties, TableToolbar } from '@h5p/ckeditor5-table'; import { TextTransformation } from '@ckeditor/ckeditor5-typing'; declare class Editor extends ClassicEditor { static builtinPlugins: (typeof Alignment | typeof AutoLink | typeof Autoformat | typeof BlockQuote | typeof Bold | typeof Code | typeof CodeBlock | typeof Essentials | typeof FontBackgroundColor | typeof FontColor | typeof FontFamily | typeof FontSize | typeof GeneralHtmlSupport | typeof Heading | typeof Highlight | typeof HorizontalLine | typeof Image | typeof ImageCaption | typeof ImageStyle | typeof ImageToolbar | typeof ImageUpload | typeof Indent | typeof IndentBlock | typeof Italic | typeof Link | typeof List | typeof MediaEmbed | typeof Paragraph | typeof PasteFromOffice | typeof RemoveFormat | typeof SelectAll | typeof Strikethrough | typeof Subscript | typeof Superscript | typeof Table | typeof TableCaption | typeof TableCellProperties | typeof TableColumnResize | typeof TableProperties | typeof TableToolbar | typeof TextTransformation | typeof Underline)[]; static defaultConfig: EditorConfig; } export default Editor; PK*\fíVV1h5plib/v127/joubel/editor/ckeditor5/tsconfig.jsonnu[{ "compilerOptions": { "lib": [ "DOM", "DOM.Iterable" ], "noImplicitAny": true, "noImplicitOverride": true, "strict": true, "module": "es6", "target": "es2019", "sourceMap": true, "allowJs": true, "moduleResolution": "node", "skipLibCheck": true }, "include": [ "./src" ] } PK*\ب;;2h5plib/v127/joubel/editor/h5peditor-ajax.class.phpnu[core = $H5PCore; $this->editor = $H5PEditor; $this->storage = $H5PEditorStorage; } /** * @param $endpoint */ public function action($endpoint) { switch ($endpoint) { case H5PEditorEndpoints::LIBRARIES: H5PCore::ajaxSuccess($this->editor->getLibraries(), TRUE); break; case H5PEditorEndpoints::SINGLE_LIBRARY: // pass on arguments $args = func_get_args(); array_shift($args); $library = call_user_func_array( array($this->editor, 'getLibraryData'), $args ); H5PCore::ajaxSuccess($library, TRUE); break; case H5PEditorEndpoints::CONTENT_TYPE_CACHE: if (!$this->isHubOn()) return; H5PCore::ajaxSuccess($this->getContentTypeCache(!$this->isContentTypeCacheUpdated()), TRUE); break; case H5PEditorEndpoints::CONTENT_HUB_METADATA_CACHE: if (!$this->isHubOn()) return; header('Cache-Control: no-cache'); header('Content-Type: application/json; charset=utf-8'); print '{"success":true,"data":' . $this->core->getUpdatedContentHubMetadataCache(func_get_arg(1)) . '}'; break; case H5PEditorEndpoints::LIBRARY_INSTALL: if (!$this->isPostRequest()) return; $token = func_get_arg(1); if (!$this->isValidEditorToken($token)) return; $machineName = func_get_arg(2); $this->libraryInstall($machineName); break; case H5PEditorEndpoints::LIBRARY_UPLOAD: if (!$this->isPostRequest()) return; $token = func_get_arg(1); if (!$this->isValidEditorToken($token)) return; $uploadPath = func_get_arg(2); $contentId = func_get_arg(3); $this->libraryUpload($uploadPath, $contentId); break; case H5PEditorEndpoints::FILES: $token = func_get_arg(1); $contentId = func_get_arg(2); if (!$this->isValidEditorToken($token)) return; $this->fileUpload($contentId); break; case H5PEditorEndpoints::TRANSLATIONS: $language = func_get_arg(1); H5PCore::ajaxSuccess($this->editor->getTranslations($_POST['libraries'], $language)); break; case H5PEditorEndpoints::FILTER: $token = func_get_arg(1); if (!$this->isValidEditorToken($token)) return; $this->filter(func_get_arg(2)); break; case H5PEditorEndpoints::GET_HUB_CONTENT: if (!$this->isPostRequest() || !$this->isValidEditorToken(func_get_arg(1))) { return; } $this->getHubContent(func_get_arg(2), func_get_arg(3)); break; } } /** * Handles uploaded files from the editor, making sure they are validated * and ready to be permanently stored if saved. * * Marks all uploaded files as * temporary so they can be cleaned up when we have finished using them. * * @param int $contentId Id of content if already existing content */ private function fileUpload($contentId = NULL) { $file = new H5peditorFile($this->core->h5pF); if (!$file->isLoaded()) { H5PCore::ajaxError($this->core->h5pF->t('File not found on server. Check file upload settings.')); return; } // Make sure file is valid and mark it for cleanup at a later time if ($file->validate()) { $file_id = $this->core->fs->saveFile($file, 0); $this->storage->markFileForCleanup($file_id, 0); } $file->printResult(); } /** * Handles uploading libraries so they are ready to be modified or directly saved. * * Validates and saves any dependencies, then exposes content to the editor. * * @param {string} $uploadFilePath Path to the file that should be uploaded * @param {int} $contentId Content id of library */ private function libraryUpload($uploadFilePath, $contentId) { // Verify h5p upload if (!$uploadFilePath) { H5PCore::ajaxError($this->core->h5pF->t('Could not get posted H5P.'), 'NO_CONTENT_TYPE'); exit; } $file = $this->saveFileTemporarily($uploadFilePath, TRUE); if (!$file) return; $this->processContent($contentId); } /** * Process H5P content from local H5P package. * * @param integer $contentId The Local Content ID / vid. TODO Remove when JI-366 is fixed */ private function processContent($contentId) { // Check if the downloaded package is valid if (!$this->isValidPackage()) { return; // Validation errors } // Install any required dependencies (libraries) from the package // (if permission allows it, of course) $storage = new H5PStorage($this->core->h5pF, $this->core); $storage->savePackage(NULL, NULL, TRUE); // Make content available to editor $files = $this->core->fs->moveContentDirectory($this->core->h5pF->getUploadedH5pFolderPath(), $contentId); // Clean up $this->storage->removeTemporarilySavedFiles($this->core->h5pF->getUploadedH5pFolderPath()); // Mark all files as temporary // TODO: Uncomment once moveContentDirectory() is fixed. JI-366 /*foreach ($files as $file) { $this->storage->markFileForCleanup($file, 0); }*/ H5PCore::ajaxSuccess(array( 'h5p' => $this->core->mainJsonData, 'content' => $this->core->contentJsonData, 'contentTypes' => $this->getContentTypeCache() )); } /** * Validates security tokens used for the editor * * @param string $token * * @return bool */ private function isValidEditorToken($token) { $isValidToken = $this->editor->ajaxInterface->validateEditorToken($token); if (!$isValidToken) { H5PCore::ajaxError( $this->core->h5pF->t('Invalid security token.'), 'INVALID_TOKEN' ); return FALSE; } return TRUE; } /** * Handles installation of libraries from the Content Type Hub. * * Accepts a machine name and attempts to fetch and install it from the Hub if * it is valid. Will also install any dependencies to the requested library. * * @param string $machineName Name of library that should be installed */ private function libraryInstall($machineName) { // Determine which content type to install from post data if (!$machineName) { H5PCore::ajaxError($this->core->h5pF->t('No content type was specified.'), 'NO_CONTENT_TYPE'); return; } // Look up content type to ensure it's valid(and to check permissions) $contentType = $this->editor->ajaxInterface->getContentTypeCache($machineName); if (!$contentType) { H5PCore::ajaxError($this->core->h5pF->t('The chosen content type is invalid.'), 'INVALID_CONTENT_TYPE'); return; } // Check install permissions if (!$this->editor->canInstallContentType($contentType)) { H5PCore::ajaxError($this->core->h5pF->t('You do not have permission to install content types. Contact the administrator of your site.'), 'INSTALL_DENIED'); return; } else { // Override core permission check $this->core->mayUpdateLibraries(TRUE); } // Retrieve content type from hub endpoint $response = $this->callHubEndpoint(H5PHubEndpoints::CONTENT_TYPES . $machineName); if (!$response) return; // Session parameters has to be set for validation and saving of packages if (!$this->isValidPackage(TRUE)) return; // Save H5P $storage = new H5PStorage($this->core->h5pF, $this->core); $storage->savePackage(NULL, NULL, TRUE); // Clean up $this->storage->removeTemporarilySavedFiles($this->core->h5pF->getUploadedH5pFolderPath()); // Successfully installed. Refresh content types H5PCore::ajaxSuccess($this->getContentTypeCache()); } /** * End-point for filter parameter values according to semantics. * * @param {string} $libraryParameters */ private function filter($libraryParameters) { $libraryParameters = json_decode($libraryParameters); if (!$libraryParameters) { H5PCore::ajaxError($this->core->h5pF->t('Could not parse post data.'), 'NO_LIBRARY_PARAMETERS'); exit; } // Filter parameters and send back to client $validator = new H5PContentValidator($this->core->h5pF, $this->core); $validator->validateLibrary($libraryParameters, (object) array('options' => array($libraryParameters->library))); H5PCore::ajaxSuccess($libraryParameters); } /** * Download and use content from the HUB * * @param integer $hubId The Hub Content ID * @param integer $localContentId The Local Content ID */ private function getHubContent($hubId, $localContentId) { // Download H5P file if (!$this->callHubEndpoint(H5PHubEndpoints::CONTENT . '/' . $hubId . '/export')) { return; // Download failed } $this->processContent($localContentId); } /** * Validates the package. Sets error messages if validation fails. * * @param bool $skipContent Will not validate cotent if set to TRUE * * @return bool */ private function isValidPackage($skipContent = FALSE) { $validator = new H5PValidator($this->core->h5pF, $this->core); if (!$validator->isValidPackage($skipContent, FALSE)) { $this->storage->removeTemporarilySavedFiles($this->core->h5pF->getUploadedH5pPath()); H5PCore::ajaxError( $this->core->h5pF->t('Validating h5p package failed.'), 'VALIDATION_FAILED', NULL, $this->core->h5pF->getMessages('error') ); return FALSE; } return TRUE; } /** * Saves a file or moves it temporarily. This is often necessary in order to * validate and store uploaded or fetched H5Ps. * * Sets error messages if saving fails. * * @param string $data Uri of data that should be saved as a temporary file * @param boolean $move_file Can be set to TRUE to move the data instead of saving it * * @return bool|object Returns false if saving failed or the path to the file * if saving succeeded */ private function saveFileTemporarily($data, $move_file = FALSE) { $file = $this->storage->saveFileTemporarily($data, $move_file); if (!$file) { H5PCore::ajaxError( $this->core->h5pF->t('Failed to download the requested H5P.'), 'DOWNLOAD_FAILED' ); return FALSE; } return $file; } /** * Calls provided hub endpoint and downloads the response to a .h5p file. * * @param string $endpoint Endpoint without protocol * * @return bool */ private function callHubEndpoint($endpoint) { $path = $this->core->h5pF->getUploadedH5pPath(); $response = $this->core->h5pF->fetchExternalData(H5PHubEndpoints::createURL($endpoint), NULL, TRUE, empty($path) ? TRUE : $path); if (!$response) { H5PCore::ajaxError( $this->core->h5pF->t('Failed to download the requested H5P.'), 'DOWNLOAD_FAILED', NULL, $this->core->h5pF->getMessages('error') ); return FALSE; } return TRUE; } /** * Checks if request is a POST. Sets error message on fail. * * @return bool */ private function isPostRequest() { if ($_SERVER['REQUEST_METHOD'] !== 'POST') { H5PCore::ajaxError( $this->core->h5pF->t('A post message is required to access the given endpoint'), 'REQUIRES_POST', 405 ); return FALSE; } return TRUE; } /** * Checks if H5P Hub is enabled. Sets error message on fail. * * @return bool */ private function isHubOn() { if (!$this->core->h5pF->getOption('hub_is_enabled', TRUE)) { H5PCore::ajaxError( $this->core->h5pF->t('The hub is disabled. You can enable it in the H5P settings.'), 'HUB_DISABLED', 403 ); return false; } return true; } /** * Checks if Content Type Cache is up to date. Immediately tries to fetch * a new Content Type Cache if it is outdated. * Sets error message if fetching new Content Type Cache fails. * * @return bool */ private function isContentTypeCacheUpdated() { // Update content type cache if enabled and too old $ct_cache_last_update = $this->core->h5pF->getOption('content_type_cache_updated_at', 0); $outdated_cache = $ct_cache_last_update + (60 * 60 * 24 * 7); // 1 week if (time() > $outdated_cache) { $success = $this->core->updateContentTypeCache(); if (!$success) { return false; } } return true; } /** * Gets content type cache for globally available libraries and the order * in which they have been used by the author * * @param bool $cacheOutdated The cache is outdated and not able to update */ private function getContentTypeCache($cacheOutdated = FALSE) { $canUpdateOrInstall = ($this->core->h5pF->hasPermission(H5PPermission::INSTALL_RECOMMENDED) || $this->core->h5pF->hasPermission(H5PPermission::UPDATE_LIBRARIES)); return array( 'outdated' => $cacheOutdated && $canUpdateOrInstall, 'libraries' => $this->editor->getLatestGlobalLibrariesData(), 'recentlyUsed' => $this->editor->ajaxInterface->getAuthorsRecentlyUsedLibraries(), 'apiVersion' => array( 'major' => H5PCore::$coreApi['majorVersion'], 'minor' => H5PCore::$coreApi['minorVersion'] ), 'details' => $this->core->h5pF->getMessages('info') ); } } PK*\+h5plib/v127/joubel/editor/readme_moodle.txtnu[H5P Editor PHP Library ---------------------- Downloaded last release from: https://github.com/h5p/h5p-editor-php-library/releases Import procedure: * Remove the content in this folder (but the readme_moodle.txt) * Copy all the files from the folder repository in this directory. Removed: * composer.json * .gitignore * ckeditor5/sample Changed: * In the method ns.LibrarySelector.prototype.appendTo (scripts/h5peditor-library-selector.js), comment the line "this.$selector.appendTo($element);" to avoid the display of the Hub Selector. * Review strings in joubel/editor/language/en.js and compare them with existing ones in lang/en/h5plib_vXXX.php: add the new ones and remove the unexisting ones. Remember to use the AMOS script commands, such CPY, to copy all the existing strings from the previous version. As you'll see, all the strings in en.js have been converted following these rules: - Prefix "editor:" has been added. - Keys have been lowercased. Attention: When upgrading to 1.22.4, most of the new strings haven't been added to the lang file because they are related to the H5P Hub which is not currently supported by Moodle. * Add namespace to this library to avoid collision. It means: - Add the "namespace Moodle;" line at the top of all the h5peditor*.php files in the root folder. - Replace \H5Pxxx uses to H5Pxxx (for instance, in h5peditor-ajax.class.php there are several references to \H5PCore that must be replaced with H5PCore). * Add "use stdClass;" in h5peditor.class.php and h5peditor-file.class.php (check that it's still used before replacing it when upgrading the library). * Edit language/en.js and remove the content for 'filters' (it's a JSON with several fields, such as level or language). PK*\&:)h5plib/v127/joubel/editor/images/down.pngnu[PNG  IHDR zjbKGD pHYs  IDATӝѱ 0 ()H]#kE  Bp %7?˒MOb7mfs|vXRfđ.2 qEjgX7V]/lP+;% { ʉ`NIENDB`PK*\{R-j j (h5plib/v127/joubel/editor/images/add.pngnu[PNG  IHDR,,ZbKGD) pHYs  tIME "WPIDATXՙnGƿK+`89K!η0_i X^ }\d){ %dOwW;\+k-0.zjf_u=yq| Tuy"ւ(}:Hb-7L]+Zy]{<Qҥ@&ɳ?c\4M~0*y ZCDf"uRlGQ+uګa%֗&f"Zkټz#~tJ{{{'5XUM;^WA*}xډ7kٷ" cLJDmQQUկ+~B ݓnD^C0,_t^JSeo޼Q,XB&"'w_oc@Ʒ("AD9'''xziHD͕qF5ҵbjTU̜ D'/WU,K3FcôyMo4m?y0ȫW*pUUR5zP1Yk1>Sխ"8&]ZIm TU/f>K9|>窪鞼8!@9\K1-2"J{tK7†DtND%8qIc@ckёD}(RU4k?Ѵ=~$׭CnLj Ƙ1S2TD~"3΋އDҮ ~HevE"YD5^kk팙I;."x=-TUcMv~<~ɲeY~߄`wÿiX^c>{}~!?ݾЇڵ)l<IENDB`PK*\-q*h5plib/v127/joubel/editor/images/order.pngnu[PNG  IHDRH-bKGD|saE pHYs  tIME 4zr]IDAT(mJA [F*ې![ W (اRX b1Lkcbv70w9kT[QPBAּi ř :AJ ck8z<&R;)745ut\jTK@UPTAQrqyL$ܿqWGqO(nNqRAnK2m`4Zh6XdIhea<"UQO5H?C274p1T >7/>",yp1 ˶u;dy'l9* J _ׄl< KBIENDB`PK*\+h5plib/v127/joubel/editor/images/expand.pngnu[PNG  IHDR r|bKGD pHYs  tIME VIDAT(ϝA1_-GҹY5<1 "l#)d`XXAOmBG<}{C]eIENDB`PK*\B/[[+h5plib/v127/joubel/editor/images/remove.pngnu[PNG  IHDRH-bKGD pHYs  tIME IDAT(m=OQsgaIDVBh(_HK@$dKPX+F;w3`ow>r9y‚Ŀ2[ l I $dT>cĜ0p xOW?8goP( {%=e GUn4Yi18ί%@Dz''>>Ɵ}̰aab40~(Oaw,[B؝PQllqIENDB`PK*\!8:hh.h5plib/v127/joubel/editor/images/webm-file.pngnu[PNG  IHDRddpTbKGD pHYs B(xtIME %;IDATx]il׵fpJ"E-8m \+vc M1CP5C_16h+RYР0b;i.NlǭJ(P p!9#3)Q4))/@3s=wνdTUv{r- |w&e$R.%V⻘l0 w}q h-W-uMJ͡q" <$`f%J3jE644{ܵkס`C|>~>9h+ 㘶׏9rۚ0,k}zrb6M6~7n\^ZZ٥V{Bl6s>ܰ&k%b-[K a,A0uuu}ȼfJ+ZXS,Rvqf9zq,KW Y1ڿ`jjlV*qA(90eY Uaa()`pI9D\}*ATUd !RlAg%7;nobYǁ㸒b_nR꣒^صDv 6DUUf11 s1G`UUfhr fԵh4Vɔ9- aqngϞ}t^&Sʕj2p Ֆ=qhjjz>UaH)Zm{R[+ `0ӧO߽jRʮD bJ=) Sw=ڻ )–x&Sʑr=aYF>|ZUN*/-5SZ@ [jI/5v1Ebʵާ*kRLYՒl_^V=ZؒuBt:ygLLF=$I]$Iy=ѨNjE_/cbbbfdSSS:捍allLw}LOK$8z(i$I8qℎ8vtEL.ki4D@ddB(@r𳳳z**AWWn7L&b<z{{a0˗/۷oG}aׇ[Rp`˖-qa:u ۶mæMw^lطo<ہo} pܹIHYe!$Id>, *-1g d4! W"=R[G8V[jJ62*rp Ҿst8d2`(ŠL2 ժ XATR)-+e40hllD$ϣa$q QJx=yfLNNBUU`022qwUAwy'Μ9BGŢ'M7ݴ})Y,b1 d "%hlF$A>0be,l6eYa YZ0P t" " Vl>ǁeYl6ܹsسgL&~?ejƉ' " eq XV{oPUD7nDgg'سgJJ([@2 k=~R8T9I$T i]+R}pxoDe1 K%YJ%U )ڌ*;2F^Q2R̔UN$IB6}Na>1B',#H `08(xOdHJD#vIF,CL&XV(ټEͦg 7jD"A#l˅xD*ei,t'N! +h,:E"ly&iЉ LN#1 EQQ__WiˀE(X,yJ<l6TJi[]]$Ng98R)J\L1-aX(@yXna\r뭷a~EJBYCaYzZnxLn Ce\.pA ʐX,͆x<EQp8`00==fF(9\.DQ 199-[PO/LBb1 Sl޽'OD>.\@ss3 "6n܈͛7_ǎ;x7}v;va9 _~{\Ddʲ I;]K%l۶wElJqUgMDᕞ:~YX x/)pߚEcT!FbjnjV>m, 2RԂJgD`H$VED"]dtďbBlb"@<+߯X<ǑH$0 _tfCA:ujub-JQW tlVG`0łL&CKR(5$!rann$!N#rAQA', X,h4JZx"fqU(r \.]wJh4?Z;a.dhX,!ns8@/LnxbAkk+ڰaaWU}}}lF?u??; ;wԝUѯI>+DĀjUHĢJ])AG-ftt` Q¤xykQIH )$F1㥅SH1D)S>EV Ʉ|>O7l2!-:CfZa2HY|()T(Uc2^=QaZLXUUBDbT%dȲH$Ƣ>[!AXVckV&v;U=DE444th4RLnf3r8  Պ뮻000tww?) GtN~lذ?iM҂-[ J;v؁> 諳SU鴚Ni}ݷ`lkk:==f25,:-ܲ+HPH Bj0Tknn{š;ggpi>K7^~e8p---xW1>>P(w}}}}tz988#G  ȑ#X~=~?~.駟ܹsw Ip9B!/V;A+W$R/l~!'O%$mddDwxÙ3gheLYe2:%.$I4 /@UUj'v؁|>{p84o"JҥKH&F0aȞ8|0TU8V+Ύ$I]'j7Ӄg"LO?m݆)"!$T#7@^{1{*[n$z!?^z HPbffݻ)HړO>Ǐ#ٳ~׿Iu>wA˲pݴ6 iۆ '`tt]]]`Yhj-ۆjitwwFlٲ!-<>#+xGʶ]]]]bF?^@$RB * byXnF%tzSZ0a1l?ݻw]v^@'/qAݻ^<ϣnV"|I۷v ~S (Ľj-G`$ vր;2 S:2% ?ݮ/W-I$(tBQzWi455vttP$y~Tha#Aa)t86 L,RL@x"*nȒXT 6 X lrGJ|i܃)x㍘lRh \~=^N Y122={/}-e͇>1%,({6b赫f-xH˵%FׅlFKK. .w5#c޾*p9 2ޗ/Qu$It HR4jVUtDB7.HНd\4gya]ftT ~_qLOO @3c? jYi`KV4xwiwc͆h4 EQ禍0 v;fgg*aZ!=D:r$x<yIH$hlN ܌)d2'.%Q+nC }Ʉ\.a`2t2 uy(0 ]\^%L#nl Ȯ+YB!iP(D+] `2r`2*Vgle9iH6)vQ҅`rh]д JX>%K )ڇ)VLC[Z(hBl^b}H,h y݇ (NA qV-vm9ź";gsۇIhC9޵{.~o ٻ\V;;($j5_jq;ʆp߿>>>:{{ջWm%귟{AB8b<In,J{/w M?؟ym\@nllܻ{jWu˲q ($qW~CM+j($I~;.\nNb/%(8<EQOH&{%q.۶<%o-pn!<]-dŰ?mƣGZvq{կ8@Q|H 4ge2<|`h _N]xrl.͛pܹCG?B"q-}{Ǐc,--Rx Xݻgbddw]Ke m%T*!!\.0"KZ  bppT 000Y]jmxx~ȲL_?$DQD>G2|>w}#G`ii `vv8ufgg7nӧ몠ӧOڵk9ՄyD"AiTU!I666`&q<,˂eY$ <#qXE8mPhd28p t]<ABÇ~e9s(byy FH$peW^yp<x饗o8">G3^3g`rrMsق~K/V۶Q(\jF6$ -ɸ}idYVpmlll\.CQW@ C6E2(BrFFFFi\Ñ#G066FU!HǕ+Wq`xx{/$/ҥK7MBɇbLӄ mi(aЈ0eYP(" ¶mHw~?BnRebH#X,BLD7 ܖ|H+@/]$# P(mD"|>`xx~m#J!!Jrc_GiG}aAUU>|Gscll _ ӸtRGV@?/vBt_˲`u{I'NLm ٮ}AݴICu@V ':15MF6 u0!ml,`YJ3"4Ɔ^UUU4MC>wM~>G&qe" mX^^vQ,ibaabќݻwiFxyӟ\n:\3a\.SW j&u}}@ђr\.GaHӈbHR0 jbm4N,rQ,|\pq躎177G#G}DߡVݻ~G'9+Ο?{ZQ-j })pHJ%aZP(轥R ,܎ ͢Q>q@ QZuAQ8Nn^EDV[ ]`&0U=d 3b9)BWkIP`Yس,($IB0$IX__ %%<8GT*H8tUQC$ *8@s0@UU VWW1<p˲ꦪJ:) *UU]QVR'l e2d2Zl6ڻRհ*]d2u=??k׮ѼK?eFRC1 U( 2$V4Q(DP(`TUERA,lFVmfD"8XXX@0D U&R r7޽{DZMJȢ* {.;ׯT*O>x >cܻwy~?Α^ZO'3HpJ{ 8YڅUͨRPaI )Vt$$l";"!͎cnU'E,8/u"򦝽_{`lZMt)b ta 0KdzAٖ|["ƞCȪBC(N4 4N2U$ HzW8i&t {J*011ASttk.(%D@Ԏ B4 ;RqO& 6СCX[[$IH$c#tYÇqQ(BfvvgΜqq_D }mZkG±F- WHgWk612lt $IȈk"cb1Ռ@x @w6׷w'MBva,˂TUua#,P.i 8*Ţ_X;{I\.GN!f,#NreWS(Bs0ah75 RN~wjZ,N2i,DWBrlۦog|>aq  BQz )t 5X$LӤbHcB ѣG4ɳIԶېzho G/Z +4$B|W hĭ$5B8xVLzlldhK<G&(bEcuw[_rh糠5>"l\S PEl; $ 'Bcim5Sݲ#EHa_^%J3jYjDx#3DQ x)q¾VʫDyeqj5/QTJ@6NEƆ%v$ur|VIÓzI.zW +,KNe NXb;(U=jHJ4zdj àـJ6Z%AQEqJ7`mm tio_~c-<Փ;OUuܩ8TzIFv&[ivpl\/Ґ{I`wQT$,2IENDB`PK*\}P)8h5plib/v127/joubel/editor/images/cropper/rotate-left.svgnu[ PK*\C+1h5plib/v127/joubel/editor/images/cropper/crop.svgnu[ PK*\04h5plib/v127/joubel/editor/images/cropper/confirm.svgnu[ PK*\,[VV3h5plib/v127/joubel/editor/images/cropper/cancel.svgnu[ PK*\(6aa9h5plib/v127/joubel/editor/images/cropper/rotate-right.svgnu[ PK*\ȕjܺ;h5plib/v127/joubel/editor/images/transparent-background.pngnu[PNG  IHDRKm)tEXtSoftwareAdobe ImageReadyqe<(iTXtXML:com.adobe.xmp (IDATxbܶm L 8?s._L ; ڼ`rIENDB`PK*\-h5plib/v127/joubel/editor/images/collapse.pngnu[PNG  IHDR r|bKGD pHYs  tIME )DAgXIDAT( 0g>i/kwFHJ?P1EO#"C`_7I5Hfxn l"bfVf8^FҟIENDB`PK*\r'h5plib/v127/joubel/editor/composer.jsonnu[{ "name": "h5p/h5p-editor", "type": "library", "description": "H5P Editor functionality in PHP", "keywords": ["h5p","hvp","editor","interactive","content","quiz"], "homepage": "https://h5p.org", "license": "GPL-3.0", "authors": [ { "name": "Svein-Tore Griff With", "email": "with@joubel.com", "homepage": "http://joubel.com", "role": "CEO" }, { "name": "Frode Petterson", "email": "frode.petterson@joubel.com", "homepage": "http://joubel.com", "role": "Developer" } ], "require": { "php": ">=7.0.0" }, "autoload": { "files": [ "h5peditor.class.php", "h5peditor-file.class.php", "h5peditor-ajax.class.php", "h5peditor-storage.interface.php", "h5peditor-ajax.interface.php" ] } } PK*\t UU+h5plib/v127/joubel/editor/webpack.config.jsnu[const path = require('path'); const MiniCssExtractPlugin = require("mini-css-extract-plugin"); const CopyPlugin = require("copy-webpack-plugin"); module.exports = { output: { path: path.resolve(__dirname, "styles/css") }, entry: { index: [path.join(path.resolve(__dirname, 'styles'), "scss", "application.scss")] }, mode: "production", module: { rules: [ { test: /\.s[ac]ss$/i, use: [MiniCssExtractPlugin.loader, 'css-loader', 'sass-loader'] }, { test: /\.(woff(2)?|ttf|eot|svg)$/, type: 'asset/resource', generator: { filename: './fonts/[name][ext]' } } ] }, plugins: [ new MiniCssExtractPlugin({ filename: "application.css" }), new CopyPlugin({ patterns: [ { from: path.join(path.resolve(__dirname, 'node_modules'), 'h5p-image-cropper', 'cropper.js'), to: path.join(path.resolve(__dirname, 'libs'), 'cropper.js') }, { from: path.join(path.resolve(__dirname, 'node_modules'), 'h5p-image-cropper', 'cropper.css'), to: path.join(path.resolve(__dirname, 'libs'), 'cropper.css') }, { from: path.join(path.resolve(__dirname, 'node_modules'), 'h5p-image-cropper', 'images'), to: path.join(path.resolve(__dirname, 'images'), 'cropper') }, { from: path.join(path.resolve(__dirname, 'node_modules'), 'zebra_datepicker', 'dist', 'zebra_datepicker.min.js'), to: path.join(path.resolve(__dirname, 'libs'), 'zebra_datepicker.min.js') }, { from: path.join(path.resolve(__dirname, 'node_modules'), 'zebra_datepicker', 'dist', 'css', 'bootstrap', 'zebra_datepicker.min.css'), to: path.join(path.resolve(__dirname, 'styles'), 'css', 'libs', 'zebra_datepicker.min.css') }, { from: path.join(path.resolve(__dirname, 'node_modules'), 'zebra_datepicker', 'dist', 'css', 'bootstrap', 'icons.png'), to: path.join(path.resolve(__dirname, 'styles'), 'css', 'libs', 'icons.png') } ] }) ] }; PK*\0K6@6@+h5plib/v127/joubel/editor/language/pt-br.jsnu[H5PEditor.language.core = { missingTranslation: '[Tradução ausente :key]', loading: 'Carregando, aguarde...', selectLibrary: 'Selecione a biblioteca que deseja usar em seu conteúdo.', unknownFieldPath: 'Incapaz de encontrar ":path".', notImageField: '":path" não é uma imagem.', notImageOrDimensionsField: '":path" não é uma imagem ou campo de dimensão.', requiredProperty: 'O :property é obrigatório e deve ter um valor.', onlyNumbers: 'O valor de :property pode conter apenas números.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: 'O valor de :property excede o máximo de :max.', listExceedsMax: 'A lista excede o número máxima de :max itens.', belowMin: 'O valor de :property é menor que o mínimo de :min.', listBelowMin: 'A lista precisa de pelo menos :min itens para que o conteúdo funcione corretamente.', outOfStep: 'O valor de :property pode ser mudade em escalas de :step.', add: 'Adicionar', addFile: 'Adicionar arquivo', removeFile: 'Remover arquivo', confirmRemoval: 'Tem certeza de que deseja remover :type?', removeImage: 'Remover imagem', confirmImageRemoval: 'Isso removerá sua imagem. Tem certeza de que deseja continuar?', changeFile: 'Alterar arquivo', changeLibrary: 'Alterar tipo de conteúdo?', semanticsError: 'Erro de semântica: :error', missingProperty: 'Campo :index não possui sua propriedade :property.', expandCollapse: 'Expandir/Recolher', addEntity: 'Adicionar :entity', tooLong: 'Valor do campo é muito longo, deve conter :max caracteres ou menos.', invalidFormat: 'Valor do campo contém um formato inválido ou caracteres proibidos.', confirmChangeLibrary: 'Fazendo isso você perderá todo o trabalho concluído com o tipo atual de conteúdo. Tem certeza de que deseja alterar o tipo de conteúdo?', commonFields: 'Sobreposição de texto e traduções', commonFieldsDescription: 'Aqui você pode editar configurações ou traduzir textos usados neste conteúdo.', uploading: 'Enviando, aguarde...', noFollow: 'Incapaz de seguir campo ":path".', editCopyright: 'Editar direitos autorais', close: 'Fechar', tutorial: 'Tutorial', editMode: 'Modo de edição', listLabel: 'Lista', uploadError: 'Erro de envio de arquivo', fileToLarge: 'O arquivo que você está tentando enviar pode ser muito grande.', unknownFileUploadError: 'Erro de envio de arquivo desconhecido', noSemantics: 'Erro, não foi possível carregar o formulário do tipo de conteúdo.', editImage: 'Editar imagem', saveLabel: 'Salvar', cancelLabel: 'Cancelar', resetToOriginalLabel: 'Resetar para original', loadingImageEditor: 'Carregar editor de imagem, aguarde...', selectFiletoUpload: 'Selecionar arquivo para enviar', or: 'ou', enterAudioUrl: 'Insira a URL fonte para o áudio', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Cole aqui o link do áudio', enterVideoTitle: 'Cole aqui a URL do vídeo ou o link do YouTube', uploadAudioTitle: 'Enviar arquivo de áudio', uploadVideoTitle: 'Enviar arquivo de vídeo', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Inserir', cancel: 'Cancelar', height: 'altura', width: 'largura', textField: 'campo de texto', numberField: 'campo de número', orderItemUp: 'Mover item para cima', orderItemDown: 'Mover item para baixo', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Remover item', hubPanelLabel: 'Selecionar tipo de conteúdo', importantInstructions: 'Instruções importantes', showImportantInstructions: 'Mostrar instruções', hideImportantInstructions: 'Esconder instruções importantes', hide: 'Esconder', example: 'Exemplo', createContentTabLabel: 'Criar conteúdo', uploadTabLabel: 'Carregar', uploadPlaceholder: 'Nenhum arquivo selecionado', uploadInstructionsTitle: 'Carregar um arquivo H5P.', uploadInstructionsContent: 'Você pode começar com exemplos em H5P.org.', uploadFileButtonLabel: 'Carregar um arquivo', uploadFileButtonChangeLabel: 'Alterar arquivo', uploadingThrobber: 'Carregando...', uploadSuccess: ':title foi carregado com sucesso!', unableToInterpretError: 'Incapaz de interpretar resposta.', unableToInterpretSolution: 'Por favor, verifique seu log de erros.', h5pFileWrongExtensionTitle: 'O arquivo selecionado não pôde ser carregado', h5pFileWrongExtensionContent: 'Somente arquivos com a extensão .h5p são permitidos.', h5pFileValidationFailedTitle: 'Não foi possível validar o arquivo H5P.', h5pFileValidationFailedContent: 'Tenha certeza que o H5P carregado possui conteúdo válido H5P. Arquivos H5P que contém apenas bibliotecas devem ser enviados através da página de Bibliotecas H5P.', h5pFileUploadServerErrorTitle: 'O arquivo H5P não pôde ser enviado', h5pFileUploadServerErrorContent: 'Um erro inesperado ocorreu. Verifique seu o log de erros do servidor para maiores informações.', contentTypeSectionAll: 'Todos os tipos de conteúdo', searchResults: 'Procurar resultados', contentTypeSearchFieldPlaceholder: 'Procurar por tipos de conteúdo', contentTypeInstallButtonLabel: 'Instalar', contentTypeInstallingButtonLabel: 'Instalando', contentTypeUseButtonLabel: 'Usar', contentTypeDetailButtonLabel: 'Detalhes', contentTypeUpdateButtonLabel: 'Atualizar', contentTypeUpdatingButtonLabel: 'Atualizando', contentTypeGetButtonLabel: 'Obter', contentTypeBackButtonLabel: 'Voltar', contentTypeIconAltText: 'ícone', contentTypeInstallSuccess: ':contentType instalado com sucesso!', contentTypeUpdateSuccess: ':contentType atualizado com sucesso!', contentTypeInstallError: ':contentType não pôde ser instalado. Contate seu administrador.', contentTypeLicensePanelTitle: 'Licença', contentTypeDemoButtonLabel: 'Demonstração de conteúdo', numResults: ':num resultados', show: 'Mostrar', recentlyUsedFirst: 'Recentemente usados primeiro', popularFirst: 'Populares primeiro', newestFirst: 'Novos primeiro', aToZ: 'Ordem alfabética', noResultsFound: 'Nenhum resultado encontrado', noResultsFoundDesc: 'Não há nenhum tipo de conteúdo que corresponde aos critérios da pesquisa.', readMore: 'Veja mais', readLess: 'Veja menos', contentTypeOwner: 'Por :owner', contentTypeUnsupportedApiVersionTitle: 'Este tipo de conteúdo requer uma nova versão principal', contentTypeUnsupportedApiVersionContent: 'Contate o administrador de seu sistema para lhe prover as atualizações necessárias', contentTypeUpdateAvailable: 'Atualização disponível', contentTypeRestricted: 'Tipo de conteúdo restrito', contentTypeRestrictedDesc: 'O uso deste tipo de conteúdo foi restringido pelo administrador.', contentTypeNotInstalled: 'Tipo de conteúdo não instalado', contentTypeNotInstalledDesc: 'Você não possui permissão para instalar tipos de conteúdo.', theContentType: 'o tipo de conteúdo', currentMenuSelected: 'seleção atual', errorCommunicatingHubTitle: 'Incapaz de se comunicar com o hub.', errorCommunicatingHubContent: 'Um erro ocorreu. Por favor, tente novamente.', warningNoContentTypesInstalled: 'Você não possui nenhum tipo de conteúdo instalado.', warningChangeBrowsingToSeeResults: 'Clique em todos para obter uma lista de todos os conteúdos que você pode instalar.', warningUpdateAvailableTitle: 'Uma nova versão de :contentType está disponível.', warningUpdateAvailableBody: 'Atualize para a última versão para uma experiência melhorada.', licenseDescription: 'Algumas das características desta licença são indicadas abaixo. Clique o ícone de informações acima para ler o texto original da licença. ', licenseModalTitle: 'Detalhes da licença', licenseModalSubtitle: 'Selecione uma licença para ver informações sobre seu uso apropriado', licenseUnspecified: 'Não informado', licenseCanUseCommercially: 'Pode usar comercialmente', licenseCanModify: 'Pode modificar', licenseCanDistribute: 'Pode distribuir', licenseCanSublicense: 'Pode sub-licenciar', licenseCanHoldLiable: 'Pode ser responsabilizado', licenseCannotHoldLiable: 'Não pode ser responsabilizado', licenseMustIncludeCopyright: 'Precisa incluir direitos autorais', licenseMustIncludeLicense: 'Precisa incluir licença', licenseFetchDetailsFailed: 'Falha em buscar detalhes da licença', imageLightboxTitle: 'Imagens', imageLightBoxProgress: ':num de :total', nextImage: 'Próxima imagem', previousImage: 'Imagem anterior', screenshots: 'Capturas de tela', reloadButtonLabel: 'Recarregar', videoQuality: 'Rótulo de qualidade de vídeo', videoQualityDescription: 'Este rótulo ajuda o usuário a identificar a qualidade atual do vídeo. Ex.: 1080p, 720p, HD ou Mobile', videoQualityDefaultLabel: 'Qualidade :index', noContentTypesAvailable: 'Nenhum tipo de conteúdo está disponível', noContentTypesAvailableDesc: 'Seu site está tendo dificuldades ao conectar ao H5P.org e listar os tipos de conteúdo disponíveis.', contentTypeCacheOutdated: 'Lista de tipos de conteúdo desatualizada', contentTypeCacheOutdatedDesc: 'Seu site está tendo dificuldades ao conectar ao H5P.org e verificar os tipos de conteúdo disponíveis. Você pode não ser capaz de atualizar ou instalar novos tipos de conteúdo.', tryAgain: 'Tentar novamente', getHelp: 'Obter ajuda', untitled: 'Sem título', title: 'Título', metadata: 'Metadados', addTitle: 'Adicionar título', usedForSearchingReportsAndCopyrightInformation: 'Usado para pesquisas, relatórios e informações de direitos autorais', metadataSharingAndLicensingInfo: 'Metadados (informações de compartilhamento e licenciamento)', fillInTheFieldsBelow: 'Preencha os campos abaixo', saveMetadata: 'Salvar metadados', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Adicionar nova alteração', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Registrar alteração', newChangeHasBeenLogged: 'A nova alteração foi registrada no log', loggedChanges: 'Alterações registradas', noChangesHaveBeenLogged: 'Nenhuma alteração foi registrada', errorHeader: 'Um erro ocorreu', errorCalculatingMaxScore: 'Não foi possível calcular a pontuação máxima para este conteúdo. A pontuação máxima é assumida como sendo 0. Contate seu administrador se isto não estiver correto.', maxScoreSemanticsMissing: 'Não foi possível encontrar a semântica esperada no conteúdo.', copyButton: 'Copiar', copiedButton: 'Copiado', pasteButton: 'Colar', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Copiar conteúdo H5P para o painel', copiedToClipboard: 'O conteúdo foi copiado para o painel', pasteFromClipboard: 'Colar conteúdo H5P do painel', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'Não há conteúdo H5P no painel', pasteError: 'Não foi possível colar', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: "Unfortunately, the selected content type '%lib' isn't installed on this system.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\+m>>(h5plib/v127/joubel/editor/language/pl.jsnu[H5PEditor.language.core = { missingTranslation: '[Brakujące tłumaczenie :key]', loading: 'Wczytywanie proszę czekać...', selectLibrary: 'Wybierz typ zasobu, którego chcesz użyć.', unknownFieldPath: 'Nie można odnaleźć ":path".', notImageField: '":path" nie jest obrazem.', notImageOrDimensionsField: '":path" nie jest obrazem ani polem wartości.', requiredProperty: 'property: jest wymagana i musi mieć wartość.', onlyNumbers: 'property: może zawierać tylko cyfry.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: 'property: przekracza maksymalną wartość :max.', listExceedsMax: 'Lista przekracza maksimum :max elementów.', belowMin: 'property: mniej niż minimum: min.', listBelowMin: 'Lista musi mieć co najmniej :min elementów, aby zasób działał poprawnie.', outOfStep: ':property może zostać zmieniona tylko w :step.', add: 'Dodaj', addFile: 'Dodaj plik', removeFile: 'Usuń plik', confirmRemoval: 'Czy na pewno usunąć :type?', removeImage: 'Usuń obraz', confirmImageRemoval: 'Obrazy zostaną usunięte, kontynować?', changeFile: 'Zmień plik', changeLibrary: 'Zmienić typ?', semanticsError: 'Błąd semantyki', missingProperty: 'W pliku :index brakuje własności :property.', expandCollapse: 'Rozwiń/Zwiń', addEntity: 'Dodaj :entity', tooLong: 'Wartość pola jest za długa, powinna zawierać :max lub mniej liter.', invalidFormat: 'Pole zawiera wartość w nieprawidłowym formacie lub zabronione znaki.', confirmChangeLibrary: 'Stracisz całą pracę wykonaną w bieżącym typie zasobu. Czy na pewno chcesz zmienić typ zasobu?', commonFields: 'Własne komunikaty i tłumaczenia', commonFieldsDescription: 'Tutaj możesz edytować ustawienia lub przetłumaczyć teksty użyte w tym zasobie.', uploading: 'Dodawanie, proszę czekać...', noFollow: 'Nie można śledzić pola ":path".', editCopyright: 'Edytuj prawa autorskie', close: 'Zamknij', tutorial: 'Instrukcja', editMode: 'Tryb edycji', listLabel: 'Lista', uploadError: 'Błąd podczas dodawnia', fileToLarge: 'Plik, który chcesz przesłać, może być zbyt duży.', unknownFileUploadError: 'Nieznany błąd przesyłania plików', noSemantics: 'Błąd, nie można załadować formularza typu zasobu.', editImage: 'Edytuj obraz', saveLabel: 'Zapisz', cancelLabel: 'Anuluj', resetToOriginalLabel: 'Resetuj do oryginału', loadingImageEditor: 'Wczytywanie edytora obrazów, proszę czekać...', selectFiletoUpload: 'Wybierz plik, który chcesz dodać', or: 'lub', enterAudioUrl: 'Edytuj źródło audio', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Wklej link lub inne źródło pliku audio.', enterVideoTitle: 'Wklej link YouTube lub dodaj plik wideo', uploadAudioTitle: 'Dodaj plik audio', uploadVideoTitle: 'Dodaj plik wideo', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Wstaw', cancel: 'Anuluj', height: 'długość', width: 'szerokość', textField: 'pole tekstowe', numberField: 'ilość pól', orderItemUp: 'Uporządkuj rosnąco', orderItemDown: 'Uporządkuj malejąco', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Usuń', hubPanelLabel: 'Wybierz typ zasobu', importantInstructions: 'Ważne instrukcje', showImportantInstructions: 'Pokaż instrukcje', hideImportantInstructions: 'Ukryj instrukcje', hide: 'Ukryj', example: 'Przykład', createContentTabLabel: 'Utwórz nowy', uploadTabLabel: 'Dodaj', uploadPlaceholder: 'Nie wybrano pliku', uploadInstructionsTitle: 'Dodaj plik h5.', uploadInstructionsContent: 'Możesz rozpocząć korzystając z przykładów, które znajdziesz tutaj H5P.org.', uploadFileButtonLabel: 'Dodaj plik', uploadFileButtonChangeLabel: 'Zmień plik', uploadingThrobber: 'Trwa dodawanie...', uploadSuccess: ':title został poprawnie załadowany!', unableToInterpretError: 'Nie można zinterpretować rezultatu.', unableToInterpretSolution: 'Sprawdź dziennik błędów serwera.', h5pFileWrongExtensionTitle: 'Nie można przesłać wybranego pliku', h5pFileWrongExtensionContent: 'Dopuszczalne są tylko pliki z rozszerzeniem .h5p.', h5pFileValidationFailedTitle: 'Wybrany plik H5P może być nieprawidłowy.', h5pFileValidationFailedContent: 'Upewnij się, że przesyłane pliki zawierają prawidłową treść H5P. Pliki zawierające tylko biblioteki powinny być dodawane z formularza bibliotek H5P.', h5pFileUploadServerErrorTitle: 'Nie można przesłać pliku H5P', h5pFileUploadServerErrorContent: 'Wystąpił nieoczekiwany błąd. Sprawdź dziennik błędów serwera więcej szczegółów.', contentTypeSectionAll: 'Wszystkie typy zasobu', searchResults: 'Wyniki wyszukiwania', contentTypeSearchFieldPlaceholder: 'Szukaj', contentTypeInstallButtonLabel: 'Instaluj', contentTypeInstallingButtonLabel: 'Instalowanie', contentTypeUseButtonLabel: 'Użyj', contentTypeDetailButtonLabel: 'Szczegóły', contentTypeUpdateButtonLabel: 'Aktualizuj', contentTypeUpdatingButtonLabel: 'Aktualizuj', contentTypeGetButtonLabel: 'Pobrane', contentTypeBackButtonLabel: 'Powrót', contentTypeIconAltText: 'Ikona', contentTypeInstallSuccess: ':contentType instalacja zakończona sukcesem!', contentTypeUpdateSuccess: ':contentType aktualizacja zakończona!', contentTypeInstallError: ':contentType nie może zostać zainstalowana. Skontaktuj się z administratorem.', contentTypeLicensePanelTitle: 'Licencja', contentTypeDemoButtonLabel: 'Zasób przykładowy', numResults: ':num wyników', show: 'Pokaż', recentlyUsedFirst: 'Najpierw ostatnio używane', popularFirst: 'Najpierw popularne', newestFirst: 'Najpierw najnowsze', aToZ: 'A do Z', noResultsFound: 'Brak wyników', noResultsFoundDesc: 'Żaden typ zasobu nie spełnia kryteriów wyszukiwania.', readMore: 'Czytaj więcej', readLess: 'Czytaj mniej', contentTypeOwner: 'Przez właściciela', contentTypeUnsupportedApiVersionTitle: 'Ten typ zasobu wymaga nowszej wersji podstawowej', contentTypeUnsupportedApiVersionContent: 'Aby uzyskać niezbędne aktualizacje, skontaktuj się z administratorem systemu', contentTypeUpdateAvailable: 'Dostępna aktualizacja', contentTypeRestricted: 'Zablokowany typ zasobu', contentTypeRestrictedDesc: 'Użycie tego typu zasobu zostało zablokowane przez administratora.', contentTypeNotInstalled: 'Typ zasobu nie jest zainstalowany', contentTypeNotInstalledDesc: 'Nie masz uprawnień do instalowania typów zasobu.', theContentType: 'Typ zasobu', currentMenuSelected: 'obecny wybór', errorCommunicatingHubTitle: 'Nie można skomunikować się z hubem.', errorCommunicatingHubContent: 'Wystąpił błąd. Proszę spróbuj ponownie.', warningNoContentTypesInstalled: 'Nie masz zainstalowanych żadnych typów zasobu.', warningChangeBrowsingToSeeResults: 'Kliknij przycisk Wszystko, aby wyświetlić listę wszystkich typów zasobu, które można zainstalować.', warningUpdateAvailableTitle: 'Dostępna jest nowa wersja :contentType.', warningUpdateAvailableBody: 'Zaktualizuj do najnowszej wersji, aby uzyskać pełną funkcjonalność.', licenseDescription: 'Niektóre szczegóły licencji są wymienione poniżej. Kliknij ikonę informacji powyżej, aby przeczytać oryginalny tekst licencji.', licenseModalTitle: 'Szczegóły licencji', licenseModalSubtitle: 'Wybierz licencję, aby wyświetlić informacje o prawidłowym użyciu', licenseUnspecified: 'Nieokreślony', licenseCanUseCommercially: 'Można wykorzystywać do celów komercyjnych', licenseCanModify: 'Można modyfikować', licenseCanDistribute: 'Można rozpowszechniać', licenseCanSublicense: 'Można zmieniać licencję', licenseCanHoldLiable: 'Autor odpowiada za treść', licenseCannotHoldLiable: 'Autor nie odpowiada za treść', licenseMustIncludeCopyright: 'Trzeba dołączyć informację o prawach autorskich', licenseMustIncludeLicense: 'Trzeba dołączyć licencję', licenseFetchDetailsFailed: 'Nie udało się pobrać informacji o licencji', imageLightboxTitle: 'Obrazy', imageLightBoxProgress: ':num z :total', nextImage: 'Następny obraz', previousImage: 'Poprzedni obraz', screenshots: 'Miniatury', reloadButtonLabel: 'Przeładować', videoQuality: 'Etykieta jakości wideo', videoQualityDescription: 'Ta etykieta pomaga użytkownikowi zorientować się w jakości wideo, np. 1080p, 720p, HD lub mobilne', videoQualityDefaultLabel: 'Jakość :index', noContentTypesAvailable: 'Żaden typ zasobu nie jest dostępny', noContentTypesAvailableDesc: 'Twoja strona nie może połączyć się z H5P.org, aby wyświetlić dostępne typy zasobu.', contentTypeCacheOutdated: 'Lista typów zasobu jest nieaktualna', contentTypeCacheOutdatedDesc: 'Twoja strona nie może połączyć się z H5P.org, aby wyświetlić dostępne aktualizacje typów zasobu. Aktualizowanie ani instalowanie typów zasobu nie jest teraz możliwe.', tryAgain: 'Spróbuj ponownie', getHelp: 'Pomoc', untitled: 'Bez tytułu :libraryTitle', title: 'Tytuł', metadata: 'Metadane', addTitle: 'Dodaj tytuł', usedForSearchingReportsAndCopyrightInformation: 'Używany w wyszukiwaniu, raportach i informacji o prawach autorskich', metadataSharingAndLicensingInfo: 'Metadane (informacje o udostępnianiu i licencji)', fillInTheFieldsBelow: 'Wypełnij poniższe pola', saveMetadata: 'Zapisz metadane', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Dodaj nową zmianę', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Zarejestruj tę zmianę', newChangeHasBeenLogged: 'Nowa zmiana została zarejestrowana', loggedChanges: 'Zarejestrowane zmiany', noChangesHaveBeenLogged: 'Nie ma zarejestrowanych zmian', errorHeader: 'Wystąpił błąd', errorCalculatingMaxScore: 'Nie udało się obliczyć maksymalnego wyniku dla tego zasobu, zatem został on ustalony na 0. Jeśli to błąd, skontaktuj się z administratorem.', maxScoreSemanticsMissing: 'W zasobie nie znaleziono spodziewanej semantyki.', copyButton: 'Kopiuj', copiedButton: 'Skopiowane', pasteButton: 'Wklej', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Skopiuj zasób H5P do schowka', copiedToClipboard: 'Zasób skopiowany do schowka', pasteFromClipboard: 'Wklej zasób H5P ze schowka', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'W schowku nie ma zasobu H5P', pasteError: 'Nie można wkleić ze schowka', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: "Unfortunately, the selected content type '%lib' isn't installed on this system.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\rH5P.org.', uploadFileButtonLabel: 'Cargar un ficheiro', uploadFileButtonChangeLabel: 'Cambiar ficheiro', uploadingThrobber: 'Cargando...', uploadSuccess: ':title cargouse correctamente!', unableToInterpretError: 'Non se pode interpretar a resposta.', unableToInterpretSolution: 'Por favor, comproba o teu rexistro de erros.', h5pFileWrongExtensionTitle: 'Non se puido cargar o ficheiro seleccionado', h5pFileWrongExtensionContent: 'Só se permiten ficheiros coa extensión .h5p.', h5pFileValidationFailedTitle: 'Non se puido validar o ficheiro H5P.', h5pFileValidationFailedContent: 'Asegúrate de que o H5P que cargaches teña contido H5P válido. Os ficheiros H5P' + ' que conteñan so librerías deberían cargarse na páxina de Librerías H5P.', h5pFileUploadServerErrorTitle: 'Non se puido cargar o ficheiro H5P', h5pFileUploadServerErrorContent: 'Ocorreu un erro inesperado. Comproba o teu rexistro de error para' + ' máis detalles.', contentTypeSectionAll: 'Todos os Tipos de Contido', searchResults: 'Resultados da Busca', contentTypeSearchFieldPlaceholder: 'Buscar Tipos de Contido', contentTypeInstallButtonLabel: 'Instalar', contentTypeInstallingButtonLabel: 'Instalando', contentTypeUseButtonLabel: 'Usar', contentTypeDetailButtonLabel: 'Detalles', contentTypeUpdateButtonLabel: 'Actualizar', contentTypeUpdatingButtonLabel: 'Actualizando', contentTypeGetButtonLabel: 'Obter', contentTypeBackButtonLabel: 'Voltar', contentTypeIconAltText: 'Icona', contentTypeInstallSuccess: ':contentType instalado correctamente!', contentTypeUpdateSuccess: ':contentType actualizado correctamente!', contentTypeInstallError: 'Non se puido instalar :contentType. Contacta co teu administrador.', contentTypeLicensePanelTitle: 'Licenza', contentTypeDemoButtonLabel: 'Demostración do contido', numResults: ':num resultados', show: 'Amosar', recentlyUsedFirst: 'Primeiro os Usados Recentemete', popularFirst: 'Primeiro os máis Populares', newestFirst: 'Primeiro os máis Recentes', aToZ: 'A ao Z', noResultsFound: 'Non se atoparon resultados', noResultsFoundDesc: 'Non hai tipos de contido que coincidan cos teus criterios de busca.', readMore: 'Ler máis', readLess: 'Ler menos', contentTypeOwner: 'Por :owner', contentTypeUnsupportedApiVersionTitle: 'Este tipo de contido require una versión do núcleo máis moderna', contentTypeUnsupportedApiVersionContent: 'Contacta co administrador do sistema para que faga as actualizacións necesarias', contentTypeUpdateAvailable: 'Actualización dispoñible', contentTypeRestricted: 'Tipo de contido restrinxido', contentTypeRestrictedDesc: 'Un administrador restrinxiu o uso deste tipo de contido.', contentTypeNotInstalled: 'Tipo de contido non instalado', contentTypeNotInstalledDesc: 'Non tes permiso para instalar tipos de contido.', theContentType: 'o tipo de contido', currentMenuSelected: 'selección actual', errorCommunicatingHubTitle: 'Imposible comunicarse co hub.', errorCommunicatingHubContent: 'Ocorreu un erro. Por favor, téntao de novo.', warningNoContentTypesInstalled: "Non tes ningún tipo de contido instalado.", warningChangeBrowsingToSeeResults: 'Preme en Todos para ver unha lista de todos os tipos de contido que podes instalar.', warningUpdateAvailableTitle: 'Está dispoñible unha nova versión de :contentType.', warningUpdateAvailableBody: 'Actualiza á nova versión para mellorar a túa experiencia.', licenseDescription: 'Algunhas das características desta licenza indícanse na parte inferior. Preme na icona de información da parte superior para ler o texto orixinal da licenza.', licenseModalTitle: 'Detalles da Licenza', licenseModalSubtitle: 'Seleciona a licenza para ver información sobre o seu uso axeitado', licenseUnspecified: 'Non especificado', licenseCanUseCommercially: 'Pódese usar comercialmente', licenseCanModify: 'Pódese modificar', licenseCanDistribute: 'Pódese distribuir', licenseCanSublicense: 'Pódese sublicenciar', licenseCanHoldLiable: 'Pódede esixir responsabilidade', licenseCannotHoldLiable: 'Non se pode esixir responsabilidade', licenseMustIncludeCopyright: 'Debe incluir copyright', licenseMustIncludeLicense: 'Debe incluir licenza', licenseFetchDetailsFailed: 'Non se puideron descargar os detalles da licenza', imageLightboxTitle: 'Imaxes', imageLightBoxProgress: ':num de :total', nextImage: 'Imaxe seguinte', previousImage: 'Imaxe anterior', screenshots: 'Capturas de Pantalla', reloadButtonLabel: 'Recargar', videoQuality: 'Etiqueta de calidade de vídeo', videoQualityDescription: 'Esta etiqueta axuda ao usuario a identificar a calidade de vídeo actual. P.e. 1080p, 720p, HD ou Móbil', videoQualityDefaultLabel: 'Calidade :index', noContentTypesAvailable: 'Non hai tipos de contido dispoñibles', noContentTypesAvailableDesc: 'O teu sitio está a ter dificultades para conectarse á H5P.org e listar os tipos de contido dispoñibles.', contentTypeCacheOutdated: 'A lista de tipos de contido non está actualizada', contentTypeCacheOutdatedDesc: 'O teu sitio está a ter dificultades para conectarse á H5P.org e comprobar as actualizacións para os tipos de contido. É posible que non poidas actualizalos ou instalar tipos de contido novos.', tryAgain: 'Tenta de novo', getHelp: 'Obter axuda', untitled: 'Sen título :libraryTitle', title: 'Título', metadata: 'Metadatos', addTitle: 'Engadir título', usedForSearchingReportsAndCopyrightInformation: 'Usado para a busca, informes e información de copyright', metadataSharingAndLicensingInfo: 'Metadatos (información de licenciamento e compartición)', fillInTheFieldsBelow : 'Enche os campos da aparte inferior', saveMetadata: 'Gardar metadatos', addAuthor: 'Gardar autor', confirmRemoveAuthor: 'Seguro que queres borrar este autor?', addNewChange: 'Engadir novo cambio', confirmDeleteChangeLog: 'Seguro que queres borrar esta entrada no rexistro de cambios?', changelogDescription: 'Algunhas licenzas requiren que se rexistren ou amosen os cambios feitos ao traballo orixinal ou aos seus derivados. Podes rexistrar os cambios aquí por razóns de licenza ou so permitir que ti e outras personas vexan o rexistro dos cambios feitos a este contido.', logThisChange: 'Rexistrar este cambio', newChangeHasBeenLogged: 'Rexistrouse un novo cambio', loggedChanges: 'Cambos rexistrados', noChangesHaveBeenLogged: 'Non se rexistraron cambios', errorHeader: 'Ocorreu un erro', errorCalculatingMaxScore: 'Non se puido calcular a puntuación máxima para este contido. Asúmese que a puntuación máxima é 0. Contacta co teu administrador se isto non é correcto.', maxScoreSemanticsMissing: 'Non se puido atopar a semántica esperada no contido.', copyButton: 'Copiar', copiedButton: 'Copiado', pasteButton: 'Pegar', pasteAndReplaceButton: 'Pegar & Substituír', pasteContent: 'Substituír contido', confirmPasteContent: 'Ao facer isto, substituirase o contido actual co contido do portapapeis. Perderase o contido actual. Seguro que queres continuar?', confirmPasteButtonText: 'Substituír contido', copyToClipboard: 'Copiar contido H5P ao portapapeis', copiedToClipboard: 'Copiouse o contido ao portapapeis', pasteFromClipboard: 'Pegar contido H5P do portapapeis', pasteAndReplaceFromClipboard: 'Substituír contido existente co contido H5P do portapapeis', pasteNoContent: 'Non hai contido H5P no portapapeis', pasteError: 'Non se pode pegar do portapapeis', pasteContentNotSupported: 'O contido do portapapeis non está soportado neste contexto', pasteContentRestricted: 'Restrinxiuse o contido do portapapeis neste sitio', pasteTooOld: 'O contido do portapapeis pertence a unha versión anterior (:clip) do que se soporta neste contexto (:local), se fose posible, intenta actualizar o contido que queres pegar, volve a copialo e tenta pegalo aquí de novo.', pasteTooNew: 'O contido do portapapeis H5P é dunha versión máis alta (:clip) que a que se soporta neste contexto (:local), se fose posible, intenta actualizar o contido que queres pegar, volve a copialo e tenta pegalo aquí de novo.', ok: 'OK', avTablistLabel: 'Inserir usando', tabTitleBasicFileUpload: 'Carga de Ficheiros', tabTitleInputLinkURL: 'Enlace/URL', errorTooHighVersion: 'Os parámteros conteñen %used mais so se soportan %supported ou anteriores.', errorNotSupported: 'Os parámetros conteñen %used que non está soportado.', errorParamsBroken: 'Os parámetros están rotos.', libraryMissing: 'Falta a librería requirida %lib.', scriptMissing: 'Non se puido cargar o script de actualización para %lib.', language: 'Idioma', noLanguagesSupported: 'Non hai soporte para ningún idioma', changeLanguage: 'Cambiar idioma á :language?', thisWillPotentially: "Isto podería borrar todos os textos e as traducions. Non se pode desfacer. Non se cambiará o contido mesmo. Queres seguir?", notAllTextsChanged: 'Non se cambiaron todos os textos, so hai soporte parcial para o :language.', contributeTranslations: 'Se queres completar a tradución do :language podes informarte sobre como contribuír ás traducións de H5P', unknownLibrary: 'Desafortunadamente, o tipo de contido seleccionado \'%lib\' non está instalado neste sistema.', proceedButtonLabel: 'Seguir para gardar', enterFullscreenButtonLabel: 'Pasar a pantalla completa', exitFullscreenButtonLabel: 'Saír de pantalla completa', noContentHeader: 'Non atopas contido axeitado?', noContentSuggestion: 'Crea o teu propio!', tutorials: 'Titoriais', contentSectionAll: 'Todo o contido compartido', popularContent: 'Contido Popular', allPopular: 'Todo o Popular', newOnTheHub: 'Novo no Hub', allNew: 'Todo o Novo', filterBy: 'Filtar por', filter: 'Filtrar', filters: { level: { dropdownLabel: 'Nivel', dialogHeader: 'Seleccionar nivel educativo', dialogButtonLabel: 'Filtrar nivel educativo' }, language: { dropdownLabel: 'Idioma', dialogHeader: 'Seleccionar idioma(s)', dialogButtonLabel: 'Filtrar idiomas', searchPlaceholder: 'Escribe para buscar idiomas' }, reviewed: { dropdownLabel: 'Valorado', dialogHeader: 'Contido valorado', dialogButtonLabel: 'Filtrar', optionLabel: 'Amosar so contido valorado' }, contentTypes: { dropdownLabel: 'Tipos de Contido', dialogHeader: 'Seleccionar Tipo(s) de Contido', dialogButtonLabel: 'Filtrar Tipos de Contido', searchPlaceholder: 'Escribe para buscar tipos de contido' }, disciplines: { dropdownLabel: 'Materia', dialogHeader: 'Selecciona a túa Materia', dialogButtonLabel: 'Filtrar Materias', searchPlaceholder: 'Escribe para buscar materias' }, licenses: { dropdownLabel: 'Licenza', dialogHeader: 'Seleccionar dereitos de uso preferidos', dialogButtonLabel: 'Filtrar licenzas', options: { modified: 'Pódese modificar', commercial: 'Permite uso comercial' } } }, clearFilters: 'Borrar todos os filtros', contentSearchFieldPlaceholder: 'Buscar Contido...', loadingContentTitle: 'Estamos a cargar contido para ti...', loadingContentSubtitle: 'Agarda, por favor', by: 'Por', dropdownButton: 'Abrir despregable', paginationNavigation: 'Navegacion en páxinas', page: 'Páxina', currentPage: 'Páxina actual', nextPage: 'Ir á páxina seguinte', previousPage: 'Ir á páxina anterior', contentPreviewButtonLabel: 'Vista previa', contentDownloadButtonLabel: 'Obter contido', reuseContentTabLabel: 'Obter contido compartido', contentPublisherPanelHeader: 'Información editorial', noContentFoundDesc: 'Non hai contido que coincida cos teus criterios de busca.', h5pType: 'Tipo H5P', level: 'Nivel', size: 'Tamaño', failedFetchingData: 'Non se puideron obter os datos', filterErrorMessage: 'Algo saleu mal. Por favor, volve a cargar a páxina.', in: 'en', navigateToParent: 'Navegar ao pai', a11yTitleShowLabel: 'Amosar etiqueta para AT', a11yTitleHideLabel: 'Agochar etiqueta para AT', reuseSuccess: 'Importouse :title correctamente do hub H5P.', }; PK*\a{M?M?(h5plib/v127/joubel/editor/language/fi.jsnu[H5PEditor.language.core = { missingTranslation: '[Missing translation :key]', loading: 'Lataa, odota...', selectLibrary: 'Valitse haluamasi kirjasto.', unknownFieldPath: 'Ei löytynyt ":path".', notImageField: '":path" ei ole kuva.', notImageOrDimensionsField: '":path" ei ole kuva eikä mitta.', requiredProperty: ':property on pakollinen ja sillä on oltava arvo.', onlyNumbers: ':property täytyy sisältää vain numeroita.', illegalDecimalNumber: ':property voi sisältää vain numeroita joissa on maksimissaan :decimals desimaalia.', exceedsMax: ':property on suurempi kuin enimmäisarvo :max.', listExceedsMax: 'Lista on pidempi kuin enimmäismäärä :max.', belowMin: ':property on pienempi kuin vähimmäismäärä :min.', listBelowMin: 'Listassa täytyy olla vähintään :min kohtaa, jotta sisältö toimisi oikein.', outOfStep: ':property arvon askelmuutos voi olla ainoastaan :step.', add: 'Lisää', addFile: 'Lisää tiedosto', removeFile: 'Poista tiedosto', confirmRemoval: 'Oletko varma että haluat poistaa - :type?', removeImage: 'Poista kuva', confirmImageRemoval: 'Kuva poistetaan. Oletko varma?', changeFile: 'Vaihda tiedosto', changeLibrary: 'Vaihda sisältötyyppi?', semanticsError: 'Semanttinen virhe: :error', missingProperty: 'Kentästä :index puuttuu sen :property ominaisuus.', expandCollapse: 'Laajenna/Kutista', addEntity: 'Lisää :entity', tooLong: 'Kentän arvo on liiaan pitkä. Saa sisältää :max kirjainta tai vähemmän.', invalidFormat: 'Kentän arvo on väärässä muodossa tai sisältää kiellettyjä merkkejä.', confirmChangeLibrary: 'Tämä hävittää tekemäsi työn nykyiselle sisältötyypille. Oletko varma, että haluat vaihtaa sisältötyyppiä?', commonFields: 'Omat tekstit ja käännökset', commonFieldsDescription: 'Täällä voit muuttaa asetuksia tai kääntää tekstejä tälle sisällölle.', uploading: 'Lataa, odota...', noFollow: 'Ei pysty seuraamaan kenttää ":path".', editCopyright: 'Muuta tekijänoikeustietoa', close: 'Sulje', tutorial: 'Opas', editMode: 'Muokkaustila', listLabel: 'Lista', uploadError: 'Virhe tiedoston latauksessa', fileToLarge: 'Tiedosto jota yrität ladata saattaa olla liian suuri.', unknownFileUploadError: 'Tuntematon virhe latauksessa', noSemantics: 'Virhe, sisältötyypin muotoa ei pystytty lataamaan.', editImage: 'Muokkaa kuvaa', saveLabel: 'Tallenna', cancelLabel: 'Peruuta', resetToOriginalLabel: 'Palauta alkuperäiseksi', loadingImageEditor: 'Lataa kuvaeditoria, odota...', selectFiletoUpload: 'Valitse ladattava tiedosto', or: 'tai', enterAudioUrl: 'Anna äänen osoite', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Liitä linkki tai muu äänen osoite', enterVideoTitle: 'Liitä YouTube linkki tai muu videon osoite', uploadAudioTitle: 'Lataa äänitiedosto', uploadVideoTitle: 'Lataa videotiedosto', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Lisää', cancel: 'Peruuta', height: 'korkeus', width: 'leveus', textField: 'tekstikenttä', numberField: 'numerokenttä', orderItemUp: 'Järjestä kohde ylemmäksi', orderItemDown: 'Järjestä kohde alemmaksi', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Poista kohde', hubPanelLabel: 'Valitse sisältötyyppi', importantInstructions: 'Tärkeitä ohjeita', showImportantInstructions: 'Näytä ohjeet', hideImportantInstructions: 'Piilota tärkeät ohjeet', hide: 'Piilota', example: 'Esimerkki', createContentTabLabel: 'Luo sisältöä', uploadTabLabel: 'Lataa', uploadPlaceholder: 'Ei tiedostoa valittuna', uploadInstructionsTitle: 'Lataa H5P tiedosto.', uploadInstructionsContent: 'Sisältöesimerkkejä löytyy osoitteesta H5P.org.', uploadFileButtonLabel: 'Lataa tiedosto', uploadFileButtonChangeLabel: 'Vaihda tiedosto', uploadingThrobber: 'Lataa...', uploadSuccess: ':title ladattiin onnistuneesti!', unableToInterpretError: 'Vastausta ei pystytty tulkitsemaan.', unableToInterpretSolution: 'Ole hyvä ja tarkista virhelogi.', h5pFileWrongExtensionTitle: 'Valittua tiedostoa ei pystytty lataamaan', h5pFileWrongExtensionContent: 'Vain .h5p päätteiset tiedostot ovat sallittuja.', h5pFileValidationFailedTitle: 'H5P tiedostoa ei pystytty varmistamaan.', h5pFileValidationFailedContent: 'Varmista että ladattu H5P tiedosto sisältää H5P sisältöä. H5P tiedostot joissa on ainoastaan kirjastoja täytyy ladata H5P Libraries sivulla.', h5pFileUploadServerErrorTitle: 'H5P tiedostoa ei pystytty lataamaan', h5pFileUploadServerErrorContent: 'Odottamaton virhe. Tarkista palvelinlogisi lisätietoja varten.', contentTypeSectionAll: 'Kaikki sisältötyypit', searchResults: 'Hakutulokset', contentTypeSearchFieldPlaceholder: 'Etsi sisältötyyppejä', contentTypeInstallButtonLabel: 'Asenna', contentTypeInstallingButtonLabel: 'Asentaa', contentTypeUseButtonLabel: 'Valitse', contentTypeDetailButtonLabel: 'Yksityiskohdat', contentTypeUpdateButtonLabel: 'Päivitä', contentTypeUpdatingButtonLabel: 'Päivittää', contentTypeGetButtonLabel: 'Hae', contentTypeBackButtonLabel: 'Takaisin', contentTypeIconAltText: 'Ikoni', contentTypeInstallSuccess: ':contentType onnistuneesti asennettu!', contentTypeUpdateSuccess: ':contentType onnistuneesti päivitetty!', contentTypeInstallError: ':contentType ei pystytty asentamaan. Ota yhteys pääkäyttäjään.', contentTypeLicensePanelTitle: 'Lisenssi', contentTypeDemoButtonLabel: 'Sisältödemo', numResults: ':num hakutulosta', show: 'Show', recentlyUsedFirst: 'Viimeksi käytetty ensimmäisenä', popularFirst: 'Suosituin ensimmäisenä', newestFirst: 'Uusin ensimmäisenä', aToZ: 'A-Z', noResultsFound: 'ei hakutuloksia', noResultsFoundDesc: 'Ei löydetty sisältötyyppiä joka vastaisi hakuasi.', readMore: 'Lue lisää', readLess: 'Lue vähemmän', contentTypeOwner: 'Tekijä: :owner', contentTypeUnsupportedApiVersionTitle: 'Tämä sisältötyyppi vaatii uudemman version H5P ytimestä', contentTypeUnsupportedApiVersionContent: 'Ota yhteyttä järjestelmänvalvojaan saadaksesi tarvittavat päivitykset', contentTypeUpdateAvailable: 'Päivitys saatavilla', contentTypeRestricted: 'Rajoitettu sisältötyyppi', contentTypeRestrictedDesc: 'Tämän sisältötyypin käyttöä on rajoitettu järjestelmänvalvojan toimesta.', contentTypeNotInstalled: 'Sisältötyyppiä ei ole asennettu', contentTypeNotInstalledDesc: 'Sinulla ei ole lupaa asentaa sisältötyyppejä.', theContentType: 'sisältötyyppi', currentMenuSelected: 'nykyinen valinta', errorCommunicatingHubTitle: 'Yhteyttä hubiin ei saatu muodostettua.', errorCommunicatingHubContent: 'Virhe tapahtui. Yritä uudelleen.', warningNoContentTypesInstalled: 'Sinulla ei ole yhtään sisältötyyppiä asennettuna.', warningChangeBrowsingToSeeResults: 'Klikkaa Kaikki saadaksesi listan kaikista asennettavista sisältötyypeistä.', warningUpdateAvailableTitle: 'Sisällöstä :contentType on uusi versio saatavilla.', warningUpdateAvailableBody: 'Päivitä viimeisimpään versioon parannetuilla ominaisuuksilla.', licenseDescription: 'Tämän lisenssin jotkin ominaisuudet on annettu alempana. Klikkaa infoikonia lukeaksi alkuperäisen lisenssitekstin.', licenseModalTitle: 'Lisenssin yksityiskohdat', licenseModalSubtitle: 'Valitse lisenssi tarkastellaksesi tietoa oikeasta käytöstä', licenseUnspecified: 'Määrittelemätön', licenseCanUseCommercially: 'Saa käyttää kaupallisesti', licenseCanModify: 'Saa muokata', licenseCanDistribute: 'Saa jakaa', licenseCanSublicense: 'Saa alilisensoida', licenseCanHoldLiable: 'Ei vastuuvapautta', licenseCannotHoldLiable: 'Vastuuvapaus', licenseMustIncludeCopyright: 'Tekijänoikeus sisällytettävä', licenseMustIncludeLicense: 'Lisenssi sisällyttettävä', licenseFetchDetailsFailed: 'Lisenssin yksityiskohtien hakeminen epäonnistui', imageLightboxTitle: 'Kuvat', imageLightBoxProgress: ':num/:total', nextImage: 'Seuraava kuva', previousImage: 'Edellinen kuva', screenshots: 'Kuvakaappaukset', reloadButtonLabel: 'Lataa uudelleen', videoQuality: 'Videon laadun nimike', videoQualityDescription: 'Tämä nimike auttaa käyttäjää tunnistamaan videon nykyisen laadun. Esim. 1080p, 720p, HD tai Mobiili', videoQualityDefaultLabel: 'Laatu :index', noContentTypesAvailable: 'Sisältötyyppejä ei saatavilla.', noContentTypesAvailableDesc: 'Sivustollasi on ongelmia yhdistettäessä h5p.org-sivustoon ja sisältötyyppien listaus ei tästä syystä toimi.', contentTypeCacheOutdated: 'Sisältötyyppilista on vanhentunut', contentTypeCacheOutdatedDesc: 'Sivustollasi on ongelmia yhdistettäessä h5p.org-sivustoon tarkistaakseen onko uusia sisältötyyppipäivityksiä saatavilla. Et välttämättä pysty päivittämään vanhoja etkä lataamaan uusia sisältötyyppejä.', tryAgain: 'Yritä uudelleen', getHelp: 'Apu', untitled: 'Untitled :libraryTitle', title: 'Otsikko', metadata: 'Metadata', addTitle: 'Lisää otsikko', usedForSearchingReportsAndCopyrightInformation: 'Käytetään hakemiseen, raportointiin ja copyright-tietoihin.', metadataSharingAndLicensingInfo: 'Metadata (jakamisen ja lisenssin tiedot)', fillInTheFieldsBelow: 'Täytä alla olevat kentät', saveMetadata: 'Tallenna metadata', addAuthor: 'Tallenna tekijä', confirmRemoveAuthor: 'Oletko varma että halua että haluat poistaa tämän tekijän?', addNewChange: 'Lisää uusi muutos', confirmDeleteChangeLog: 'Oletko varma että haluat poistaa tämän muutoslogitietueen?', changelogDescription: 'Jotkut lisenssit vaativat että alkuperäiseen työhön tehtävä muutokset merkitään logiin ja esitetään. Voit merkitä nämä muutokset logiin tänne tai vain itseäsi varten jotta pysyt kärryillä mitä tietoja olet muuttanut.', logThisChange: 'Kirjoita tämä muutos logiin', newChangeHasBeenLogged: 'Uusi muutos kirjattiin logiin', loggedChanges: 'Muutokset logitettiin.', noChangesHaveBeenLogged: 'Yhtään muutosta ei kirjoitettu logiin', errorHeader: 'Tapahtui virhe', errorCalculatingMaxScore: 'Maksimiarvosanaa ei pystytty laskemaan tälle sisällölle, täten maksimiarvosanaksi asetetaan 0. Olethan yhteydessä ylläpitäjiin mikäli tämä on virhetilanne.', maxScoreSemanticsMissing: 'Odotettuja semantiikkoja ei löydetty aineistosta.', copyButton: 'Kopioi', copiedButton: 'Kopioitu', pasteButton: 'Liitä', pasteAndReplaceButton: 'Liitä & Korvaa', pasteContent: 'Korvaa sisältö', confirmPasteContent: 'Jos teet tämän niin korvaat nykyisen sisällön sisällöllä jonka olet liittämässä leikepöydältä. Nykyinen sisältö menetetään pysyvästi. Oletko varma että haluat jatkaa?', confirmPasteButtonText: 'Korvaa sisältö', copyToClipboard: 'Kopioi H5P sisältö leikepöydälle', copiedToClipboard: 'H5P sisältö on nyt kopioitu leikepöydälle', pasteFromClipboard: 'Liitä H5P sisältö leikepöydältä', pasteAndReplaceFromClipboard: 'Korvaa edellinen sisältö leikepöydän H5P sisällöllä', pasteNoContent: 'Leikepöydältä ei löytynyt H5P-sisältöä', pasteError: 'Ei pystytä liittämään leikepöydältä', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Lisää käyttäen', tabTitleBasicFileUpload: 'Tiedoston lähetys', tabTitleInputLinkURL: 'Linkki/URL-osoite', errorTooHighVersion: 'Parametrit sisältävät %used mutta vain %supported tai aikaisempi versio on tuettu', errorNotSupported: 'Parametrit sisältävät %used joita ei ole tuettu', errorParamsBroken: 'Parametrit ovat rikki', libraryMissing: 'Vaadittu kirjasto %lib puuttuu.', scriptMissing: 'Päivitysskriptiä ei pystytty lataamaan %lib sisältötyypille', language: 'Kieli', noLanguagesSupported: 'Ei tuettuja kieliä', changeLanguage: 'Vaihda kieleksi :language?', thisWillPotentially: 'Tämä mahdollisesti nollaa kaikki tähän asti tehdy kielikäännösmuutokset. Tätä ei voi perua. Itse aineisto ei muutu. Haluatko varmasti jatkaa?', notAllTextsChanged: 'Kaikkia tekstejä ei voitu vaihtaa :language kielelle koska niiden käännökset puuttuvat', contributeTranslations: 'Jos haluat auttaa käännöstyössä löydät lisätietoja täältä:H5P käännöksissä auttaminen', unknownLibrary: "Valitettavasti valittua sisältötyyppiä '%lib' ei ole asennettuna tähän järjestelmään. Olethan yhteydessä ylläpitoon.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\,V%FBFB(h5plib/v127/joubel/editor/language/pt.jsnu[H5PEditor.language.core = { missingTranslation: '[Tradução em falta :key]', loading: 'A carregar. Por favor, aguarde...', selectLibrary: 'Selecione a biblioteca que pretende usar no seu conteúdo.', unknownFieldPath: 'Não foi possível encontrar ":path".', notImageField: '":path" não é uma imagem.', notImageOrDimensionsField: '":path" não é uma imagem ou campo de dimensão.', requiredProperty: ':property é obrigatória e deve ter um valor.', onlyNumbers: 'O valor de :property apenas pode conter números.', illegalDecimalNumber: ':property apenas pode conter números com o máximo de :decimals casas decimais.', exceedsMax: 'O valor de :property excede o máximo de :max.', listExceedsMax: 'A lista excede o número máxima de :max itens.', belowMin: 'O valor de :property é menor que o mínimo de :min.', listBelowMin: 'A lista precisa de pelo menos :min itens para que o conteúdo funcione corretamente.', outOfStep: 'O valor de :property apenas pode ser mudado numa variação de :step.', add: 'Adicionar', addFile: 'Adicionar ficheiro', removeFile: 'Remover ficheiro', confirmRemoval: 'Tem a certeza de que pretende remover :type?', removeImage: 'Remover imagem', confirmImageRemoval: 'Esta ação removerá a sua imagem. Tem a certeza de que pretende continuar?', changeFile: 'Alterar ficheiro', changeLibrary: 'Pretende alterar o tipo de conteúdo?', semanticsError: 'Erro de semântica: :error', missingProperty: 'O campo :index não contém a propriedade :property.', expandCollapse: 'Expandir/Contrair', addEntity: 'Adicionar :entity', tooLong: 'O valor do campo é muito longo. Deve conter :max caracteres no máximo.', invalidFormat: 'O valor do campo contém um formato inválido ou caracteres não permitidos.', confirmChangeLibrary: 'Se continuar, perderá todo o trabalho concluído com o tipo atual de conteúdo. Tem a certeza de que pretende alterar o tipo de conteúdo?', commonFields: 'Substituição de texto e traduções', commonFieldsDescription: 'Aqui pode editar as configurações ou traduzir textos usados neste conteúdo.', uploading: 'A enviar. Por favor, aguarde...', noFollow: 'Não é possível seguir o campo ":path".', editCopyright: 'Editar direitos de autor', close: 'Fechar', tutorial: 'Tutorial', editMode: 'Modo de edição', listLabel: 'Lista', uploadError: 'Ocorreu um erro ao enviar o ficheiro', fileToLarge: 'O ficheiro que está a tentar enviar talvez seja muito grande.', unknownFileUploadError: 'Erro desconhecido no envio do ficheiro', noSemantics: 'Ocorreu um erro. Não foi possível carregar o formulário do tipo de conteúdo.', editImage: 'Editar imagem', saveLabel: 'Guardar', cancelLabel: 'Cancelar', resetToOriginalLabel: 'Restabelecer o original', loadingImageEditor: 'A carregar o editor de imagem. Por favor, aguarde...', selectFiletoUpload: 'Selecione o ficheiro para enviar', or: 'ou', enterAudioUrl: 'Insira o URL do áudio', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Cole aqui a hiperligação do áudio', enterVideoTitle: 'Cole aqui o URL do vídeo ou a hiperligação do YouTube', uploadAudioTitle: 'Enviar ficheiro de áudio', uploadVideoTitle: 'Enviar ficheiro de vídeo', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Inserir', cancel: 'Cancelar', height: 'altura', width: 'largura', textField: 'campo de texto', numberField: 'campo numérico', orderItemUp: 'Mover item para cima', orderItemDown: 'Mover item para baixo', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Remover item', hubPanelLabel: 'Selecionar tipo de conteúdo', importantInstructions: 'Instruções importantes', showImportantInstructions: 'Mostrar instruções', hideImportantInstructions: 'Ocultar instruções', hide: 'Ocultar', example: 'Exemplo', createContentTabLabel: 'Criar conteúdo', uploadTabLabel: 'Carregar', uploadPlaceholder: 'Nenhum ficheiro selecionado', uploadInstructionsTitle: 'Carregar um ficheiro H5P.', uploadInstructionsContent: 'Pode começar com exemplos existentes em H5P.org.', uploadFileButtonLabel: 'Carregar um ficheiro', uploadFileButtonChangeLabel: 'Alterar ficheiro', uploadingThrobber: 'A carregar...', uploadSuccess: ':title foi carregado com sucesso!', unableToInterpretError: 'Não foi possível interpretar a resposta.', unableToInterpretSolution: 'Por favor, verifique o registo de erros.', h5pFileWrongExtensionTitle: 'Não foi possível carregar o ficheiro', h5pFileWrongExtensionContent: 'Apenas são permitidos ficheiros com a extensão .h5p.', h5pFileValidationFailedTitle: 'Não foi possível validar o ficheiro H5P.', h5pFileValidationFailedContent: 'Certifique-se que o ficheiros H5P carregado possui conteúdo H5P válido. Ficheiros H5P com bibliotecas devem ser enviados através da página de Bibliotecas H5P.', h5pFileUploadServerErrorTitle: 'Não foi possível enviar o ficheiro H5P', h5pFileUploadServerErrorContent: 'Ocorreu um erro inesperado. Para mais informações, consulte o registo de erros do servidor.', contentTypeSectionAll: 'Todos os tipos de conteúdo', searchResults: 'Procurar resultados', contentTypeSearchFieldPlaceholder: 'Procurar por tipos de conteúdo', contentTypeInstallButtonLabel: 'Instalar', contentTypeInstallingButtonLabel: 'A instalar', contentTypeUseButtonLabel: 'Usar', contentTypeDetailButtonLabel: 'Detalhes', contentTypeUpdateButtonLabel: 'Atualizar', contentTypeUpdatingButtonLabel: 'A atualizar', contentTypeGetButtonLabel: 'Obter', contentTypeBackButtonLabel: 'Voltar', contentTypeIconAltText: 'Ícone', contentTypeInstallSuccess: ':contentType instalado com sucesso!', contentTypeUpdateSuccess: ':contentType atualizado com sucesso!', contentTypeInstallError: ':contentType não pôde ser instalado. Contacte o administrador.', contentTypeLicensePanelTitle: 'Licença', contentTypeDemoButtonLabel: 'Demonstração de conteúdo', numResults: ':num resultados', show: 'Mostrar', recentlyUsedFirst: 'Recentemente usados primeiro', popularFirst: 'Populares primeiro', newestFirst: 'Novos primeiro', aToZ: 'Ordem alfabética', noResultsFound: 'Nenhum resultado encontrado', noResultsFoundDesc: 'Não existe nenhum tipo de conteúdo que corresponda aos critérios da pesquisa.', readMore: 'Ver mais', readLess: 'Ver menos', contentTypeOwner: 'Por :owner', contentTypeUnsupportedApiVersionTitle: 'Este tipo de conteúdo requer uma nova versão do core', contentTypeUnsupportedApiVersionContent: 'Contacte o administrador de seu sistema para lhe disponibilize as atualizações necessárias', contentTypeUpdateAvailable: 'Atualização disponível', contentTypeRestricted: 'Tipo de conteúdo restrito', contentTypeRestrictedDesc: 'O uso deste tipo de conteúdo foi restringido pelo administrador.', contentTypeNotInstalled: 'Tipo de conteúdo não instalado', contentTypeNotInstalledDesc: 'Não tem permissão para instalar tipos de conteúdo.', theContentType: 'o tipo de conteúdo', currentMenuSelected: 'seleção atual', errorCommunicatingHubTitle: 'Não foi possível comunicar com o Hub.', errorCommunicatingHubContent: 'Ocorreu um erro. Por favor, tente novamente.', warningNoContentTypesInstalled: 'Nenhum tipo de conteúdo está instalado.', warningChangeBrowsingToSeeResults: 'Clique em todos para obter a lista de todos os conteúdos que pode instalar.', warningUpdateAvailableTitle: 'Está disponível uma nova versão de :contentType.', warningUpdateAvailableBody: 'Atualize para a última versão para uma melhor experiência.', licenseDescription: 'Algumas das características desta licença são indicadas abaixo. Clique no ícone de informações acima para ler o texto original da licença.', licenseModalTitle: 'Detalhes da licença', licenseModalSubtitle: 'Selecione uma licença para ver informações sobre o uso apropriado', licenseUnspecified: 'Não especificado', licenseCanUseCommercially: 'Pode usar comercialmente', licenseCanModify: 'Pode modificar', licenseCanDistribute: 'Pode distribuir', licenseCanSublicense: 'Pode sub-licenciar', licenseCanHoldLiable: 'Pode ser responsabilizado', licenseCannotHoldLiable: 'Não pode ser responsabilizado', licenseMustIncludeCopyright: 'Obrigatório incluir direitos de autor', licenseMustIncludeLicense: 'Obrigatório incluir licença', licenseFetchDetailsFailed: 'Ocorreu um erro na obtenção dos detalhes da licença', imageLightboxTitle: 'Imagens', imageLightBoxProgress: ':num de :total', nextImage: 'Imagem seguinte', previousImage: 'Imagem anterior', screenshots: 'Capturas de ecrã', reloadButtonLabel: 'Recarregar', videoQuality: 'Etiqueta da qualidade de vídeo', videoQualityDescription: 'Esta etiqueta ajuda o utilizador a identificar a qualidade atual do vídeo. Ex.: 1080p, 720p, HD ou Mobile', videoQualityDefaultLabel: 'Qualidade :index', noContentTypesAvailable: 'Nenhum tipo de conteúdo está disponível', noContentTypesAvailableDesc: 'O seu site está a ter dificuldades na ligação a H5P.org para obter a listagem os tipos de conteúdo disponíveis.', contentTypeCacheOutdated: 'Lista de tipos de conteúdo desatualizada', contentTypeCacheOutdatedDesc: 'O seu site está a ter dificuldades na ligação a H5P.org para verificar a existência de atualizações disponíveis. Pode não ser capaz de atualizar ou instalar novos tipos de conteúdo.', tryAgain: 'Tentar novamente', getHelp: 'Ajuda', untitled: 'Sem título :libraryTitle', title: 'Título', metadata: 'Metadados', addTitle: 'Adicionar título', usedForSearchingReportsAndCopyrightInformation: 'Usado para pesquisas, relatórios e informações de direitos de autor', metadataSharingAndLicensingInfo: 'Metadados (informações de partilha e licenciamento)', fillInTheFieldsBelow: 'Preencha os campos abaixo', saveMetadata: 'Guardar metadados', addAuthor: 'Guardar autor', confirmRemoveAuthor: 'Tem a certeza de que pretende remover este autor?', addNewChange: 'Adicionar nova alteração', confirmDeleteChangeLog: 'Tem a certeza de que pretende excluir esta entrada do registo de alterações?', changelogDescription: 'Algumas licenças exigem que sejam registadas e exibidas as alterações feitas no trabalho original ou derivados. Pode registar aqui as suas alterações por motivos de licenciamento ou apenas para permitir que possa, tal como outras pessoas, acompanhar as alterações feitas neste conteúdo.', logThisChange: 'Registar alteração', newChangeHasBeenLogged: 'A nova alteração foi guardada no registo', loggedChanges: 'Alterações registadas', noChangesHaveBeenLogged: 'Nenhuma alteração foi registada', errorHeader: 'Ocorreu um erro', errorCalculatingMaxScore: 'Não foi possível calcular a pontuação máxima para este conteúdo. A pontuação máxima é assumida como sendo 0. Se achar que não está correto, contacte o seu administrador.', maxScoreSemanticsMissing: 'Não foi possível encontrar a semântica esperada no conteúdo.', copyButton: 'Copiar', copiedButton: 'Copiado', pasteButton: 'Colar', pasteAndReplaceButton: 'Colar & Substituir', pasteContent: 'Substituir conteúdo', confirmPasteContent: 'Se continuar, irá substituir o conteúdo atual pelo conteúdo da área de transferência. O conteúdo atual será perdido. Tem a certeza de que pretende continuar?', confirmPasteButtonText: 'Substituir conteúdo', copyToClipboard: 'Copiar conteúdo H5P para a área de transferência', copiedToClipboard: 'O conteúdo foi copiado para a área de transferência', pasteFromClipboard: 'Colar conteúdo H5P da área de transferência', pasteAndReplaceFromClipboard: 'Substituir o conteúdo existente pelo conteúdo H5P da área de transferência', pasteNoContent: 'Nenhum conteúdo H5P na área de transferência', pasteError: 'Não foi possível colar', pasteContentNotSupported: 'O conteúdo que está a tentar colar não é suportado neste contexto', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'O conteúdo que está a tentar colar é de uma versão inferior (:clip) à versão suportada neste contexto (:local). Se possível, tente atualizar o conteúdo que deseja colar, copie-o novamente e tente colá-lo aqui.', pasteTooNew: 'O conteúdo que está a tentar colar é de uma versão superior (:clip) à versão suportada neste contexto (:local). Se possível, tente atualizar este conteúdo, e depois tente colar novamente.', ok: 'OK', avTablistLabel: 'Inserir usando', tabTitleBasicFileUpload: 'Carregar ficheiro', tabTitleInputLinkURL: 'Hiperligação/URL', errorTooHighVersion: 'Os parâmetros contêm %used mas apenas são suportados %supported ou anterior.', errorNotSupported: 'Os parâmetros contêm %used que não são suportados.', errorParamsBroken: 'Os parâmetros estão corrompidos.', libraryMissing: 'Está em falta a livraria obrigatória %lib.', scriptMissing: 'Não foi possível carregar o script de actualizações de %lib.', language: 'Idioma', noLanguagesSupported: 'Nenhum idioma suportado', changeLanguage: 'Alterar idioma para :language?', thisWillPotentially: 'Isto redefinirá potencialmente todos os textos e traduções. Não pode desfazer esta ação. O conteúdo em si não será alterado. Pretende prosseguir?', notAllTextsChanged: 'Nem todos os textos foram alterados. Existe apenas uma tradução parcial para :language.', contributeTranslations: 'Se pretende completar a tradução para :language, clique para obter informações sobre contribuir com traduções para H5P', unknownLibrary: "Infelizmente, o tipo de conteúdo selecionado '%lib' não está instalado neste sistema.", proceedButtonLabel: 'Prosseguir para guardar', enterFullscreenButtonLabel: 'Mostrar em ecrã inteiro', exitFullscreenButtonLabel: 'Sair de ecrã inteiro', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\*rCC(h5plib/v127/joubel/editor/language/fr.jsnu[H5PEditor.language.core = { missingTranslation: '[Traduction manquante :key]', loading: 'Chargement en cours, merci de patienter...', selectLibrary: 'Sélectionnez une activité pour votre exercice.', unknownFieldPath: 'Impossible de trouver ":path".', notImageField: '":path" n\'est pas une image.', notImageOrDimensionsField: '":path" n\'est pas une image ou pas aux bonnes dimensions.', requiredProperty: 'Le champ :property est obligatoire et ne peut être vide.', onlyNumbers: 'Le champ :property ne peut contenir que des nombres.', illegalDecimalNumber: ':property ne peut contenir que des nombres avec un maximum de :decimals décimales.', exceedsMax: 'La valeur du champ :property est supérieure au maximum de :max.', listExceedsMax: 'La liste dépasse le maximum de :max éléments.', belowMin: 'La valeur du champ :property est inférieure au minimum de :min.', listBelowMin: "La liste requiert un minimum de :min éléments pour que l'activité fonctionne correctement.", outOfStep: 'La :property ne peut être effectuée que par étape :step.', add: 'Ajouter', addFile: 'Ajouter un fichier', removeFile: 'Supprimer un fichier', confirmRemoval: 'Voulez-vous vraiment supprimer :type ?', removeImage: "Supprimer l'image", confirmImageRemoval: 'Votre image va être supprimée. Êtes-vous sûr de vouloir continuer ?', changeFile: 'Changer le fichier', changeLibrary: 'Changer le type de contenu', semanticsError: 'Erreur de langue: :error', missingProperty: 'Le champ :index ne comporte pas la mention :property.', expandCollapse: 'Dérouler/Enrouler', addEntity: 'Ajouter :entity', tooLong: 'Ce mot est trop long, il ne peut comporter que :max lettres ou moins.', invalidFormat: 'Ce champ contient un format ou un caractère invalide.', confirmChangeLibrary: 'Êtes-vous certain de vouloir passer à une autre activité ?', commonFields: 'Options et textes', commonFieldsDescription: 'Vous pouvez ici éditer les options et les textes.', uploading: 'Chargement en cours...', noFollow: 'Impossible de suivre le champ ":path".', editCopyright: 'Editer le copyright', close: 'Fermer', tutorial: 'Tutoriel', editMode: 'Mode de rédaction', listLabel: 'Liste', uploadError: "Erreur pendant l'envoi du fichier", fileToLarge: 'Le fichier que vous envoyez est trop lourd.', unknownFileUploadError: 'Erreur inconnue lors du téléversement du fichier', noSemantics: 'Erreur, impossible de charger ce type de contenu.', editImage: "Editer l'image", saveLabel: 'Enregistrer', cancelLabel: 'Annuler', resetToOriginalLabel: 'Réinitialiser', loadingImageEditor: "Editeur d'image en cours de chargement, patientez...", selectFiletoUpload: 'Choisissez le fichier à charger', or: 'ou', enterAudioUrl: "Entrez l'URL de la source audio", enterVideoUrl: 'Enter video URL', enterAudioTitle: "Coller le lien ou l'URL d'une autre source audio", enterVideoTitle: "Coller le lien YouTube link ou l'URL d'une autre source vidéo", uploadAudioTitle: 'Téléverser le fichier audio', uploadVideoTitle: 'Téléverser le fichier vidéo', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Insérer', cancel: 'Annuler', height: 'hauteur', width: 'largeur', textField: 'texte', numberField: 'numérique', orderItemUp: "Monter l'élément", orderItemDown: "Descendre l'élément", expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: "Supprimer l'élément", hubPanelLabel: "Sélectionner le type d'activité", importantInstructions: 'Instructions importantes', showImportantInstructions: 'Afficher les instructions', hideImportantInstructions: 'Masquer les instructions importantes', hide: 'Masquer', example: 'Exemple', createContentTabLabel: 'Créer une activité', uploadTabLabel: 'Téléverser', uploadPlaceholder: 'Aucun fichier sélectionné', uploadInstructionsTitle: 'Téléverser un fichier H5P.', uploadInstructionsContent: 'Inspirez-vous des exemples disponibles sur H5P.org.', uploadFileButtonLabel: 'Téléverser un fichier', uploadFileButtonChangeLabel: 'Modifier le fichier', uploadingThrobber: 'Téléversement en cours...', uploadSuccess: ':title a été téléversé avec succès !', unableToInterpretError: "Impossible d'interpréter la réponse.", unableToInterpretSolution: 'Merci de vérifier le journal des erreurs.', h5pFileWrongExtensionTitle: "Le fichier sélectionné n'a pas pu être téléversé.", h5pFileWrongExtensionContent: "Seuls les fichiers avec l'extentions .h5p sont autorisés.", h5pFileValidationFailedTitle: 'Impossible de valider le fichier H5P.', h5pFileValidationFailedContent: 'Merci de vérifier que le fichier H5P téléversé contient un contenu H5P valide. Les fichiers contenant uniquement des bibliothèques doivent être téléversés en utilisant la page des Librairies H5P.', h5pFileUploadServerErrorTitle: "Le fichier H5P n'a pas pu être téléversé.", h5pFileUploadServerErrorContent: "Une erreur inattendue s'est produite. Vérifier le journal des erreurs de votre serveur pour plus d'informations.", contentTypeSectionAll: "Tous les types d'activités", searchResults: 'Résultats de la recherche', contentTypeSearchFieldPlaceholder: "Rechercher des types d'activités", contentTypeInstallButtonLabel: 'Installer', contentTypeInstallingButtonLabel: 'Installation en cours', contentTypeUseButtonLabel: 'Utiliser', contentTypeDetailButtonLabel: 'Détails', contentTypeUpdateButtonLabel: 'Mettre à jour', contentTypeUpdatingButtonLabel: 'Mise à jour en cours', contentTypeGetButtonLabel: 'Obtenir', contentTypeBackButtonLabel: 'Retour', contentTypeIconAltText: 'Icône', contentTypeInstallSuccess: ':contentType installé avec succès !', contentTypeUpdateSuccess: ':contentType mis à jour avec succès !', contentTypeInstallError: ":contentType n'a pas pu être installé. Contactez votre administrateur.", contentTypeLicensePanelTitle: 'Licence', contentTypeDemoButtonLabel: "Démonstration de l'activité", numResults: ':num résultats', show: 'Afficher', recentlyUsedFirst: 'Utilisés récemment en premier', popularFirst: 'Populaires en premier', newestFirst: 'Plus récents en premier', aToZ: 'A à Z', noResultsFound: 'Aucun résultat trouvé', noResultsFoundDesc: "Il n'y a aucune activité qui corresponde à vos critères de recherche.", readMore: 'Lire plus', readLess: 'Lire moins', contentTypeOwner: 'Par :owner', contentTypeUnsupportedApiVersionTitle: "Ce type d'activité requiert une version du noyau H5P plus récente.", contentTypeUnsupportedApiVersionContent: "Contactez votre administrateur système pour qu'il vous fournisse les mises à jour nécessaires.", contentTypeUpdateAvailable: 'Mise à jour disponible', contentTypeRestricted: "Type d'activité à usage restreint", contentTypeRestrictedDesc: "L'utilisation de ce type d'activité a été restreint par un administrateur.", contentTypeNotInstalled: "Type d'activité non installé", contentTypeNotInstalledDesc: "Vous n'avez pas les droits requis pour installer des types d'activités.", theContentType: "Le type d'activité", currentMenuSelected: 'sélection en cours', errorCommunicatingHubTitle: 'Impossible de communiquer avec le hub.', errorCommunicatingHubContent: "Une erreur s'est produite. Merci d'essayer à nouveau.", warningNoContentTypesInstalled: "Vous n'avez aucun type d'activité installé.", warningChangeBrowsingToSeeResults: "Cliquez Tout pour afficher la liste de tous les types d'activités que vous pouvez installer.", warningUpdateAvailableTitle: 'Une nouvelle version de :contentType est disponible.', warningUpdateAvailableBody: "Mettez à jour vers la dernière version pour profiter d'une expérience améliorée.", licenseDescription: "Quelques caractéristiques de cette licence sont indiquées ci-dessous. Cliquez l'icône information au dessus pour afficher le texte de la licence originelle.", licenseModalTitle: 'Détails de la licence', licenseModalSubtitle: "Sélectionner une licence pour afficher les informations à propos de ses modalités d'usage.", licenseUnspecified: 'Non spécifié', licenseCanUseCommercially: 'Utilisation commerciale autorisée', licenseCanModify: 'Modification autorisée', licenseCanDistribute: 'Distribution autorisée', licenseCanSublicense: 'Sous-licence autorisée', licenseCanHoldLiable: 'Peut tenir responsable', licenseCannotHoldLiable: 'Ne peut pas tenir responsable', licenseMustIncludeCopyright: 'Doit inclure un copyright', licenseMustIncludeLicense: 'Doit inclure la licence', licenseFetchDetailsFailed: 'Echec de la récupération des détails de la licence', imageLightboxTitle: 'Images', imageLightBoxProgress: ':num sur :total', nextImage: 'Image suivante', previousImage: 'Image précédente', screenshots: "Captures d'écran", reloadButtonLabel: 'Recharger', videoQuality: 'Label pour la qualité vidéo', videoQualityDescription: "Ce label permet à l'utilisateur d'identifier la qualité de la vidéo, par exemple 1080p, 720p, HD ou Mobile", videoQualityDefaultLabel: 'Qualité :index', noContentTypesAvailable: 'Aucun type de contenu disponible', noContentTypesAvailableDesc: "Votre site rencontre des difficultés pour se connecter à H5P.org et afficher la liste des types d'activités disponibles.", contentTypeCacheOutdated: "Liste des types d'activités obsolète", contentTypeCacheOutdatedDesc: "Votre site rencontre des difficultés pour se connecter à H5P.org pour vérifier les mises à jour des types d'activités. Vous pourriez être incapable de mettre à jour ou d'installer de nouveaux types d'activités.", tryAgain: 'Recommencer', getHelp: "Obtenir de l'aide", untitled: 'Sans titre :libraryTitle', title: 'Title', metadata: 'Métadonnées', addTitle: 'Ajouter un titre', usedForSearchingReportsAndCopyrightInformation: 'Utilisé pour la recherche, les rapports et les informations de copyright', metadataSharingAndLicensingInfo: 'Métadonnées (informations de partage et de licence)', fillInTheFieldsBelow: 'Remplissez les champs ci-dessous', saveMetadata: 'Enregistrer les métadonnées', addAuthor: "Enregistrer l'auteur", confirmRemoveAuthor: 'Êtes-vous sûr de vouloir supprimer cet auteur?', addNewChange: 'Ajouter une nouvelle modification', confirmDeleteChangeLog: 'Êtes-vous sûr de vouloir supprimer cette entrée du journal des modifications ?', changelogDescription: "Certaines licences nécessitent que les modifications apportées au travail original ou aux dérivés soient consignées et affichées. Vous pouvez enregistrer vos modifications ici pour des raisons de licence ou simplement pour vous permettre, à vous-même et à d'autres, de suivre les modifications apportées à ce contenu.", logThisChange: 'Enregistrer cette modification', newChangeHasBeenLogged: 'La nouvelle modification a été enregistrée', loggedChanges: 'Modifications enregistrées', noChangesHaveBeenLogged: 'Aucune modification enregistrée', errorHeader: "Une erreur s'est produite", errorCalculatingMaxScore: 'Impossible de calculer le score maximal pour ce contenu. La note maximale est supposée être 0. Contactez votre administrateur si cela n’est pas correct.', maxScoreSemanticsMissing: 'Impossible de trouver la sémantique attendue dans le contenu.', copyButton: 'Copier', copiedButton: 'Copié', pasteButton: 'Coller', pasteAndReplaceButton: 'Coller et Remplacer', pasteContent: 'Remplacer le contenu', confirmPasteContent: 'En faisant cela, vous remplacerez le contenu actuel par le contenu de votre presse-papiers. Le contenu actuel sera perdu. Êtes-vous sûr de vouloir continuer?', confirmPasteButtonText: 'Remplacer le contenu', copyToClipboard: 'Copier le contenu H5P dans le Presse-papiers', copiedToClipboard: 'Le contenu est copié dans le presse-papier', pasteFromClipboard: 'Coller le contenu H5P depuis le presse-papiers', pasteAndReplaceFromClipboard: 'Remplacer le contenu existant par le contenu H5P du presse-papiers', pasteNoContent: 'Pas de contenu H5P dans le presse-papiers', pasteError: 'Impossible de coller le contenu du presse-papiers', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insérer via', tabTitleBasicFileUpload: 'Téléverser fichier', tabTitleInputLinkURL: 'Lien/URL', errorTooHighVersion: 'Les paramètres contiennent le paramètre %used alors que seulement le paramètre %supported ou antérieur est pris en charge.', errorNotSupported: 'Les paramètres contiennent le paramètre %used qui n’est pas pris en charge.', errorParamsBroken: 'Paramètres invalides.', libraryMissing: 'Bibliothèque requise manquante %lib.', scriptMissing: 'Impossible de charger le script des mises à jour de %lib.', language: 'Langue', noLanguagesSupported: 'Aucune langue supportée', changeLanguage: 'Changer la langue pour :language ?', thisWillPotentially: 'Cela réinitialisera potentiellement tout le texte et les traductions. Vous ne pouvez pas annuler cela. Le contenu lui-même ne sera pas changé. Voulez-vous poursuivre ?', notAllTextsChanged: "Les textes n'ont pas tous été traduits, la traduction pour la langue :language est incomplète.", contributeTranslations: 'Si vous souhaitez compléter la traduction de : language, cliquez pour en savoir plus sur la façon de contribuer aux traductions de H5P .', unknownLibrary: "Malheureusement, la bibliothèque pour le type de contenu sélectionné '%lib' n'est pas installée sur votre système.", proceedButtonLabel: 'Enregistrer', enterFullscreenButtonLabel: 'Afficher en plein écran', exitFullscreenButtonLabel: 'Quitter le mode plein écran', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\uAA+h5plib/v127/joubel/editor/language/es-cr.jsnu[H5PEditor.language.core = { missingTranslation: '[Falta la traducción :key]', loading: 'Cargando, por favor espera...', selectLibrary: 'Selecciona la librería que quiere usar con su contenido.', unknownFieldPath: 'No se puede encontrar ":path".', notImageField: '":path" no es una imagen.', notImageOrDimensionsField: '":path" no es una imagen o un campo de dimensiones.', requiredProperty: 'La :property es requerida y debe tener un valor.', onlyNumbers: 'El valor de :property solo puede contener números.', illegalDecimalNumber: ':property solamente puede contener númeroscon un máximo de :decimals decimales.', exceedsMax: 'El valor de :property excede el máximo de :max.', listExceedsMax: 'La lista excede el máximo de :max elementos.', belowMin: 'El valor de :property excede el mínimo de :min.', listBelowMin: 'La lista necesita al menos :min elementos para que el contenido funcione adecuadamente.', outOfStep: 'El valor de :property solo puede ser cambiado en pasos de :step.', add: 'Añadir', addFile: 'Añadir archivo', removeFile: 'Eliminar archivo', confirmRemoval: '¿Está seguro de que quiere eliminar este :type?', removeImage: 'Eliminar imagen', confirmImageRemoval: 'Esto eliminará la imagen. ¿Seguro que desea continuar?', changeFile: 'Cambiar archivo', changeLibrary: 'Cambiar el tipo de contenido', semanticsError: 'Error en semantics: :error', missingProperty: 'El campo :index no contiene la propiedad :property.', expandCollapse: 'Expandir/Colapsar', addEntity: 'Añadir :entity', tooLong: 'El valor del campo es demasiado largo, debería contener un máximo de :max lettras.', invalidFormat: 'El valor del campo contiene un formato no válido o caracteres prohibidos.', confirmChangeLibrary: 'Al hacer esto perderá todo el trabajo realizado con el tipo de contenido actual. ¿Está seguro de que quiere cambiar el tipo de contenido?', commonFields: 'Parámetros y textos', commonFieldsDescription: 'Aquí puede editar parámetros o traducir textos utilizados en este contenido.', uploading: 'Subiendo, por favor espera...', noFollow: 'No se puede seguir el campo ":path".', editCopyright: 'Editar copyright', close: 'Cerrar', tutorial: 'Tutorial', editMode: 'Modo de edición', listLabel: 'Lista', uploadError: 'Error en la subida del archivo', fileToLarge: 'El archivo que intenta subir es demasiado grande.', unknownFileUploadError: 'Error de carga de archivo desconocido', noSemantics: 'Error, no se ha podido cargar el formulario del tipo de contenido.', editImage: 'Editar imagen', saveLabel: 'Guardar', cancelLabel: 'Cancelar', resetToOriginalLabel: 'Restablecer el original', loadingImageEditor: 'Cargando editor de imagen, por favor espere...', selectFiletoUpload: 'Seleccione el fichero a subir', or: 'o', enterAudioUrl: 'Introduzca la URL del origen del audio', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Pegue el link u otra fuente de audio', enterVideoTitle: 'Peque el link de Youtube o la URL de la fuente del video', uploadAudioTitle: 'Subir fichero de audio', uploadVideoTitle: 'Subir fichero de video', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Insertar', cancel: 'Cancelar', height: 'altura', width: 'ancho', textField: 'campo de texto', numberField: 'campo numérico', orderItemUp: 'Ordenar elemento arriba', orderItemDown: 'Ordenar elemento abajo', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Eliminar elemento', hubPanelLabel: 'Seleccionar tipo de contenido', importantInstructions: 'Instrucciones importantes', showImportantInstructions: 'Mostrar instrucciones', hideImportantInstructions: 'Ocultar instrucciones importantes', hide: 'Ocultar', example: 'Ejemplo', createContentTabLabel: 'Crear Contenido', uploadTabLabel: 'Subir', uploadPlaceholder: 'Ningún fichero seleccionado', uploadInstructionsTitle: 'Subir un fichero H5P.', uploadInstructionsContent: 'Usted puede comenzar con ejemplos de H5P.org.', uploadFileButtonLabel: 'Subir un fichero', uploadFileButtonChangeLabel: 'Cambiar fichero', uploadingThrobber: 'Subiendo ahora...', uploadSuccess: ':title se subió correctamente!', unableToInterpretError: 'Incapaz de interpretar la respuesta.', unableToInterpretSolution: 'Por favor compruebe su log de errores.', h5pFileWrongExtensionTitle: 'El fichero elegido no se puede subir', h5pFileWrongExtensionContent: 'Solo se permiten ficheros con la extensión .h5p.', h5pFileValidationFailedTitle: 'No se puede validar el fichero H5P.', h5pFileValidationFailedContent: 'Asegúrese de que el H5P cargado contiene contenido H5P válido. H5P Los archivos que contienen sólo bibliotecas deben cargarse a través de la página Bibliotecas H5P.', h5pFileUploadServerErrorTitle: 'El fichero H5P no se ha podido cargar', h5pFileUploadServerErrorContent: 'Ocurrió un error inesperado. Compruebe el registro de errores del servidor para obtener más detalles.', contentTypeSectionAll: 'Todos los tipos de contenidos', searchResults: 'Resultados de búsqueda', contentTypeSearchFieldPlaceholder: 'Buscar tipos de contenido', contentTypeInstallButtonLabel: 'Instalar', contentTypeInstallingButtonLabel: 'Instalando', contentTypeUseButtonLabel: 'Usar', contentTypeDetailButtonLabel: 'Detalles', contentTypeUpdateButtonLabel: 'Actualizar', contentTypeUpdatingButtonLabel: 'Actualizando', contentTypeGetButtonLabel: 'Obtener', contentTypeBackButtonLabel: 'Atrás', contentTypeIconAltText: 'Icono', contentTypeInstallSuccess: ':contentType instalado con éxito!', contentTypeUpdateSuccess: ':contentType actualizado con éxito!', contentTypeInstallError: ':contentType no puede ser instalado. Contacte con su administrador.', contentTypeLicensePanelTitle: 'Licencia', contentTypeDemoButtonLabel: 'Demo de Contentenido', numResults: ':num resultados', show: 'Mostrar', recentlyUsedFirst: 'Usado recientemente Primero', popularFirst: 'Popular primero', newestFirst: 'Lo mas nuevo primero', aToZ: 'A a la Z', noResultsFound: 'No se han encontrado resultados', noResultsFoundDesc: 'No hay ningún tipo de contenido que coincida con sus criterios de búsqueda.', readMore: 'Leer más', readLess: 'Leer menos', contentTypeOwner: 'Por :owner', contentTypeUnsupportedApiVersionTitle: 'Este tipo de contenido requiere una nueva versión del core', contentTypeUnsupportedApiVersionContent: 'Póngase en contacto con el responsable del sistema para obtener las actualizaciones necesarias.', contentTypeUpdateAvailable: 'Actualización disponible', contentTypeRestricted: 'Tipo de contenido restringido', contentTypeRestrictedDesc: 'El uso de este tipo de contenido ha sido restringido por un administrador.', contentTypeNotInstalled: 'Tipo de contenido no instalado', contentTypeNotInstalledDesc: 'No tiene permiso para instalar tipos de contenido.', theContentType: 'el tipo de contenido', currentMenuSelected: 'selección actual', errorCommunicatingHubTitle: 'No se puede comunicar con el hub.', errorCommunicatingHubContent: 'Ha ocurrido un error. Por favor, inténtelo de nuevo.', warningNoContentTypesInstalled: 'No tiene ningún tipo de contenido instalado.', warningChangeBrowsingToSeeResults: 'Click Todos para obtener la lista de todos los tipos de contenido que puede instalar .', warningUpdateAvailableTitle: 'Una nueva versión de :contentType está disponible.', warningUpdateAvailableBody: 'Actualización a la última versión para una experiencia mejorada.', licenseDescription: 'Algunas de las características de esta licencia se indican a continuación. Haga clic en el icono de información de arriba para leer el texto original de la licencia.', licenseModalTitle: 'Detalles de la Licencia', licenseModalSubtitle: 'Seleccione una licencia para ver información sobre el uso adecuado', licenseUnspecified: 'Sin especificar', licenseCanUseCommercially: 'Uso comercial', licenseCanModify: 'Se puede modificar', licenseCanDistribute: 'Se puede distribuir', licenseCanSublicense: 'Se puede sublicenciar', licenseCanHoldLiable: 'Se puede declarar responsable', licenseCannotHoldLiable: 'No puede declararse responsable', licenseMustIncludeCopyright: 'Debe incluir copyright', licenseMustIncludeLicense: 'Debe incluir licencia', licenseFetchDetailsFailed: 'Fallo en la obtención de los detalles de la licencia', imageLightboxTitle: 'Imágenes', imageLightBoxProgress: ':num de :total', nextImage: 'Siguiente imagen', previousImage: 'Imagen anterior ', screenshots: 'Capturas de pantalla', reloadButtonLabel: 'Recargar', videoQuality: 'Etiqueta de calidad de vídeo', videoQualityDescription: 'Esta etiqueta ayuda al usuario a identificar la calidad actual del vídeo. Por ejemplo, 1080p, 720p, HD o móvil', videoQualityDefaultLabel: 'Calidad :index', noContentTypesAvailable: 'No hay tipos de contenido disponibles', noContentTypesAvailableDesc: 'Su sitio tiene dificultades para conectarse a H5P.org y para listar los tipos de contenido disponibles.', contentTypeCacheOutdated: 'Lista de tipos de contenido obsoleta', contentTypeCacheOutdatedDesc: 'Su sitio tiene dificultades para conectarse a H5P.org para comprobar si hay actualizaciones del tipo de contenido. Es posible que no pueda actualizar o instalar nuevos tipos de contenido.', tryAgain: 'Inténtelo de nuevo', getHelp: 'Obtener ayuda', untitled: 'Sin título :libraryTitle', title: 'Título', metadata: 'Metadata', addTitle: 'Añadir título', usedForSearchingReportsAndCopyrightInformation: 'Utilizado para búsquedas, informes e información de derechos de autor', metadataSharingAndLicensingInfo: 'Metadata (información sobre uso compartido y licencias)', fillInTheFieldsBelow: 'Rellene los siguientes campos', saveMetadata: 'Guardar metadata', addAuthor: 'Guardar autor', confirmRemoveAuthor: '¿Está seguro de que desea eliminar a este autor?', addNewChange: 'Añadir nuevo cambio', confirmDeleteChangeLog: '¿Está seguro de que desea borrar esta entrada del registro de cambios?', changelogDescription: 'Algunas licencias requieren que los cambios realizados en la obra original o los derivados se registren y visualicen. Usted puede registrar sus cambios aquí por razones de licencia o simplemente para permitirse a usted y a otros mantener un registro de los cambios realizados en este contenido.', logThisChange: 'Registrar este cambio', newChangeHasBeenLogged: 'Se ha registrado un nuevo cambio', loggedChanges: 'Cambios registrados', noChangesHaveBeenLogged: 'No se ha registrado ningún cambio', errorHeader: 'Se ha producido un error', errorCalculatingMaxScore: 'No se pudo calcular la puntuación máxima para este contenido. La puntuación máxima se supone que es 0. Contacte con su administrador si esto no es correcto.', maxScoreSemanticsMissing: 'No se pudo encontrar la semántica esperada en el contenido.', copyButton: 'Copiar', copiedButton: 'Copiado', pasteButton: 'Pegar', pasteAndReplaceButton: 'Pegar y Reemplazar', pasteContent: 'Reemplazar contenido', confirmPasteContent: 'Al hacer esto usted reemplazará el contenido actual con el contenido de su portapapeles. El contenido actual se perderá. ¿Está seguro de que quiere continuar?', confirmPasteButtonText: 'Reemplazar contenido', copyToClipboard: 'Copiar el contenido H5P al portapapeles', copiedToClipboard: 'El contenido se ha copiado al portapapeles', pasteFromClipboard: 'Pegar el contenido H5P del portapapeles', pasteAndReplaceFromClipboard: 'Reemplazar el contenido existente con contenido H5P del portapapeles', pasteNoContent: 'Ningún contenido H5P content en el portapapeles', pasteError: 'No se puede pegar desde el portapapeles', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insertar usando', tabTitleBasicFileUpload: 'Subir fichero', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Los parámetros contienen %used mientras que solamente %supported o anteriores están soportados.', errorNotSupported: 'Los parámetros contienen %used que no está soportado.', errorParamsBroken: 'Los parámetros están rotos.', libraryMissing: 'Falta la biblioteca requerida %lib.', scriptMissing: 'No se pudo cargar el script de actualizaciones para %lib.', language: 'Idioma', noLanguagesSupported: 'No hay idiomas soportados', changeLanguage: '¿Cambiar el idioma a :language?', thisWillPotentially: 'Esto potencialmente restablecerá todo el texto y las traducciones. No puedes deshacer esto. El contenido en sí no será cambiado. ¿Desea proceder?', notAllTextsChanged: 'No todos los textos fueron cambiados, solo hay una cobertura parcial para :language.', contributeTranslations: 'Si desea completar la traducción para :language, puede obtener información sobre contribuir con traducciones al H5P ', unknownLibrary: "Desafortunadamente, el tipo de contenido seleccionado '%lib' no está instalado en este sistema.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\wo7o7(h5plib/v127/joubel/editor/language/en.jsnu[H5PEditor.language.core = { missingTranslation: '[Missing translation :key]', loading: 'Loading, please wait...', selectLibrary: 'Select the library you wish to use for your content.', unknownFieldPath: 'Unable to find ":path".', notImageField: '":path" is not an image.', notImageOrDimensionsField: '":path" is not an image or dimensions field.', requiredProperty: 'The :property is required and must have a value.', onlyNumbers: 'The :property value can only contain numbers.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: 'The :property value exceeds the maximum of :max.', listExceedsMax: 'The list exceeds the maximum of :max items.', belowMin: 'The :property value is below the minimum of :min.', listBelowMin: 'The list needs at least :min items for the content to function properly.', outOfStep: 'The :property value can only be changed in steps of :step.', add: 'Add', addFile: 'Add file', removeFile: 'Remove file', confirmRemoval: 'Are you sure you wish to remove this :type?', removeImage: 'Remove image', confirmImageRemoval: 'This will remove your image. Are you sure you wish to proceed?', changeFile: 'Change file', changeLibrary: 'Change content type?', semanticsError: 'Semantics error: :error', missingProperty: 'Field :index is missing its :property property.', expandCollapse: 'Expand/Collapse', addEntity: 'Add :entity', tooLong: 'Field value is too long, should contain :max letters or less.', invalidFormat: 'Field value contains an invalid format or characters that are forbidden.', confirmChangeLibrary: 'By doing this you will lose all work done with the current content type. Are you sure you wish to change content type?', commonFields: 'Text overrides and translations', commonFieldsDescription: 'Here you can edit settings or translate texts used in this content.', uploading: 'Uploading, please wait...', noFollow: 'Cannot follow field ":path".', editCopyright: 'Edit copyright', close: 'Close', tutorial: 'Tutorial', editMode: 'Editing mode', listLabel: 'List', uploadError: 'File Upload Error', fileToLarge: 'The file you are trying to upload might be too large.', unknownFileUploadError: 'Unknown file upload error', noSemantics: 'Error, could not load the content type form.', editImage: 'Edit image', saveLabel: 'Save', cancelLabel: 'Cancel', resetToOriginalLabel: 'Reset to original', loadingImageEditor: 'Loading image editor, please wait...', selectFiletoUpload: 'Select file to upload', or: 'or', enterAudioUrl: 'Enter audio source URL', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Paste link or other audio source URL', enterVideoTitle: 'Paste YouTube link or other video source URL', uploadAudioTitle: 'Upload audio file', uploadVideoTitle: 'Upload video file', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Insert', cancel: 'Cancel', height: 'height', width: 'width', textField: 'text field', numberField: 'number field', orderItemUp: 'Order item up', orderItemDown: 'Order item down', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Remove item', hubPanelLabel: 'Select content type', importantInstructions: 'Important instructions', showImportantInstructions: 'Show instructions', hideImportantInstructions: 'Hide important instructions', hide: 'Hide', example: 'Example', createContentTabLabel: 'Create Content', uploadTabLabel: 'Upload', uploadPlaceholder: 'No file chosen', uploadInstructionsTitle: 'Upload an H5P file.', uploadInstructionsContent: 'You may start with examples from H5P.org.', uploadFileButtonLabel: 'Upload a file', uploadFileButtonChangeLabel: 'Change file', uploadingThrobber: 'Now uploading...', uploadSuccess: ':title was successfully uploaded!', unableToInterpretError: 'Unable to interpret response.', unableToInterpretSolution: 'Please check your error log.', h5pFileWrongExtensionTitle: 'The selected file could not be uploaded', h5pFileWrongExtensionContent: 'Only files with the .h5p extension are allowed.', h5pFileValidationFailedTitle: 'Could not validate H5P file.', h5pFileValidationFailedContent: 'Make sure the uploaded H5P contains valid H5P content. H5P' + ' files containing only libraries should be uploaded through the H5P Libraries page.', h5pFileUploadServerErrorTitle: 'The H5P file could not be uploaded', h5pFileUploadServerErrorContent: 'An unexpected error occured. Check your server error log for' + ' more details.', contentTypeSectionAll: 'All Content Types', searchResults: 'Search Results', contentTypeSearchFieldPlaceholder: 'Search for Content Types', contentTypeInstallButtonLabel: 'Install', contentTypeInstallingButtonLabel: 'Installing', contentTypeUseButtonLabel: 'Use', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'Update', contentTypeUpdatingButtonLabel: 'Updating', contentTypeGetButtonLabel: 'Get', contentTypeBackButtonLabel: 'Back', contentTypeIconAltText: 'Icon', contentTypeInstallSuccess: ':contentType successfully installed!', contentTypeUpdateSuccess: ':contentType successfully updated!', contentTypeInstallError: ':contentType could not be installed. Contact your administrator.', contentTypeLicensePanelTitle: 'License', contentTypeDemoButtonLabel: 'Content Demo', numResults: ':num results', show: 'Show', recentlyUsedFirst: 'Recently Used First', popularFirst: 'Popular First', newestFirst: 'Newest First', aToZ: 'A to Z', noResultsFound: 'No results found', noResultsFoundDesc: 'There is no content type that matches your search criteria.', readMore: 'Read more', readLess: 'Read less', contentTypeOwner: 'By :owner', contentTypeUnsupportedApiVersionTitle: 'This content type requires a newer core version', contentTypeUnsupportedApiVersionContent: 'Contact your system administrator to provide you with the necessary updates', contentTypeUpdateAvailable: 'Update available', contentTypeRestricted: 'Restricted content type', contentTypeRestrictedDesc: 'The use of this content type has been restricted by an administrator.', contentTypeNotInstalled: 'Content type not installed', contentTypeNotInstalledDesc: 'You do not have permission to install content types.', theContentType: 'the content type', currentMenuSelected: 'current selection', errorCommunicatingHubTitle: 'Not able to communicate with hub.', errorCommunicatingHubContent: 'An error occured. Please try again.', warningNoContentTypesInstalled: "You don't have any content types installed.", warningChangeBrowsingToSeeResults: 'Click All to get the list of all the content types you can install.', warningUpdateAvailableTitle: 'A new version of :contentType is available.', warningUpdateAvailableBody: 'Update to the latest version for an improved experience.', licenseDescription: 'Some of the features of this license are indicated below. Click the info icon above to read the original license text.', licenseModalTitle: 'License Details', licenseModalSubtitle: 'Select a license to view information about proper usage', licenseUnspecified: 'Unspecified', licenseCanUseCommercially: 'Can use commercially', licenseCanModify: 'Can modify', licenseCanDistribute: 'Can distribute', licenseCanSublicense: 'Can sublicense', licenseCanHoldLiable: 'Can hold liable', licenseCannotHoldLiable: 'Cannot hold liable', licenseMustIncludeCopyright: 'Must include copyright', licenseMustIncludeLicense: 'Must include license', licenseFetchDetailsFailed: 'Failed fetching license details', imageLightboxTitle: 'Images', imageLightBoxProgress: ':num of :total', nextImage: 'Next image', previousImage: 'Previous image', screenshots: 'Screenshots', reloadButtonLabel: 'Reload', videoQuality: 'Video quality label', videoQualityDescription: 'This label helps the user identify the current quality of the video. E.g. 1080p, 720p, HD or Mobile', videoQualityDefaultLabel: 'Quality :index', noContentTypesAvailable: 'No content types are available', noContentTypesAvailableDesc: 'Your site is having difficulties connecting to H5P.org and listing the available content types.', contentTypeCacheOutdated: 'Content type list outdated', contentTypeCacheOutdatedDesc: 'Your site is having difficulties connecting to H5P.org to check for content type updates. You may not be able to update or install new content types.', tryAgain: 'Try again', getHelp: 'Get help', untitled: 'Untitled :libraryTitle', title: 'Title', metadata: 'Metadata', addTitle: 'Add title', usedForSearchingReportsAndCopyrightInformation: 'Used for searching, reports and copyright information', metadataSharingAndLicensingInfo: 'Metadata (sharing and licensing info)', fillInTheFieldsBelow : 'Fill in the fields below', saveMetadata: 'Save metadata', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Add new change', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Log this change', newChangeHasBeenLogged: 'New change has been logged', loggedChanges: 'Logged changes', noChangesHaveBeenLogged: 'No changes have been logged', errorHeader: 'An error occured', errorCalculatingMaxScore: 'Could not calculate the max score for this content. The max score is assumed to be 0. Contact your administrator if this isn’t correct.', maxScoreSemanticsMissing: 'Could not find the expected semantics in the content.', copyButton: 'Copy', copiedButton: 'Copied', pasteButton: 'Paste', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Copy H5P content to the clipboard', copiedToClipboard: 'Content is copied to the clipboard', pasteFromClipboard: 'Paste H5P content from the clipboard', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'No H5P content on the clipboard', pasteError: 'Cannot paste from clipboard', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: 'Unfortunately, the selected content type \'%lib\' isn\'t installed on this system.', proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', }; PK*\3:D:D(h5plib/v127/joubel/editor/language/de.jsnu[H5PEditor.language.core = { missingTranslation: '[Fehlende Übersetzung :key]', loading: 'Lade, bitte warten...', selectLibrary: 'Wähle die Bibliothek, die für den Inhalt verwendet werden soll.', unknownFieldPath: '":path" kann nicht gefunden werden.', notImageField: '":path" ist kein Bild.', notImageOrDimensionsField: '":path" ist kein Bild oder Dimensionsfeld.', requiredProperty: ':property wird benötigt und muss einen Wert besitzen.', onlyNumbers: 'Der Wert des Feldes ":property" kann nur Nummern beinhalten.', illegalDecimalNumber: ':property kann nur Zahlen mit maximal :decimals Stellen enthalten.', exceedsMax: 'Der Wert des Feldes ":property" übersteigt das Maximum von :max.', listExceedsMax: 'Die Liste ist länger als die Maximallänge von :max Einträgen.', belowMin: 'Der Wert des Feldes ":property" liegt unter dem Minimum von :min.', listBelowMin: 'Die Liste muss mindestens :min Einträge lang sein, damit der Inhalt korrekt funktioniert.', outOfStep: 'Der Wert des Feldes ":property" kann nur in Schritten von :step geändert werden.', add: 'Hinzufügen', addFile: 'Datei hinzufügen', removeFile: 'Datei entfernen', confirmRemoval: 'Ganz sicher entfernen?', removeImage: 'Bild entfernen', confirmImageRemoval: 'Dies wird das Bild entfernen. Ganz sicher fortfahren?', changeFile: 'Datei ändern', changeLibrary: 'Inhaltstyp ändern?', semanticsError: 'Semantischer Fehler: :error', missingProperty: 'Im Feld :index fehlt die Eigenschaft ":property".', expandCollapse: 'Erweitern/Verkleinern', addEntity: ':entity hinzufügen', tooLong: 'Der Text des Feldes ist zu lang. Es sollte :max Buchstaben oder weniger beinhalten.', invalidFormat: 'Das Feld beinhaltet ein ungültiges Format oder verbotene Zeichen.', confirmChangeLibrary: 'Wenn dies ausgeführt wird, dann geht alles verloren, was mit dem aktuellen Inhaltstyp erstellt wurde. Ganz sicher den Inhaltstyp wechseln?', commonFields: 'Bezeichnungen und Beschriftungen', commonFieldsDescription: 'Hier können Bezeichnungen bearbeitet oder Texte übersetzt werden, die in diesem Inhalt verwendet werden.', uploading: 'Lade hoch, bitte warten...', noFollow: 'Dem Feld ":path" kann nicht gefolgt werden.', editCopyright: 'Rechteangaben bearbeiten', close: 'Schließen', tutorial: 'Tutorial', editMode: 'Bearbeitungsmodus', listLabel: 'Liste', uploadError: 'Fehler beim Hochladen der Datei', fileToLarge: 'Die Datei, die hochgeladen werden soll, könnte zu groß sein.', unknownFileUploadError: 'Unbekannter Fehler beim Hochladen der Datei', noSemantics: 'Der Editor zu diesem Inhaltstyp konnte nicht geladen werden.', editImage: 'Bild bearbeiten', saveLabel: 'Speichern', cancelLabel: 'Abbrechen', resetToOriginalLabel: 'Auf Original zurücksetzen', loadingImageEditor: 'Lade Bildeditor, bitte warten...', selectFiletoUpload: 'Datei zum Hochladen auswählen', or: 'oder', enterAudioUrl: 'URL der Audiodatei eingeben', enterVideoUrl: 'Video-URL eingeben', enterAudioTitle: 'Link oder URL zur Audiodatei einfügen', enterVideoTitle: 'YouTube-Link oder andere Video-URL einfügen', uploadAudioTitle: 'Audio-Datei hochladen', uploadVideoTitle: 'Video-Datei hochladen', addVideoDescription: 'H5P unterstützt alle externen Videoquellen, die das mp4-, webm- or ogv-Format haben, wie Vimeo Pro, und unterstützt YouTube- und Panopto-Links.', insert: 'Einfügen', cancel: 'Abbrechen', height: 'Höhe', width: 'Breite', textField: 'Textfeld', numberField: 'Nummernfeld', orderItemUp: 'Element nach oben schieben', orderItemDown: 'Element nach unten schieben', expandAllContent: 'Alle Inhalte ausklappen', collapseAllContent: 'Alle Inhalte einklappen', removeItem: 'Element entfernen', hubPanelLabel: 'Inhaltstyp auswählen', importantInstructions: 'Wichtige Hinweise', showImportantInstructions: 'Anleitung anzeigen', hideImportantInstructions: 'Anleitung ausblenden', hide: 'Ausblenden', example: 'Beispiel', createContentTabLabel: 'Inhalt erstellen', uploadTabLabel: 'Hochladen', uploadPlaceholder: 'Keine Datei ausgewählt', uploadInstructionsTitle: 'Eine H5P-Datei hochladen.', uploadInstructionsContent: 'Du kannst mit Beispielen von H5P.org starten.', uploadFileButtonLabel: 'Datei hochladen', uploadFileButtonChangeLabel: 'Datei ändern', uploadingThrobber: 'Lade hoch ...', uploadSuccess: ':title wurde erfolgreich hochgeladen!', unableToInterpretError: 'Antwort nicht lesbar.', unableToInterpretSolution: 'Bitte überprüfe das Fehlerprotokoll.', h5pFileWrongExtensionTitle: 'Die ausgewählte Datei konnte nicht hochgeladen werden', h5pFileWrongExtensionContent: 'Nur Dateien mit der Endung .h5p sind erlaubt.', h5pFileValidationFailedTitle: 'Die H5P-Datei ist ungültig oder fehlerhaft.', h5pFileValidationFailedContent: 'Stelle sicher, dass die hochgeladene Datei gültigen H5P-Inhalt enthält. H5P-Dateien, die nur Bibliotheken enthalten, sollten über die H5P-Bibliothekenseite hochgeladen werden.', h5pFileUploadServerErrorTitle: 'Die H5P-Datei konnte nicht hochgeladen werden', h5pFileUploadServerErrorContent: 'Ein unerwarteter Fehler ist aufgetreten. Bitte prüfe die Fehlerlogdatei des Servers für mehr Details.', contentTypeSectionAll: 'Alle Inhaltstypen', searchResults: 'Suchergebnisse', contentTypeSearchFieldPlaceholder: 'Nach Inhaltstypen suchen', contentTypeInstallButtonLabel: 'Installieren', contentTypeInstallingButtonLabel: 'Installiere', contentTypeUseButtonLabel: 'Benutzen', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'Aktualisieren', contentTypeUpdatingButtonLabel: 'Aktualisiere', contentTypeGetButtonLabel: 'Installieren', contentTypeBackButtonLabel: 'Zurück', contentTypeIconAltText: 'Icon', contentTypeInstallSuccess: ':contentType erfolgreich installiert!', contentTypeUpdateSuccess: ':contentType erfolgreich aktualisiert!', contentTypeInstallError: ':contentType konnte nicht installiert werden. Kontaktiere bitte deinen Administrator.', contentTypeLicensePanelTitle: 'Lizenz', contentTypeDemoButtonLabel: 'Inhalts-Demo', numResults: ':num Ergebnisse', show: 'Anzeigen', recentlyUsedFirst: 'Zuletzt verwendete zuerst', popularFirst: 'Beliebteste zuerst', newestFirst: 'Neueste zuerst', aToZ: 'A bis Z', noResultsFound: 'Keine Ergebnisse gefunden', noResultsFoundDesc: 'Kein passender Inhaltstyp gefunden.', readMore: 'mehr anzeigen', readLess: 'weniger anzeigen', contentTypeOwner: 'Von :owner', contentTypeUnsupportedApiVersionTitle: 'Dieser Inhaltstyp erfordert eine neuere Version von H5P.', contentTypeUnsupportedApiVersionContent: 'Kontaktiere bitte deinen Systemadministrator, um die notwendigen Aktualisierungen zu erhalten.', contentTypeUpdateAvailable: 'Aktualisierung verfügbar', contentTypeRestricted: 'Beschränkter Inhaltstyp', contentTypeRestrictedDesc: 'Die Verwendung dieses Inhaltstyps wurde durch einen Administrator beschränkt.', contentTypeNotInstalled: 'Inhaltstyp nicht installiert', contentTypeNotInstalledDesc: 'Du hast keine Berechtigung, Inhaltstypen zu installieren.', theContentType: 'dem Inhaltstyp', currentMenuSelected: 'aktuelle Auswahl', errorCommunicatingHubTitle: 'Es ist keine Verbindung zum Hub möglich.', errorCommunicatingHubContent: 'Ein Fehler ist aufgetreten. Bitte versuche es noch einmal.', warningNoContentTypesInstalled: 'Es sind keine Inhaltstypen installiert.', warningChangeBrowsingToSeeResults: 'Klicke Alle Inhaltstypen an, um eine Liste aller installierbaren Inhaltstypen zu erhalten.', warningUpdateAvailableTitle: 'Eine neuere Version von :contentType ist verfügbar.', warningUpdateAvailableBody: 'Aktualisiere auf die neueste Version, um von allen Verbesserungen zu profitieren.', licenseDescription: 'Einige der Eigenschaften der Lizenz sind unten aufgeführt. Klicke auf das Info-Icon, um den Originallizenztext zu lesen.', licenseModalTitle: 'Lizenzdetails', licenseModalSubtitle: 'Wähle eine Lizenz aus, um zu erfahren, welche Auflagen sie umfasst.', licenseUnspecified: 'Nicht näher angegeben', licenseCanUseCommercially: 'Darf kommerziell genutzt werden', licenseCanModify: 'Darf verändert werden', licenseCanDistribute: 'Darf weitergegeben werden', licenseCanSublicense: 'Unterlizenzvertrag ist möglich', licenseCanHoldLiable: 'Haftung wird übernommen', licenseCannotHoldLiable: 'Haftung wird nicht übernommen', licenseMustIncludeCopyright: 'Muss Urheberrechtshinweis enthalten', licenseMustIncludeLicense: 'Muss Lizenztext enthalten', licenseFetchDetailsFailed: 'Lizenzdetails konnten nicht geladen werden', imageLightboxTitle: 'Bilder', imageLightBoxProgress: ':num von :total', nextImage: 'Nächstes Bild', previousImage: 'Vorheriges Bild', screenshots: 'Bildschirmfotos', reloadButtonLabel: 'Neu laden', videoQuality: 'Beschreibung der Videoqualität', videoQualityDescription: 'An dieser Beschreibung kann der Benutzer die Qualität des hochgeladenen Videos erkennen. Beispiele: 1080p, 720p, HD oder mobil', videoQualityDefaultLabel: 'Videoqualität :index', noContentTypesAvailable: 'Keine Inhaltstypen verfügbar', noContentTypesAvailableDesc: 'Es können keine Inhaltstypen aufgelistet werden, da Verbindungsprobleme zu H5P.org bestehen.', contentTypeCacheOutdated: 'Die Liste der Inhaltstypen ist veraltet', contentTypeCacheOutdatedDesc: 'Es kann nicht nach Aktualisierungen für Inhaltstypen gesucht werden, da Verbindungsprobleme zu H5P.org bestehen. Es ist möglich, dass keine neuen Inhaltstypen installiert oder bestehende aktualisiert werden können.', tryAgain: 'Bitte versuche es erneut', getHelp: 'Hilfe', untitled: 'Unbenannt: :libraryTitle', title: 'Titel', metadata: 'Metadaten', addTitle: 'Titel hinzufügen', usedForSearchingReportsAndCopyrightInformation: 'Wird für die Suche, Berichte und Urheberrechtsinformationen benutzt', metadataSharingAndLicensingInfo: 'Metadaten (Lizenzinformationen)', fillInTheFieldsBelow: 'Fülle die folgenden Felder aus', saveMetadata: 'Metadaten speichern', addAuthor: 'Author speichern', confirmRemoveAuthor: 'Bist du sicher, dass du diesen Autor aus der Liste entfernen möchtest?', addNewChange: 'Änderung hinzufügen', confirmDeleteChangeLog: 'Bist du dir sicher, dass du diesen Eintrag des Änderungsprotokolls löschen möchtest?', changelogDescription: 'Einige Lizenzen schreiben vor, dass Änderungen am ursprünglichen Werk oder an Derivaten gekennzeichnet werden. Hier kannst du solche Änderungen protokollieren - aus Lizenzgründen oder um einen Überblick über die vorgenommen Änderungen zu haben.', logThisChange: 'Änderung festhalten', newChangeHasBeenLogged: 'Neue Änderung wurde festgehalten', loggedChanges: 'Änderungen festgehalten', noChangesHaveBeenLogged: 'Keine Änderungen festgehalten', errorHeader: 'Ein Fehler ist aufgetreten', errorCalculatingMaxScore: 'Die maximale Punktzahl für diesen Inhalt konnte nicht berechnet werden. Es wird angenommen, dass die maximale Punktzahl 0 ist. Kontaktiere bitte deinen Administrator, falls das nicht korrekt ist.', maxScoreSemanticsMissing: 'Die Datei, in der die Struktur des Inhalts beschrieben wird, konnte nicht gefunden werden (semantics.json).', copyButton: 'Kopieren', copiedButton: 'Kopiert', pasteButton: 'Einfügen', pasteAndReplaceButton: 'Einfügen & Ersetzen', pasteContent: 'Inhalte ersetzen', confirmPasteContent: 'Diese Aktion ersetzt den derzeitigen Inhalt mit dem aus der Zwischenablage. Der aktuelle Inhalt geht dadurch verloren. Bist du dir sicher, dass du weitermachen willst?', confirmPasteButtonText: 'Inhalt ersetzen', copyToClipboard: 'Kopiere H5P-Inhalt in den Zwischenspeicher', copiedToClipboard: 'Inhalt wurde in die Zwischenablage kopiert', pasteFromClipboard: 'H5P-Inhalt aus der Zwischenablage einfügen', pasteAndReplaceFromClipboard: 'Existierenden Inhalt mit H5P-Inhalt aus der Zwischenablage ersetzen', pasteNoContent: 'Kein H5P-Inhalt in der Zwischenablage', pasteError: 'Kann nicht aus der Zwischenablage einfügen', pasteContentNotSupported: 'Der Inhalt der Zwischenablage kann an dieser Stelle nicht eingefügt werden', pasteContentRestricted: 'Der Inhalt der Zwischenlage kann auf dieser Seite nicht eingefügt werden, da die Nutzung des Inhaltstyps von den Administratoren eingeschränkt wurde', pasteTooOld: 'Der Inhalt in der Zwischenablage liegt in einer zu alten Version vor (:clip), die nicht an dieser Stelle eingefügt werden kann (erfordert :local). Aktualisiere bitte den Inhalt, den du einfügen möchtest, kopiere ihn erneut und füge ihn dann hier wieder ein.', pasteTooNew: 'Der Inhalt in der Zwischenablage liegt in einer zu neuen Version vor (:clip), die nicht an dieser Stelle eingefügt werden kann (erfordert: local). Aktualisiere bitte den Inhalt, in den du hineinkopieren möchtest und versuche es dann erneut. ', ok: 'OK', avTablistLabel: 'Einfügen über', tabTitleBasicFileUpload: 'Datei hochladen', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Inhalt enthält %used, die Seite unterstützt aber nur %supported oder älter.', errorNotSupported: 'Inhalt enthält %used, was von dieser Seite nicht unterstützt wird.', errorParamsBroken: 'Der Inhalt konnte nicht eingelesen werden (Parameter fehlerhaft).', libraryMissing: 'Die Bibliothek %lib, ohne die nicht fortgefahren werden kann, fehlt.', scriptMissing: 'Die Aktualisierungsroutine für %lib konnten nicht geladen werden.', language: 'Sprache', noLanguagesSupported: 'Keine Sprachen unterstützt', changeLanguage: 'Sprache auf :language ändern?', thisWillPotentially: 'Hierdurch werden möglicherweise alle Bezeichnungen und Beschriftungen zurückgesetzt. Dies kann nicht rückgängig gemacht werden. Der Inhalt selbst wird nicht geändert. Möchtest du fortfahren?', notAllTextsChanged: 'Nicht alle Texte wurden geändert, da die Übersetzungen in :language nicht vollständig ist.', contributeTranslations: 'Wenn du die Übersetzung in :language vervollständigen möchtest, kannst du Übersetzungen zu H5P beisteuern', unknownLibrary: "Leider ist der ausgewählte Inhaltstyp '%lib' auf dieser Seite nicht installiert.", proceedButtonLabel: 'Weiter zum Speichern', enterFullscreenButtonLabel: 'Vollbild', exitFullscreenButtonLabel: 'Vollbild beenden', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title wurde Erfolgreich vom H5P Hub importiert.', noContentHeader: 'Kein passender Inhalt?', noContentSuggestion: 'Erstelle ihn selber!', tutorials: 'Tutorials', contentSectionAll: 'Gesamter geteilter Inhalt', popularContent: 'Beliebter Inhalt', allPopular: 'Alles beliebte', newOnTheHub: 'Neu im Hub', allNew: 'Alle neuen Inhalte', filterBy: 'Filtern nach', filter: 'Filter', filters: { level: { dropdownLabel: 'Niveau', dialogHeader: 'Wähle den Schwierigkeitsgrad', dialogButtonLabel: 'Nach Schwierigkeitsgrad filtern', }, language: { dropdownLabel: 'Sprache', dialogHeader: 'Wähle die Sprache(n)', dialogButtonLabel: 'Nach Sprachen filtern', searchPlaceholder: 'Tippe, um nach Sprachen zu suchen', }, reviewed: { dropdownLabel: 'Überprüft', dialogHeader: 'Überprüfter Inhalt', dialogButtonLabel: 'Filtern', optionLabel: 'Nur überprüften Inhalt anzeigen', }, contentTypes: { dropdownLabel: 'Inhaltstypen', dialogHeader: 'Wähle Inhaltstyp(en) aus', dialogButtonLabel: 'Nach Inhaltstypen filtern', searchPlaceholder: 'Tippe, um nach Inhaltstypen zu suchen', }, disciplines: { dropdownLabel: 'Fach', dialogHeader: 'Wähle das Fach / die Fächer aus', dialogButtonLabel: 'Nach Fächern filtern', searchPlaceholder: 'Tippe, um nach Fächern zu suchen', }, licenses: { dropdownLabel: 'Lizenz', dialogHeader: 'Wähle die von dir bevorzugten Nutzungsrechte aus', dialogButtonLabel: 'Nach Lizenzen filtern', options: { modified: 'Darf verändert werden', commercial: 'Erlaubt kommerzielle Nutzung' }, }, }, clearFilters: 'Alle Filter zurücksetzen', contentSearchFieldPlaceholder: 'Nach Inhalt suchen', loadingContentTitle: 'Wir laden den Inhalt für dich...', loadingContentSubtitle: 'Bitte warten', by: 'Von', dropdownButton: 'Dropdown öffnen', paginationNavigation: 'Seitennavigation', page: 'Seite', currentPage: 'Aktuelle Seite', nextPage: 'Zur nächsten Seite gehen', previousPage: 'Zur vorherigen Seite gehen', contentPreviewButtonLabel: 'Vorschau', contentDownloadButtonLabel: 'Inhalt verwenden', reuseContentTabLabel: 'Geteilten Inhalt verwenden', contentPublisherPanelHeader: 'Informationen zum Herausgeber', noContentFoundDesc: 'Kein Inhalt passt zu deinen Suchkriterien.', h5pType: 'Inhaltstyp', level: 'Niveau', size: 'Größe', failedFetchingData: 'Konnte Daten nicht herunterladen', filterErrorMessage: 'Etwas ist schiefgegangen. Biete lade die Seite neu.', in: 'in', navigateToParent: 'Zum übergeordneten Objekt navigieren', }; PK*\ eDD(h5plib/v127/joubel/editor/language/ar.jsnu[H5PEditor.language.core = { missingTranslation: '[Missing translation :key]', loading: 'جاري التحميل الرجاءالانتظار...', selectLibrary: 'حدد المكتبة التي ترغب في استخدامها للمحتوى الخاص بك.', unknownFieldPath: 'تعذر العثور على ":path".', notImageField: '":path" ليست صورة.', notImageOrDimensionsField: '":path" ليست صورة أو أبعاد حقل', requiredProperty: 'ال :property مطلوب ويجب أن يكون له قيمة.', onlyNumbers: ' :property القيمة يمكن أن تحوي على أرقام فقط.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: ' :property القيمة تتجاوز الحد الأعظمي لـ :max.', listExceedsMax: 'تتجاوز القائمة الحد الأقصى لـ :max items.', belowMin: ' :property القيمة تحت الحد الأدنى من :min.', listBelowMin: 'القائمة تحتاج على الأقل :min العناصر للمحتوى لتعمل بشكل صحيح', outOfStep: ' :property يمكن تغيير قيمة فقط في خطوات من :step.', add: 'اضافة', addFile: 'اضافة ملف', removeFile: 'حذف ملف', confirmRemoval: 'هل أنت متأكد أنك تريد حذف :type?', removeImage: 'حذف الصورة', confirmImageRemoval: 'سيؤدي هذا إلى إزالة الصورة. هل أنت متأكد أنك تريد المتابعة?', changeFile: 'تغيير الملف', changeLibrary: 'تغيير نوع المحتوى?', semanticsError: 'خطأ في الدلالات: :error', missingProperty: 'الحقل :index مفقود :property خصائصه.', expandCollapse: 'توسيع/طي', addEntity: 'اذافة :entity', tooLong: 'قيمة الحقل طويلة جداً يجب أن تتضمن :max من الحروف والأرقام', invalidFormat: 'تحتوي قيمة الحقل على تنسيق غير صالح أو أحرف غير مسموح بها.', confirmChangeLibrary: 'من خلال القيام بذلك سوف تفقد كل العمل المنجز مع نوع المحتوى الحالي. هل تريد بالتأكيد تغيير نوع المحتوى؟', commonFields: 'تجاوزات النصوص والترجمة', commonFieldsDescription: 'يمكنك هنا تعديل الإعدادات أو ترجمة النصوص المستخدمة في هذا المحتوى.', uploading: 'جاري التحميل .. الرجاء الانتظار...', noFollow: 'لا يمكن متابعة الحقل ":path".', editCopyright: 'تعديل حقوق الطبع والنشر', close: 'اغلاق', tutorial: 'تعليم', editMode: 'نمط التحرير', listLabel: 'قائمة', uploadError: 'خطأ في تحميل الملف', fileToLarge: 'قد يكون الملف الذي تحاول تحميله كبيرا جدا.', unknownFileUploadError: 'خطأ في تحميل الملف غير معروف', noSemantics: 'حدث خطأ، تعذر تحميل نموذج نوع المحتوى.', editImage: 'تعديل الصورة', saveLabel: 'حفظ', cancelLabel: 'إلغاء', resetToOriginalLabel: 'إعادة التعيين إلى النسخة الأصلية', loadingImageEditor: 'تحميل محرر الصور، يرجى الانتظار...', selectFiletoUpload: 'حدد ملفا لتحميله', or: 'أو', enterAudioUrl: 'أدخل عنوان مصدر الصوت', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'الصق الرابط أو عنوان مصدر الصوت الاخر', enterVideoTitle: 'ألصق رابط اليوتيوب أو عنوان مصدر الفيديو الاخر', uploadAudioTitle: 'رفع ملف الصوت', uploadVideoTitle: 'رفع ملف الفيديو', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'ادراج', cancel: 'الغاء', height: 'ارتفاع', width: 'عرض', textField: 'حقل نصي', numberField: 'حقل رقمي', orderItemUp: 'ترتيب العنصر لأعلى', orderItemDown: 'ترتيب العنصر لأدنى', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'إزالة العنصر', hubPanelLabel: 'اختر نوع المحتوى', importantInstructions: 'تعليمات هامة', showImportantInstructions: 'Show instructions', hideImportantInstructions: 'إخفاء التعليمات الهامة', hide: 'إخفاء', example: 'مثال', createContentTabLabel: 'إنشاء محتوى', uploadTabLabel: 'رفع', uploadPlaceholder: 'لم يتم اختيار ملف', uploadInstructionsTitle: 'رفع ملف', uploadInstructionsContent: 'يمكن أن تجد أمثلة في H5P.org.', uploadFileButtonLabel: 'رفع ملف', uploadFileButtonChangeLabel: 'تغيير الملف', uploadingThrobber: 'يتم الرفع الان...', uploadSuccess: ':title was successfully uploaded!', unableToInterpretError: 'Unable to interpret response.', unableToInterpretSolution: 'Please check your error log.', h5pFileWrongExtensionTitle: 'تعذر تحميل الملف المحدد', h5pFileWrongExtensionContent: 'فقط الملفات بالامتداد .h5p مسموحة.', h5pFileValidationFailedTitle: 'تعذر التحقق من الملف.', h5pFileValidationFailedContent: 'تأكد أن الملف الذي تم رفعه يحوي على محتوى صالح. H5P يجب تحميل الملفات التي تحتوي على مكتبات فقط من خلال صفحة مكتبات H5P.', h5pFileUploadServerErrorTitle: 'الملف لا يمكن تحميله', h5pFileUploadServerErrorContent: 'حدث خطأ غير متوقع. تحقق من سجل أخطاء السيرفر more details.', contentTypeSectionAll: 'الكل', searchResults: 'Search Results', contentTypeSearchFieldPlaceholder: 'البحث عن أنواع المحتوى', contentTypeInstallButtonLabel: 'تحميل', contentTypeInstallingButtonLabel: 'تحميل', contentTypeUseButtonLabel: 'استخدم', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'تحديث', contentTypeUpdatingButtonLabel: 'تحديث', contentTypeGetButtonLabel: 'احصل على', contentTypeBackButtonLabel: 'العودة', contentTypeIconAltText: 'أيقونة', contentTypeInstallSuccess: ':contentType تم تحميلها بنجاح!', contentTypeUpdateSuccess: ':contentType تم التحديث بنجاح!', contentTypeInstallError: ':contentType لا يمكن تحميله. تواصل مع المشرف.', contentTypeLicensePanelTitle: 'رخصة', contentTypeDemoButtonLabel: 'عرض المحتوى', numResults: ':num results', show: 'Show', recentlyUsedFirst: 'Recently Used First', popularFirst: 'Popular First', newestFirst: 'Newest First', aToZ: 'A to Z', noResultsFound: 'No results found', noResultsFoundDesc: 'There is no content type that matches your search criteria.', readMore: 'أقرأ أكثر', readLess: 'أقرأ أقل', contentTypeOwner: 'بواسطة :owner', contentTypeUnsupportedApiVersionTitle: 'يتطلب نوع المحتوى هذا إصدارا أساسيا أحدث', contentTypeUnsupportedApiVersionContent: 'اتصل بمسؤول النظام لتزويدك بالتحديثات الضرورية', contentTypeUpdateAvailable: 'التحديث متاح', contentTypeRestricted: 'نوع المحتوى المقيد', contentTypeRestrictedDesc: 'تم تقييد استخدام هذا النوع من المحتوى بواسطة مسؤول.', contentTypeNotInstalled: 'نوع المحتوى غير مثبت', contentTypeNotInstalledDesc: 'ليس لديك إذن لتثبيت أنواع المحتوى.', theContentType: 'نوع المحتوى', currentMenuSelected: 'الإختيار الحالي', errorCommunicatingHubTitle: 'غير قادر على التواصل مع المحور.', errorCommunicatingHubContent: 'حدث خطأ. حاول مرة اخرى.', warningNoContentTypesInstalled: 'ليس لديك أي أنواع محتوى مثبتة.', warningChangeBrowsingToSeeResults: 'انقر All للحصول على قائمة بجميع أنواع المحتويات التي يمكنك تثبيتها.', warningUpdateAvailableTitle: 'نسخة جديدة من :contentType متوفرة.', warningUpdateAvailableBody: 'تحديث إلى أحدث إصدار لتجربة أكثر جودة', licenseDescription: 'وفيما يلي بعض ميزات هذا الترخيص. انقر على رمز المعلومات أعلاه لقراءة نص الترخيص الأصلي.', licenseModalTitle: 'تفاصيل الترخيص', licenseModalSubtitle: 'حدد ترخيصا لعرض معلومات حول الاستخدام الصحيح', licenseUnspecified: 'غير محدد', licenseCanUseCommercially: 'يمكن استخدامها تجاريا', licenseCanModify: 'يمكن تعديل', licenseCanDistribute: 'يمكن التوزيع', licenseCanSublicense: 'يمكن ترخيص فرعي', licenseCanHoldLiable: 'يمكن أن تحمل المسؤولية', licenseCannotHoldLiable: 'لا يمكن تحمل المسؤولية', licenseMustIncludeCopyright: 'يجب تضمين حقوق الطبع والنشر', licenseMustIncludeLicense: 'يجب أن يتضمن الترخيص', licenseFetchDetailsFailed: 'فشل في تحميل تفاصيل الترخيص', imageLightboxTitle: 'صور', imageLightBoxProgress: ':num من :total', nextImage: 'الصورة التالية', previousImage: 'الصورة السابقة', screenshots: 'لقطات', reloadButtonLabel: 'اعادة تحميل', videoQuality: 'تصنيف جودة الفيديو', videoQualityDescription: 'يساعد هذا التصنيف المستخدم في تحديد الجودة الحالية للفيديو. مثلا 1080p، 720p، HD أو موبايل', videoQualityDefaultLabel: 'الجودة :index', noContentTypesAvailable: 'No content types are available', noContentTypesAvailableDesc: 'Your site is having difficulties connecting to H5P.org and listing the available content types.', contentTypeCacheOutdated: 'Content type list outdated', contentTypeCacheOutdatedDesc: 'Your site is having difficulties connecting to H5P.org to check for content type updates. You may not be able to update or install new content types.', tryAgain: 'Try again', getHelp: 'Get help', untitled: 'Untitled :libraryTitle', title: 'Title', metadata: 'Metadata', addTitle: 'Add title', usedForSearchingReportsAndCopyrightInformation: 'Used for searching, reports and copyright information', metadataSharingAndLicensingInfo: 'Metadata (sharing and licensing info)', fillInTheFieldsBelow: 'Fill in the fields below', saveMetadata: 'Save metadata', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Add new change', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Log this change', newChangeHasBeenLogged: 'New change has been logged', loggedChanges: 'Logged changes', noChangesHaveBeenLogged: 'No changes have been logged', errorHeader: 'An error occured', errorCalculatingMaxScore: 'Could not calculate the max score for this content. The max score is assumed to be 0. Contact your administrator if this isn’t correct.', maxScoreSemanticsMissing: 'Could not find the expected semantics in the content.', copyButton: 'Copy', copiedButton: 'Copied', pasteButton: 'Paste', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Copy H5P content to the clipboard', copiedToClipboard: 'Content is copied to the clipboard', pasteFromClipboard: 'Paste H5P content from the clipboard', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'No H5P content on the clipboard', pasteError: 'Cannot paste from clipboard', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: "Unfortunately, the selected content type '%lib' isn't installed on this system.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\x<<(h5plib/v127/joubel/editor/language/et.jsnu[H5PEditor.language.core = { missingTranslation: '[Puudub tõlge :key]', loading: 'Laadib, palun oota...', selectLibrary: 'Vali teek, mida soovid oma sisu jaoks kasutada.', unknownFieldPath: 'Ei leia ":path".', notImageField: '":path" ei ole pilt.', notImageOrDimensionsField: '":path" ei ole pilt ega mõõtudega väli.', requiredProperty: 'Atribuut :property on vajalik ja peab omama väärtust.', onlyNumbers: 'Atribuudi :property väärtus võib sisaldada üksnes numbreid.', illegalDecimalNumber: ':property võib sisaldada ainult kuni :decimals komakohta.', exceedsMax: 'Atribuudi :property väärtus on suurem, kui lubatud :max.', listExceedsMax: 'Loetelus on rohkem, kui lubatud :max kannet.', belowMin: 'Atribuudi :property väärtus on väiksem, kui lubatud :min.', listBelowMin: 'Loetelus peab olema vähemalt :min kannet, et sisu toimiks õigesti.', outOfStep: 'Atribuudi :property väärtust saab muuta üksnes sammuga :step.', add: 'Lisa', addFile: 'Lisa fail', removeFile: 'Eemalda fail', confirmRemoval: 'Oled kindel, et soovid eemaldada selle :type?', removeImage: 'Eemalda pilt', confirmImageRemoval: 'Sellega eemaldatakse sinu pilt. Kas oled kindel, et soovid jätkata?', changeFile: 'Muuda faili', changeLibrary: 'Muuda sisu tüüpi?', semanticsError: 'Semantikaviga: :error', missingProperty: 'Väljal :index puudub atribuut :property.', expandCollapse: 'Laota/Sulge', addEntity: 'Lisa :entity', tooLong: 'Välja väärtus on liiga pikk, lubatud on :max tähte või vähem.', invalidFormat: 'Välja väärtus sisaldab sobimatut formaati või keelatud märke.', confirmChangeLibrary: 'Seda tehes kaotad kogu töö, mis on tehtud jooksva sisu-tüübiga. Kas oled kindel, et soovid muuta sisu tüüpi?', commonFields: 'Teksti asendused ja tõlge', commonFieldsDescription: 'Siin saad muuta seadeid või tõlkida selle sisutüübi juures kasutatud tekste.', uploading: 'Laadib üles, palun oota...', noFollow: 'Ei saa järgida välja ":path".', editCopyright: 'Muuda autoriõiguse seadeid', close: 'Sulge', tutorial: 'Tutvustus', editMode: 'Redigeerimismood', listLabel: 'Loetelu', uploadError: 'Faili üleslaadimise viga', fileToLarge: 'Fail, mida püüad üles laadida, võib olla liiga suur.', unknownFileUploadError: 'Tundmatu faili üleslaadimise viga', noSemantics: 'Viga, ei suutnud laadida sisutüübi vormi.', editImage: 'Töötle pilti', saveLabel: 'Salvesta', cancelLabel: 'Tühista', resetToOriginalLabel: 'Lähtesta algsele kujule', loadingImageEditor: 'Pildiredigeerija laadimine, palun oota...', selectFiletoUpload: 'Vali fail, mida üles laadida', or: 'või', enterAudioUrl: 'Sisesta lähteheli link', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Kleebi lähteheli link', enterVideoTitle: 'Kleebi lähtevideo link', uploadAudioTitle: 'Laadi helifail üles', uploadVideoTitle: 'Laadi videofail üles', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Aseta', cancel: 'Tühista', height: 'kõrgus', width: 'laius', textField: 'tekstiväli', numberField: 'numbriväli', orderItemUp: 'Tõsta objekt ülespoole', orderItemDown: 'Liiguta objekt allapoole', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Eemalda objekt', hubPanelLabel: 'Vali sisu tüüp', importantInstructions: 'Olulised juhised', showImportantInstructions: 'Näita juhiseid', hideImportantInstructions: 'Peida olulised juhised', hide: 'Peida', example: 'Näiteks', createContentTabLabel: 'Loo sisu', uploadTabLabel: 'Laadi üles', uploadPlaceholder: 'Faili ei ole valitud', uploadInstructionsTitle: 'Laadi H5P fail üles.', uploadInstructionsContent: 'Võid alustada näidetega lehelt H5P.org.', uploadFileButtonLabel: 'Laadi fail üles', uploadFileButtonChangeLabel: 'Muuda faili', uploadingThrobber: 'Laadib üles...', uploadSuccess: ':title laeti edukalt üles!', unableToInterpretError: 'Arusaamatu tagasiside.', unableToInterpretSolution: 'Palun vaata vea-logist järele.', h5pFileWrongExtensionTitle: 'Valitud faili ei saanud üles laadida', h5pFileWrongExtensionContent: 'Ainult .h5p laiendiga failid on lubatud.', h5pFileValidationFailedTitle: 'Ei saanud H5P faili valideerida.', h5pFileValidationFailedContent: 'Veendu, et üles laetud H5P sisu on valiidne. H5P failid, mis sisaldab vaid teeke, tuleks laadida läbi H5P teekide lehe.', h5pFileUploadServerErrorTitle: 'H5P faili ei saanud üles laadida', h5pFileUploadServerErrorContent: 'Ootamatu viga. Vaata täpsemalt oma vea-logist täiendavaid detaile.', contentTypeSectionAll: 'Kõik sisutüübid', searchResults: 'Otsi tulemusi', contentTypeSearchFieldPlaceholder: 'Otsi sisutüüpe', contentTypeInstallButtonLabel: 'Paigalda', contentTypeInstallingButtonLabel: 'Paigaldab', contentTypeUseButtonLabel: 'Kasuta', contentTypeDetailButtonLabel: 'Detailid', contentTypeUpdateButtonLabel: 'Uuendus', contentTypeUpdatingButtonLabel: 'Uuendab', contentTypeGetButtonLabel: 'Hangi', contentTypeBackButtonLabel: 'Tagasi', contentTypeIconAltText: 'Ikoon', contentTypeInstallSuccess: ':contentType edukalt paigaldatud!', contentTypeUpdateSuccess: ':contentType edukalt uuendatud!', contentTypeInstallError: ':contentType ei saanud paigaldada. Võta administraatoriga ühendust.', contentTypeLicensePanelTitle: 'Litsents', contentTypeDemoButtonLabel: 'Sisu demo', numResults: ':num tulemused', show: 'Näita', recentlyUsedFirst: 'Viimati kasutatutest esimene', popularFirst: 'Populaarseist esimene', newestFirst: 'Uusimaist esimene', aToZ: 'Tähestikulises järjekorras', noResultsFound: 'Ei leidnud tulemusi', noResultsFoundDesc: 'Otsingutingimustele vastavat sisutüüpi ei ole.', readMore: 'Loe rohkem', readLess: 'Loe vähem', contentTypeOwner: ':owner', contentTypeUnsupportedApiVersionTitle: 'See sisutüüp vajab uuemat tuuma versiooni', contentTypeUnsupportedApiVersionContent: 'Võta ühendust oma süsteemiadministraatoriga, et saada vajalikke uuendusi', contentTypeUpdateAvailable: 'Uuendus saadaval', contentTypeRestricted: 'Piiratud sisutüüp', contentTypeRestrictedDesc: 'Selle sisutüübi kasutamise on administraator piiranud.', contentTypeNotInstalled: 'Sisutüüp ei ole paigaldatud', contentTypeNotInstalledDesc: 'Sul ei ole sisutüüpide paigaldamise õigust.', theContentType: 'sisutüüp', currentMenuSelected: 'jooksvalt valitud', errorCommunicatingHubTitle: 'Ei saa keskusega ühendust.', errorCommunicatingHubContent: 'Juhtus viga. Palun proovi uuesti.', warningNoContentTypesInstalled: 'Sul ei ole ühtki sisutüüpi paigaldatud.', warningChangeBrowsingToSeeResults: 'Kliki Kõik et näha loetelu kõikidest sisutüüpidest, mida saad paigaldada.', warningUpdateAvailableTitle: 'Sisutüübist :contentType on uus versioon saadaval.', warningUpdateAvailableBody: 'Parema kasutajakogemuse jaoks uuenda viimasesse versiooni.', licenseDescription: 'Mõned selle litsentsi iseärasustest on näidatud allpool. Kliki ülal olevat info-ikooni, et lugeda litsentsilepingu teksti.', licenseModalTitle: 'Litsentsi detailid', licenseModalSubtitle: 'Vali litsents, et näha teavet sobilikust kasutamisest', licenseUnspecified: 'Määratlemata', licenseCanUseCommercially: 'Võib kasutada ärilistel eesmärkidel', licenseCanModify: 'Võib muuta', licenseCanDistribute: 'Võib jagada', licenseCanSublicense: 'Võib all-litsentseerida', licenseCanHoldLiable: 'Võib olla vastutav', licenseCannotHoldLiable: 'Ei saa olla vastutav', licenseMustIncludeCopyright: 'Peab sisaldama autoriõiguste teavet', licenseMustIncludeLicense: 'Peab sisaldama litsentsi', licenseFetchDetailsFailed: 'Ei õnnestu näidata litsentsi detaile', imageLightboxTitle: 'Pilte', imageLightBoxProgress: ':num, kokku :total', nextImage: 'Järgmine pilt', previousImage: 'Eelmine pilt', screenshots: 'Ekraanipildid', reloadButtonLabel: 'Laadi uuesti', videoQuality: 'Videokvaliteedi silt', videoQualityDescription: 'See silt aitab kasutajal määratleda videomängimise kvaliteeti. Näiteks 1080p, 720p, HD või mobiilne', videoQualityDefaultLabel: 'Kvaliteet :index', noContentTypesAvailable: 'Saadaval ei ole sisutüüpe', noContentTypesAvailableDesc: 'Sinu lehekülg ei saa ühenduda H5P.org serveriga ja näidata võimalikke sisutüüpide loetlemisega.', contentTypeCacheOutdated: 'Sisutüüpide loetelu on aegunud', contentTypeCacheOutdatedDesc: 'Sinu lehekülg ei saa ühenduda H5P.org serveriga, kontrollimaks sisutüüpide uuendusi. Sa ei saa sisutüüpe uuendada ega paigaldada.', tryAgain: 'Proovi uuesti', getHelp: 'Vajan abi', untitled: 'Ilma pealkirjata :libraryTitle', title: 'Pealkiri', metadata: 'Meta-andmed', addTitle: 'Lisa pealkiri', usedForSearchingReportsAndCopyrightInformation: 'Kasutatakse otsimise, raportite ja autoriõiguse teabe jaoks', metadataSharingAndLicensingInfo: 'Metaandmed (jagamine ja litsentsiteave)', fillInTheFieldsBelow: 'Täida allolevad väljad', saveMetadata: 'Salvesta metaandmed', addAuthor: 'Salvesta autor', confirmRemoveAuthor: 'Oled kindel, et tahad eemaldada selle autori?', addNewChange: 'Lisa uus muudatus', confirmDeleteChangeLog: 'Oled kindel, et tahad selle muutus-logi sissekande kustutada?', changelogDescription: 'Mõnede litsentside jaoks on vaja algsesse töösse ja selle tuletistesse tehtud muudatusi logida ja näidata. Tehtud muutused saad logida siia litsenseerimispõhjustel või lihtsalt selleks, et aidata sellesse sisusse tehtud muutuste üle järge pidada.', logThisChange: 'Logi see muudatus', newChangeHasBeenLogged: 'Uus muudatus on logitud', loggedChanges: 'Logitud muudatused', noChangesHaveBeenLogged: 'Ei leidu logitud muudatusi', errorHeader: 'Juhtus viga', errorCalculatingMaxScore: 'Ei saa selle sisu jaoks arvutada maksimaalseid punkte. Eeldatakse, et maksimaalsed punktid on 0. Kui see ei ole nii, siis võta ühendust oma administraatoriga.', maxScoreSemanticsMissing: 'Ei saanud mahutada vajalikku semantikat sisusse mahutada.', copyButton: 'Kopeeri', copiedButton: 'Kopeeritud', pasteButton: 'Kleebi', pasteAndReplaceButton: 'Kleebi ja asenda', pasteContent: 'Asenda sisu', confirmPasteContent: 'Seda tehes asendad olemasoleva sisu kleebitava sisuga. Senine sisu läheb kaotsi. Kas oled kindel, et soovid jätkata?', confirmPasteButtonText: 'Asenda sisu', copyToClipboard: 'Kopeeri H5P sisu mällu', copiedToClipboard: 'Sisu on mällu kopeeritud', pasteFromClipboard: 'Kleebi mälust H5P sisu', pasteAndReplaceFromClipboard: 'Asenda olemasolev sisu mälust võetava H5P sisuga', pasteNoContent: 'Mälus ei ole H5P sisu', pasteError: 'Ei saa mälust kleepida', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'Hästi', avTablistLabel: 'Aseta, kasutades', tabTitleBasicFileUpload: 'Faili üleslaadimine', tabTitleInputLinkURL: 'Link', errorTooHighVersion: 'Parameetrid sisaldavad %used, kuigi vaid %supported või varasem on toetatud.', errorNotSupported: 'Parameetrid sisaldavad %used, mis ei ole toetatud.', errorParamsBroken: 'Parameeetrid on sobimatud.', libraryMissing: 'Vajalik teek %lib on puudu.', scriptMissing: 'Ei saanud laadida üles uuendusi skripti %lib jaoks.', language: 'Keel', noLanguagesSupported: 'Keeli ei toetata', changeLanguage: 'Vali uueks keeleks :language?', thisWillPotentially: 'Tõenäoliselt lähtestad sellega kogu teksti ja tõlked. Neid ei saa seejärel taastada. Sisu ennast ei muudeta. Kas tahad jätkata?', notAllTextsChanged: 'Mitte kõiki tekste ei muudetud. Ainult osaliselt on kaetud - :language.', contributeTranslations: 'Kui tahad lõpetada tõlge keelele :language, siis vaata lähemalt contributing translations to H5P', unknownLibrary: "Kahjuks ei ole valitud sisutüüp '%lib' sellesse süsteemi paigaldatud.", proceedButtonLabel: 'Edasi salvestama', enterFullscreenButtonLabel: 'Ava täisekraanis', exitFullscreenButtonLabel: 'Välju täisekraanist', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\X BB(h5plib/v127/joubel/editor/language/it.jsnu[H5PEditor.language.core = { missingTranslation: '[Traduzione mancante :key]', loading: 'Caricamento, si prega di attendere...', selectLibrary: 'Seleziona la libreria che userai per i tuoi contenuti.', unknownFieldPath: 'Impossibibile trovare :path.', notImageField: ":path non è un'immagine.", notImageOrDimensionsField: ":path non è un'immagine o dimensioni campo.", requiredProperty: ':property è richiesta e deve avere un valore.', onlyNumbers: 'Il valore di :property può contenere solo numeri.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: 'Il valore di :property eccede il massimo di :max.', listExceedsMax: 'The list exceeds the maximum of :max items.', belowMin: 'Il valore di :property eccede il minimo di :min.', listBelowMin: 'The list needs at least :min items for the content to function properly.', outOfStep: 'Il valore di :property può essere modificato solo negli step di :step.', add: 'Aggiungi', addFile: 'Aggiungi file', removeFile: 'Rimuovi file', confirmRemoval: 'Sei sicuro di voler rimuovere questo :type?', removeImage: 'Rimuovi immagine', confirmImageRemoval: "Questo rimuoverà l'immagine . Sei sicuro di voler procedere ?", changeFile: 'Cambia file', changeLibrary: 'Cambiare tipo di contenuto', semanticsError: 'Errore semantico: :error', missingProperty: 'Nel campo :index manca la sua proprietà :property.', expandCollapse: 'Espandi/Collassa', addEntity: 'Aggiungi :entity', tooLong: 'Il valore del campo è troppo lungo, dovrebbe contenere al massimo :max lettere.', invalidFormat: 'Il valore del campo contiene un formato non valido o caratteri non consentiti.', confirmChangeLibrary: 'Sei sicuro di voler cambiare libreria?', commonFields: 'Impostazioni e testi', commonFieldsDescription: 'Da qui puoi modificare le impostazioni o tradurre testi utilizzati in questo contenuto.', uploading: 'Caricamento, si prega di attendere...', noFollow: 'Impossibile seguire il campo :path.', editCopyright: 'Modifica copyright', close: 'Chiudi', tutorial: 'Tutorial', editMode: 'Modalità modifica', listLabel: 'Lista', uploadError: 'Errore nel caricamento del File', fileToLarge: 'Il file che stai cercando di caricare potrebbe essere troppo pesante.', unknownFileUploadError: 'Errore di caricamento di file sconosciuto', noSemantics: 'Errore, impossibile caricare il tipo del contenuto del form.', editImage: 'Modifica immagine', saveLabel: 'Salva', cancelLabel: 'Cancella', resetToOriginalLabel: 'Ripristina all\'originale', loadingImageEditor: 'Caricamento dell\'immagine dell\'editor, attendere per favore...', selectFiletoUpload: 'Selezionare il file da caricare', or: 'oppure', enterAudioUrl: 'Inserire URL della sorgente audio', enterVideoUrl: 'Inserire l\'URL del video', enterAudioTitle: 'Incolla il link o l\'URL di un\'altro sorgente audio', enterVideoTitle: 'Incolla il link YouTube link o un altro URL sorgente video', uploadAudioTitle: 'Carica file audio', uploadVideoTitle: 'Carica file video', addVideoDescription: 'H5P supporta tutte le sorgenti video esterne formattate come mp4, webm o ogv, come Vimeo Pro, e supporta i collegamenti YouTube e Panopto.', insert: 'Inserisci', cancel: 'Cancella', height: 'altezza', width: 'larghezza', textField: 'campo di testo', numberField: 'campo numerico', orderItemUp: 'Ordina l\'elemento in alto', orderItemDown: 'Ordina l\'elemento in basso', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Rimuovi elemento', hubPanelLabel: 'Seleziona tipo di contenuto', importantInstructions: 'Istruzioni importanti', showImportantInstructions: 'Mostra istruzioni', hideImportantInstructions: 'Nascondi importanti istruzioni', hide: 'Nascondi', example: 'Esempio', createContentTabLabel: 'Crea Contenuto', uploadTabLabel: 'Carica', uploadPlaceholder: 'Nessun file scelto', uploadInstructionsTitle: 'Scarica un file H5P.', uploadInstructionsContent: 'Potresti iniziare con un esempio da H5P.org.', uploadFileButtonLabel: 'Scarica un file', uploadFileButtonChangeLabel: 'Cambia file', uploadingThrobber: 'In fase di caricamento...', uploadSuccess: ':title è stato caricato con successo!', unableToInterpretError: 'Impossibile interpretare la risposta.', unableToInterpretSolution: 'Si prega di controllare il log degli errori.', h5pFileWrongExtensionTitle: 'Il file selezionato non può essere caricato', h5pFileWrongExtensionContent: 'Sono permessi solo file con estensione .h5p', h5pFileValidationFailedTitle: 'Non può validare il file .h5p.', h5pFileValidationFailedContent:'Assicurati che l\'H5P caricato contenga contenuti H5P validi. I file H5P contenenti solo librerie devono essere caricati tramite la pagina Librerie H5P.', h5pFileUploadServerErrorTitle: 'Il file H5P non può essere caricato', h5pFileUploadServerErrorContent: 'Si è verificato un errore inatteso. Controllare il log degli errori sul tuo server per ulteriori dettagli.', contentTypeSectionAll: 'Tutti i tipi di contenuto', searchResults: 'Cerca Risultati', contentTypeSearchFieldPlaceholder: 'Cerca Tipi di Contenuto', contentTypeInstallButtonLabel: 'Installa', contentTypeInstallingButtonLabel: 'Installazione in corso', contentTypeUseButtonLabel: 'Usa', contentTypeDetailButtonLabel: 'Dettagli', contentTypeUpdateButtonLabel: 'Carica', contentTypeUpdatingButtonLabel: 'In caricamento', contentTypeGetButtonLabel: 'Ottieni', contentTypeBackButtonLabel: 'Indietro', contentTypeIconAltText: 'Icona', contentTypeInstallSuccess: ':contentType installato con successo!', contentTypeUpdateSuccess: ':contentType caricato con successo!', contentTypeInstallError: ':contentType non può essere installato. Contattare il tuo amministratore.', contentTypeLicensePanelTitle: 'Licenza', contentTypeDemoButtonLabel: 'Contenuto Demo', numResults: ':num risultati', show: 'Mostra', recentlyUsedFirst: 'Prima Utilizzati di recente', popularFirst: 'Prima i più popolari', newestFirst: 'Prima i più recenti', aToZ: 'Dalla A alla Z', noResultsFound: 'Nessun risultato trovato', noResultsFoundDesc: 'Non ci sono tipi di contenuto che soddisfano i criteri di ricerca.', readMore: 'Leggi di più', readLess: 'Leggi di meno', contentTypeOwner: 'Creato da :owner', contentTypeUnsupportedApiVersionTitle: 'Questo contenuto richiede una versione principale più recente', contentTypeUnsupportedApiVersionContent: 'Contattare il tuo amministratore di sistema per fornirti i necessari aggiornamenti', contentTypeUpdateAvailable: 'Aggiornamento disponibile', contentTypeRestricted: 'Tipo di contenuto limitato', contentTypeRestrictedDesc: 'L\'uso di questo contenuto è stato limitato da un amministratore.', contentTypeNotInstalled: 'Tipo di contenuto non installato', contentTypeNotInstalledDesc: 'Non hai i permessi per installare tipi di contenuto.', theContentType: 'il tipo di contenuto', currentMenuSelected: 'selezione attuale', errorCommunicatingHubTitle: 'Impossibile comunicare con l\'hub.', errorCommunicatingHubContent: 'Si è verificato un errore. Per favore riprovare.', warningNoContentTypesInstalled: "Non hai alcun tipo di contenuto installato.", warningChangeBrowsingToSeeResults: 'Clicca Tutto per ottenere una lista di tutti i tipi di contenuto installati.', warningUpdateAvailableTitle: 'Una nuova versione di :contentType è disponibile.', warningUpdateAvailableBody: 'Aggiorna all\'ultima versione per migliorare l\'esperienza.', licenseDescription: 'Alcune delle caratteristiche di questa licenza sono indicate di seguito. Fare clic sull\'icona delle informazioni in alto per leggere il testo della licenza originale.', licenseModalTitle: 'Dettagli sulla Licenza', licenseModalSubtitle: 'Seleziona la licenza per vedere le informazione riguardo l\'uso appropriato', licenseUnspecified: 'Non specificata', licenseCanUseCommercially: 'Utilizzo commerciale concesso', licenseCanModify: 'Può modificare', licenseCanDistribute: 'Può distribuire', licenseCanSublicense: 'Permette sublicenze', licenseCanHoldLiable: 'Può ritenersi responsabile', licenseCannotHoldLiable: 'Non può ritenersi responsabile', licenseMustIncludeCopyright: 'Deve includere copyright', licenseMustIncludeLicense: 'Deve includere la licenza', licenseFetchDetailsFailed: 'Impossibile recuperare i dettagli della licenza', imageLightboxTitle: 'Immagini', imageLightBoxProgress: ':num di :total', nextImage: 'Prossima immagine', previousImage: 'Immagine precedente', screenshots: 'Screenshots', reloadButtonLabel: 'Ricarica', videoQuality: 'Etichetta della qualità video', videoQualityDescription: 'Questa etichetta aiuta l\'utente a identificare la qualità attuale del video. Per esempio 1080p, 720p, HD o Mobile', videoQualityDefaultLabel: 'Qualità :index', noContentTypesAvailable: 'Nessun tipo di contenuto è disponibile', noContentTypesAvailableDesc: 'Il tuo sito ha difficoltà a connettersi a H5P.org e ad elencare i tipi di contenuto disponibili.', contentTypeCacheOutdated: 'Elenco dei tipi di contenuto obsoleto', contentTypeCacheOutdatedDesc: 'Il tuo sito ha difficoltà a connettersi a H5P.org per controllare gli aggiornamenti del tipo di contenuto. Potrebbe non essere possibile aggiornare o installare nuovi tipi di contenuto.', tryAgain: 'Prova di nuovo', getHelp: 'Chiedi aiuto', untitled: 'Senza titolo :libraryTitle', title: 'Titolo', metadata: 'Metadata', addTitle: 'Aggiungi titolo', usedForSearchingReportsAndCopyrightInformation: 'Usato per la ricerca, i report e le informazioni sui copyright', metadataSharingAndLicensingInfo: 'Metadata (informazioni sulla condivisione e sulle licenze)', fillInTheFieldsBelow: 'Completa i campi sottostanti', saveMetadata: 'Salva metadata', addAuthor: 'Salva autore', confirmRemoveAuthor: 'Sei sicuro di voler rimuovere questo autore?', addNewChange: 'Aggiungi nuova modifica', confirmDeleteChangeLog: 'Sei sicuro di voler eliminare questa voce del registro delle modifiche?', changelogDescription: 'Alcune licenze richiedono che le modifiche apportate all\'opera originale o ai derivati ​​vengano registrate e visualizzate. Puoi registrare le tue modifiche qui per motivi di licenza o semplicemente per consentire a te stesso e ad altri di tenere traccia delle modifiche apportate a questo contenuto.', logThisChange: 'Registra questa modifica', newChangeHasBeenLogged: 'La nuova modifica è stata registrata', loggedChanges: 'Modifiche registrate', noChangesHaveBeenLogged: 'Nessun cambiamento è stato registrato', errorHeader: 'Si è verificato un errore', errorCalculatingMaxScore: 'Impossibile calcolare il punteggio massimo per questo contenuto. Si presume che il punteggio massimo sia 0. Contatta l\'amministratore se non è corretto.', maxScoreSemanticsMissing: 'Impossibile trovare la semantica prevista nel contenuto.', copyButton: 'Copia', copiedButton: 'Copiato', pasteButton: 'Incolla', pasteAndReplaceButton: 'Incolla e Sostituisci', pasteContent: 'Sostituisci il contenuto', confirmPasteContent: 'In questo modo sostituirai il contenuto corrente con il contenuto dei tuoi appunti. Il contenuto corrente andrà perso. Sei sicuro di voler continuare?', confirmPasteButtonText: 'Sostituisci contenuto', copyToClipboard: 'Copia contenuto H5P negli appunti', copiedToClipboard: 'Il contenuto è stato copiato negli appunti', pasteFromClipboard: 'Incolla contenuto H5P dagli appunti', pasteAndReplaceFromClipboard: 'Sostituisci contenuto esistente con contenuto H5P dagli appunti', pasteNoContent: 'Nessun contenuto H5P negli appunti', pasteError: 'Impossibile incollare dagli appunti', pasteContentNotSupported: 'Il contenuto negli appunti H5P non è supportato in questo contesto', pasteContentRestricted: 'Il contenuto negli appunti è stato limitato su questo sito', pasteTooOld: 'Il contenuto negli appunti H5P è di una versione inferiore (:clip) rispetto a quella supportata in questo contesto (:local), se possibile provare ad aggiornare il contenuto che si desidera incollare, copiarlo di nuovo e provare a incollarlo qui.', pasteTooNew: 'Il contenuto negli appunti H5P è di una versione superiore (:clip) rispetto a quella supportata in questo contesto (:local), se possibile, prova prima ad aggiornare questo contenuto, quindi prova a incollare nuovamente il contenuto qui.', ok: 'OK', avTablistLabel: 'Inserisci utilizzando', tabTitleBasicFileUpload: 'Caricamento file', tabTitleInputLinkURL: 'Indirizzo/URL', errorTooHighVersion: 'I parametri contengono %used mentre sono supportati solo %supported o versioni precedenti.', errorNotSupported: 'I parametri contengono %used che non è supportato.', errorParamsBroken: 'I parametri sono corrotti.', libraryMissing: 'Libreria richiesta mancante %lib.', scriptMissing: 'Impossibile caricare lo script degli aggiornamenti per %lib.', language: 'Linguaggi', noLanguagesSupported: 'Nessun linguaggio supportato', changeLanguage: 'Cambiare lingua in :language?', thisWillPotentially: "Questo potenzialmente ripristinerà tutto il testo e le traduzioni. Non puoi annullare questa operazione. Il contenuto stesso non verrà modificato. Vuoi procedere?", notAllTextsChanged: 'Non tutti i testi sono stati modificati, c\'è solo una copertura parziale per :language.', contributeTranslations: 'Se desideri completare la traduzione per :language, puoi ottenere informazioni su come contribuire alle traduzioni per H5P', unknownLibrary: "Purtroppo, il tipo di contenuto selezionato '%lib' non è installato nel tuo sistema.", proceedButtonLabel: 'Procedi al salvataggio', enterFullscreenButtonLabel: 'Entra in modalità schermo intero', exitFullscreenButtonLabel: 'Esci dalla modalità schermo intero', a11yTitleShowLabel: 'Mostra l\'etichetta per AT', a11yTitleHideLabel: 'Nascondi l\'etichetta per AT', reuseSuccess: ':title è stato importato con successo dall\'Hub H5P.', noContentHeader: 'nessun contenuto adatto?', noContentSuggestion: 'Creane uno tu stesso!', tutorials: 'I Tutorial', contentSectionAll: 'Tutti i contenuti condivisi', popularContent: 'Contenuti Popolari', allPopular: 'Tutti i popolari', newOnTheHub: 'Nuovi nell\'Hub', allNew: 'Tutti i nuovi', filterBy: 'Filtra per', filter: 'Filtra', filters: { level: { dropdownLabel: 'Livello', dialogHeader: 'Seleziona il livello di istruzione', dialogButtonLabel: 'Filtra il livello di istruzione', }, language: { dropdownLabel: 'Lingua', dialogHeader: 'Seleziona una o più lingue', dialogButtonLabel: 'Filtra lingue', searchPlaceholder: 'Digita per cercare le lingue', }, reviewed: { dropdownLabel: 'Revisionato', dialogHeader: 'Contenuto Revisionato', dialogButtonLabel: 'Filtro', optionLabel: 'Mostra solo contenuti revisionati', }, contentTypes: { dropdownLabel: 'Tipi di contenuto', dialogHeader: 'Seleziona uno o più tipi di Contenuto', dialogButtonLabel: 'Filtra i Tipi di Contenuto', searchPlaceholder: 'Digita per cercare i tipi di contenuto', }, disciplines: { dropdownLabel: 'Disciplina', dialogHeader: 'Seleziona la tua disciplina', dialogButtonLabel: 'Filtra le tue discipline', searchPlaceholder: 'Digita per cercare le discipline', }, licenses: { dropdownLabel: 'Licenza', dialogHeader: 'Seleziona i diritti d\'uso preferiti', dialogButtonLabel: 'Filtra le licenze', options: { modified: 'Può modificare', commercial: 'Permette l\'uso commerciale' }, }, }, clearFilters: 'Cancella tutti i filtri', contentSearchFieldPlaceholder: 'Ricerca per Contenuto', loadingContentTitle: 'Stiamo caricando il contenuto per te...', loadingContentSubtitle: 'Attendere per favore', by: 'Fatto da', dropdownButton: 'Apri menù a discesa', paginationNavigation: 'Navigazione dell\'impaginazione', page: 'Pagina', currentPage: 'Pagina corrente', nextPage: 'Vai alla pagina seguente', previousPage: 'Vai alla pagina precedente', contentPreviewButtonLabel: 'Anteprima', contentDownloadButtonLabel: 'Ottieni Contenuto', reuseContentTabLabel: 'Ottieni contenuto condiviso', contentPublisherPanelHeader: 'Informazioni sull\'autore', noContentFoundDesc: 'Non ci sono contenuti corrispondenti ai criteri di ricerca.', h5pType: 'Tipo di H5P', level: 'Livello', size: 'Dimensione', failedFetchingData: 'Recupero dei dati non riuscito', filterErrorMessage: 'Qualcosa è andato storto. Si prega di ricaricare la pagina.', in: 'in', navigateToParent: 'Vai al parent', }; PK*\(88-h5plib/v127/joubel/editor/language/zh-hans.jsnu[H5PEditor.language.core = { missingTranslation: '[缺少翻译 :key]', loading: '加载中,请稍候...', selectLibrary: '请选择用于创建内容的库。', unknownFieldPath: '找不到":path".', notImageField: '":path" 不是图片。', notImageOrDimensionsField: '":path" 不是图片或尺寸字段。', requiredProperty: ':property 是必需的,并且必须有一个值。', onlyNumbers: ':property 的值只能包含数字。', illegalDecimalNumber: ':property 只能包含最大为:decimals小数的数字。', exceedsMax: ':property 的值超过了:max的最大值。', listExceedsMax: '列表超过了:max个项目的上限。', belowMin: ':property 值低于:min的最小值。', listBelowMin: '该列表至少需要:min个项目,内容才能正常运行。', outOfStep: ':property 的值只能以:step为单位更改。', add: '添加', addFile: '添加文件', removeFile: '移除文件', confirmRemoval: '您确定要删除此:type吗?', removeImage: '移除图片', confirmImageRemoval: '这将删除您的图片。 您确定要继续吗?', changeFile: '更改文件', changeLibrary: '更改内容类型?', semanticsError: '语义错误::error', missingProperty: '字段:index缺少其:property属性。', expandCollapse: '展开/折叠', addEntity: '添加:entity', tooLong: '字段值太长,应包含最多:max个字母。', invalidFormat: '字段值包含无效的格式或被禁止的字符。', confirmChangeLibrary: '继续操作将丢失使用当前内容类型创建的所有工作。 您确定要更改内容类型吗?', commonFields: '文字替代和翻译', commonFieldsDescription: '您可以在此处编辑设置或翻译此内容中使用的文本。', uploading: '正在上传,请稍候...', noFollow: '无法追踪字段":path".', editCopyright: '编辑版权', close: '关闭', tutorial: '使用教程', editMode: '编辑模式', listLabel: '列表', uploadError: '文件上传错误', fileToLarge: '您尝试上传的文件可能太大了。', unknownFileUploadError: '未知文件上传错误', noSemantics: '错误,无法加载内容类型表格。', editImage: '编辑图片', saveLabel: '保存', cancelLabel: '取消', resetToOriginalLabel: '重置为原始状态', loadingImageEditor: '正在加载图片编辑器,请稍候...', selectFiletoUpload: '请选择要上传的文件', or: '或', enterAudioUrl: '请输入音频源URL', enterVideoUrl: '请输入视频源URL', enterAudioTitle: '粘贴链接或其他音频源URL', enterVideoTitle: '粘贴YouTube链接或其他视频源URL', uploadAudioTitle: '上传音频文件', uploadVideoTitle: '上传视频文件', addVideoDescription: 'H5P 支持格式为 mp4、webm 或 ogv 的所有外部视频源,如 Vimeo Pro,并支持 YouTube 和 Panopto 链接。', insert: '插入', cancel: '取消', height: '高度', width: '宽度', textField: '文本字段', numberField: '数字字段', orderItemUp: '向上', orderItemDown: '向下', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: '移除', hubPanelLabel: '选择内容类型', importantInstructions: '重要说明', showImportantInstructions: '显示重要说明', hideImportantInstructions: '隐藏重要说明', hide: '隐藏', example: '示例', createContentTabLabel: '创建内容', uploadTabLabel: '上传', uploadPlaceholder: '没有选择文件', uploadInstructionsTitle: '上传H5P文件。', uploadInstructionsContent: '您可以从H5P.org中的示例开始。', uploadFileButtonLabel: '上传文件', uploadFileButtonChangeLabel: '替换文件', uploadingThrobber: '正在上传...', uploadSuccess: ':title 已成功上传!', unableToInterpretError: '无法解释响应。', unableToInterpretSolution: '请检查您的错误日志。', h5pFileWrongExtensionTitle: '所选文件无法上传', h5pFileWrongExtensionContent: '仅允许使用扩展名为.h5p的文件。', h5pFileValidationFailedTitle: '无法验证H5P文件。', h5pFileValidationFailedContent: '确保上传的H5P包含有效的H5P内容。如果H5P仅包含库文件,则应通过“ H5P库”页面上载。', h5pFileUploadServerErrorTitle: '无法上传H5P文件', h5pFileUploadServerErrorContent: '发生意外错误。 请检查服务器错误日志中是否有更多信息。', contentTypeSectionAll: '所有内容类型', searchResults: '搜索结果', contentTypeSearchFieldPlaceholder: '搜索内容类型', contentTypeInstallButtonLabel: '安装', contentTypeInstallingButtonLabel: '正在安装', contentTypeUseButtonLabel: '应用', contentTypeDetailButtonLabel: '详细信息', contentTypeUpdateButtonLabel: '更新', contentTypeUpdatingButtonLabel: '正在更新', contentTypeGetButtonLabel: '获取', contentTypeBackButtonLabel: '返回', contentTypeIconAltText: '图标', contentTypeInstallSuccess: ':contentType 成功安装!', contentTypeUpdateSuccess: ':contentType 成功更新!', contentTypeInstallError: ':contentType 无法安装。请与您的管理员联系。', contentTypeLicensePanelTitle: '许可证', contentTypeDemoButtonLabel: '演示内容', numResults: ':num 条结果', show: '显示', recentlyUsedFirst: '最近使用', popularFirst: '热门', newestFirst: '最新', aToZ: '按名称', noResultsFound: '未找到结果', noResultsFoundDesc: '没有与您的搜索条件匹配的内容类型。', readMore: '更多', readLess: '更少', contentTypeOwner: '由 :owner', contentTypeUnsupportedApiVersionTitle: '此内容类型需要一个更新的核心版本', contentTypeUnsupportedApiVersionContent: '请与您的系统管理员联系安装必要的更新', contentTypeUpdateAvailable: '有可用更新', contentTypeRestricted: '受限内容类型', contentTypeRestrictedDesc: '管理员已限制使用此内容类型。', contentTypeNotInstalled: '内容类型未安装', contentTypeNotInstalledDesc: '您无权安装内容类型。', theContentType: '内容类型', currentMenuSelected: '当前选择', errorCommunicatingHubTitle: '无法与H5P Hub通信。', errorCommunicatingHubContent: '出错了,请再试一次。', warningNoContentTypesInstalled: '您没有安装任何内容类型。', warningChangeBrowsingToSeeResults: '单击全部以获取可以安装的所有内容类型的列表。', warningUpdateAvailableTitle: '有:contentType的更新可用。', warningUpdateAvailableBody: '更新到最新版本以获得更好的使用体验。', licenseDescription: '该许可证的某些功能如下所示。 单击上方的信息图标以阅读原始许可证文本。', licenseModalTitle: '许可证详细信息', licenseModalSubtitle: '选择一个许可证以查看有关正确使用的信息', licenseUnspecified: '未指定', licenseCanUseCommercially: '可以商业使用', licenseCanModify: '可以修改', licenseCanDistribute: '可以分发', licenseCanSublicense: '可以再许可', licenseCanHoldLiable: '承担责任', licenseCannotHoldLiable: '不承担责任', licenseMustIncludeCopyright: '必须包含版权信息', licenseMustIncludeLicense: '必须包含许可证', licenseFetchDetailsFailed: '获取许可证详细信息失败', imageLightboxTitle: '图片', imageLightBoxProgress: ':num / :total', nextImage: '下一个图片', previousImage: '上一个图片', screenshots: '屏幕截图', reloadButtonLabel: '重新加载', videoQuality: '视频质量标签', videoQualityDescription: '此标签可帮助用户识别视频的当前视频质量。 例如。 1080p,720p,高清或手机端', videoQualityDefaultLabel: '视频质量 :index', noContentTypesAvailable: '没有可用的内容类型', noContentTypesAvailableDesc: '您的网站在连接到H5P.org并列出可用的内容类型时遇到问题。', contentTypeCacheOutdated: '内容类型列表已过时', contentTypeCacheOutdatedDesc: '您的网站无法连接到H5P.org以检查内容类型更新。 您可能无法更新或安装新的内容类型。', tryAgain: '再试一次', getHelp: '获取帮助', untitled: '未命名:libraryTitle', title: '标题', metadata: '元数据', addTitle: '添加标题', usedForSearchingReportsAndCopyrightInformation: '用于搜索,报告和版权信息', metadataSharingAndLicensingInfo: '元数据(共享和许可信息)', fillInTheFieldsBelow: '请填写下面的字段', saveMetadata: '保存元数据', addAuthor: '保存作者', confirmRemoveAuthor: '您确定要删除这个作者吗?', addNewChange: '新增变更', confirmDeleteChangeLog: '您确定要删除这个更新日志条目吗?', changelogDescription: '有些许可证要求记录并显示对原始作品或衍生作品所做的更改。 您可以根据许可证要求的原因在此处记录您的更改,或者只是为了让自己和他人跟踪对此内容所做的更改。', logThisChange: '记录此更改', newChangeHasBeenLogged: '已记录新的更改', loggedChanges: '已记录的更改', noChangesHaveBeenLogged: '尚未记录任何更改', errorHeader: '发生错误', errorCalculatingMaxScore: '无法计算此内容的最高分。 当前最高分数设定为0。如果您觉得设置不正确,请与管理员联系。', maxScoreSemanticsMissing: '在内容中找不到预期的语义。', copyButton: '复制', copiedButton: '已复制', pasteButton: '粘贴', pasteAndReplaceButton: '粘贴并替换', pasteContent: '替换内容', confirmPasteContent: '通过此操作,您将用剪贴板中的内容替换当前内容。 当前内容将丢失。 您确定要继续吗?', confirmPasteButtonText: '替换内容', copyToClipboard: '将H5P内容复制到剪贴板', copiedToClipboard: '内容已复制到剪贴板', pasteFromClipboard: '从剪贴板粘贴H5P内容', pasteAndReplaceFromClipboard: '用剪贴板中的H5P内容替换现有内容', pasteNoContent: '剪贴板中没有H5P内容', pasteError: '无法从剪贴板粘贴', pasteContentNotSupported: '当前环境不支持H5P剪贴板中的内容', pasteContentRestricted: '剪贴板中的内容已在此站点上受到限制', pasteTooOld: 'H5P剪贴板中的内容(:clip)的版本低于当前环境(:local)中支持的版本,如果可能,请尝试升级要粘贴的内容,然后再次复制并尝试将其粘贴到此处。', pasteTooNew: 'H5P剪贴板中的内容(:clip)的版本高于当前环境(:local)中支持的版本,如果可能,请尝试先升级此内容,然后再尝试将其粘贴到此处。', ok: '我知道了', avTablistLabel: '插入使用', tabTitleBasicFileUpload: '上传文件', tabTitleInputLinkURL: '链接/URL', errorTooHighVersion: '参数中包含%used,而仅支持%supported或更早的版本。', errorNotSupported: '参数中包含不支持的%used。', errorParamsBroken: '参数已损坏。', libraryMissing: '缺少必需的库 %lib。', scriptMissing: '无法加载 %lib的升级脚本。', language: '语言', noLanguagesSupported: '没有支持的语言', changeLanguage: '更改语言为 :language?', thisWillPotentially: '这可能会重置所有文本和翻译。 您无法撤消此操作。 内容本身不会被更改。 您要继续吗?', notAllTextsChanged: '并非所有文本都已更改,:language仅部分覆盖。', contributeTranslations: '如果您想完善或帮助 :language的语言翻译,可以了解有关为H5P贡献翻译的信息', unknownLibrary: "很遗憾,此系统上未安装选定的内容类型 '%lib'。", proceedButtonLabel: '继续保存', enterFullscreenButtonLabel: '进入全屏', exitFullscreenButtonLabel: '退出全屏', noContentHeader: '没有合适的内容?', noContentSuggestion: '自己创建一个吧!', tutorials: '使用教程', contentSectionAll: '所有共享内容', popularContent: '热门内容', allPopular: '所有热门', newOnTheHub: '最新添加', allNew: '所有最新内容', filterBy: '筛选条件', filter: '筛选', filters: { level: { dropdownLabel: '程度', dialogHeader: '选择教育程度', dialogButtonLabel: '按教育程度' }, language: { dropdownLabel: '语言', dialogHeader: '选择语言', dialogButtonLabel: '按语言', searchPlaceholder: '键入以搜索语言', }, reviewed: { dropdownLabel: '已审核', dialogHeader: '已审核内容', dialogButtonLabel: '筛选', optionLabel: '仅显示已审核的内容', }, contentTypes: { dropdownLabel: '内容类型', dialogHeader: '选择内容类型', dialogButtonLabel: '按内容类型', searchPlaceholder: '键入以搜索内容类型', }, disciplines: { dropdownLabel: '学科', dialogHeader: '选择学科', dialogButtonLabel: '按学科', searchPlaceholder: '键入以搜索学科', }, licenses: { dropdownLabel: '许可证', dialogHeader: '选择许可证类型', dialogButtonLabel: '按许可证类型', options: { modified: '可以修改', commercial: '允许商业用途' }, }, }, clearFilters: '清除所有过滤器', contentSearchFieldPlaceholder: '搜索内容', loadingContentTitle: '正在为您加载内容...', loadingContentSubtitle: '请稍等', by: '作者', dropdownButton: '打开下拉菜单', paginationNavigation: '分页导航', page: '页', currentPage: '当前页面', nextPage: '转到下一页', previousPage: '转到上一页', contentPreviewButtonLabel: '预览', contentDownloadButtonLabel: '获取内容', reuseContentTabLabel: '获取共享内容', contentPublisherPanelHeader: '出版商信息', noContentFoundDesc: '没有找到符合您的搜索条件的内容。', h5pType: 'H5P类型', level: '等级', size: '大小', failedFetchingData: '获取数据失败', filterErrorMessage: '出问题了,请重新加载页面。', in: 'in', navigateToParent: '导航到父级', a11yTitleShowLabel: '显示 AT 的标签', a11yTitleHideLabel: '隐藏 AT 的标签', reuseSuccess: ':title 已成功从 H5P Hub 导入。', }; PK*\(88(h5plib/v127/joubel/editor/language/zh.jsnu[H5PEditor.language.core = { missingTranslation: '[缺少翻译 :key]', loading: '加载中,请稍候...', selectLibrary: '请选择用于创建内容的库。', unknownFieldPath: '找不到":path".', notImageField: '":path" 不是图片。', notImageOrDimensionsField: '":path" 不是图片或尺寸字段。', requiredProperty: ':property 是必需的,并且必须有一个值。', onlyNumbers: ':property 的值只能包含数字。', illegalDecimalNumber: ':property 只能包含最大为:decimals小数的数字。', exceedsMax: ':property 的值超过了:max的最大值。', listExceedsMax: '列表超过了:max个项目的上限。', belowMin: ':property 值低于:min的最小值。', listBelowMin: '该列表至少需要:min个项目,内容才能正常运行。', outOfStep: ':property 的值只能以:step为单位更改。', add: '添加', addFile: '添加文件', removeFile: '移除文件', confirmRemoval: '您确定要删除此:type吗?', removeImage: '移除图片', confirmImageRemoval: '这将删除您的图片。 您确定要继续吗?', changeFile: '更改文件', changeLibrary: '更改内容类型?', semanticsError: '语义错误::error', missingProperty: '字段:index缺少其:property属性。', expandCollapse: '展开/折叠', addEntity: '添加:entity', tooLong: '字段值太长,应包含最多:max个字母。', invalidFormat: '字段值包含无效的格式或被禁止的字符。', confirmChangeLibrary: '继续操作将丢失使用当前内容类型创建的所有工作。 您确定要更改内容类型吗?', commonFields: '文字替代和翻译', commonFieldsDescription: '您可以在此处编辑设置或翻译此内容中使用的文本。', uploading: '正在上传,请稍候...', noFollow: '无法追踪字段":path".', editCopyright: '编辑版权', close: '关闭', tutorial: '使用教程', editMode: '编辑模式', listLabel: '列表', uploadError: '文件上传错误', fileToLarge: '您尝试上传的文件可能太大了。', unknownFileUploadError: '未知文件上传错误', noSemantics: '错误,无法加载内容类型表格。', editImage: '编辑图片', saveLabel: '保存', cancelLabel: '取消', resetToOriginalLabel: '重置为原始状态', loadingImageEditor: '正在加载图片编辑器,请稍候...', selectFiletoUpload: '请选择要上传的文件', or: '或', enterAudioUrl: '请输入音频源URL', enterVideoUrl: '请输入视频源URL', enterAudioTitle: '粘贴链接或其他音频源URL', enterVideoTitle: '粘贴YouTube链接或其他视频源URL', uploadAudioTitle: '上传音频文件', uploadVideoTitle: '上传视频文件', addVideoDescription: 'H5P 支持格式为 mp4、webm 或 ogv 的所有外部视频源,如 Vimeo Pro,并支持 YouTube 和 Panopto 链接。', insert: '插入', cancel: '取消', height: '高度', width: '宽度', textField: '文本字段', numberField: '数字字段', orderItemUp: '向上', orderItemDown: '向下', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: '移除', hubPanelLabel: '选择内容类型', importantInstructions: '重要说明', showImportantInstructions: '显示重要说明', hideImportantInstructions: '隐藏重要说明', hide: '隐藏', example: '示例', createContentTabLabel: '创建内容', uploadTabLabel: '上传', uploadPlaceholder: '没有选择文件', uploadInstructionsTitle: '上传H5P文件。', uploadInstructionsContent: '您可以从H5P.org中的示例开始。', uploadFileButtonLabel: '上传文件', uploadFileButtonChangeLabel: '替换文件', uploadingThrobber: '正在上传...', uploadSuccess: ':title 已成功上传!', unableToInterpretError: '无法解释响应。', unableToInterpretSolution: '请检查您的错误日志。', h5pFileWrongExtensionTitle: '所选文件无法上传', h5pFileWrongExtensionContent: '仅允许使用扩展名为.h5p的文件。', h5pFileValidationFailedTitle: '无法验证H5P文件。', h5pFileValidationFailedContent: '确保上传的H5P包含有效的H5P内容。如果H5P仅包含库文件,则应通过“ H5P库”页面上载。', h5pFileUploadServerErrorTitle: '无法上传H5P文件', h5pFileUploadServerErrorContent: '发生意外错误。 请检查服务器错误日志中是否有更多信息。', contentTypeSectionAll: '所有内容类型', searchResults: '搜索结果', contentTypeSearchFieldPlaceholder: '搜索内容类型', contentTypeInstallButtonLabel: '安装', contentTypeInstallingButtonLabel: '正在安装', contentTypeUseButtonLabel: '应用', contentTypeDetailButtonLabel: '详细信息', contentTypeUpdateButtonLabel: '更新', contentTypeUpdatingButtonLabel: '正在更新', contentTypeGetButtonLabel: '获取', contentTypeBackButtonLabel: '返回', contentTypeIconAltText: '图标', contentTypeInstallSuccess: ':contentType 成功安装!', contentTypeUpdateSuccess: ':contentType 成功更新!', contentTypeInstallError: ':contentType 无法安装。请与您的管理员联系。', contentTypeLicensePanelTitle: '许可证', contentTypeDemoButtonLabel: '演示内容', numResults: ':num 条结果', show: '显示', recentlyUsedFirst: '最近使用', popularFirst: '热门', newestFirst: '最新', aToZ: '按名称', noResultsFound: '未找到结果', noResultsFoundDesc: '没有与您的搜索条件匹配的内容类型。', readMore: '更多', readLess: '更少', contentTypeOwner: '由 :owner', contentTypeUnsupportedApiVersionTitle: '此内容类型需要一个更新的核心版本', contentTypeUnsupportedApiVersionContent: '请与您的系统管理员联系安装必要的更新', contentTypeUpdateAvailable: '有可用更新', contentTypeRestricted: '受限内容类型', contentTypeRestrictedDesc: '管理员已限制使用此内容类型。', contentTypeNotInstalled: '内容类型未安装', contentTypeNotInstalledDesc: '您无权安装内容类型。', theContentType: '内容类型', currentMenuSelected: '当前选择', errorCommunicatingHubTitle: '无法与H5P Hub通信。', errorCommunicatingHubContent: '出错了,请再试一次。', warningNoContentTypesInstalled: '您没有安装任何内容类型。', warningChangeBrowsingToSeeResults: '单击全部以获取可以安装的所有内容类型的列表。', warningUpdateAvailableTitle: '有:contentType的更新可用。', warningUpdateAvailableBody: '更新到最新版本以获得更好的使用体验。', licenseDescription: '该许可证的某些功能如下所示。 单击上方的信息图标以阅读原始许可证文本。', licenseModalTitle: '许可证详细信息', licenseModalSubtitle: '选择一个许可证以查看有关正确使用的信息', licenseUnspecified: '未指定', licenseCanUseCommercially: '可以商业使用', licenseCanModify: '可以修改', licenseCanDistribute: '可以分发', licenseCanSublicense: '可以再许可', licenseCanHoldLiable: '承担责任', licenseCannotHoldLiable: '不承担责任', licenseMustIncludeCopyright: '必须包含版权信息', licenseMustIncludeLicense: '必须包含许可证', licenseFetchDetailsFailed: '获取许可证详细信息失败', imageLightboxTitle: '图片', imageLightBoxProgress: ':num / :total', nextImage: '下一个图片', previousImage: '上一个图片', screenshots: '屏幕截图', reloadButtonLabel: '重新加载', videoQuality: '视频质量标签', videoQualityDescription: '此标签可帮助用户识别视频的当前视频质量。 例如。 1080p,720p,高清或手机端', videoQualityDefaultLabel: '视频质量 :index', noContentTypesAvailable: '没有可用的内容类型', noContentTypesAvailableDesc: '您的网站在连接到H5P.org并列出可用的内容类型时遇到问题。', contentTypeCacheOutdated: '内容类型列表已过时', contentTypeCacheOutdatedDesc: '您的网站无法连接到H5P.org以检查内容类型更新。 您可能无法更新或安装新的内容类型。', tryAgain: '再试一次', getHelp: '获取帮助', untitled: '未命名:libraryTitle', title: '标题', metadata: '元数据', addTitle: '添加标题', usedForSearchingReportsAndCopyrightInformation: '用于搜索,报告和版权信息', metadataSharingAndLicensingInfo: '元数据(共享和许可信息)', fillInTheFieldsBelow: '请填写下面的字段', saveMetadata: '保存元数据', addAuthor: '保存作者', confirmRemoveAuthor: '您确定要删除这个作者吗?', addNewChange: '新增变更', confirmDeleteChangeLog: '您确定要删除这个更新日志条目吗?', changelogDescription: '有些许可证要求记录并显示对原始作品或衍生作品所做的更改。 您可以根据许可证要求的原因在此处记录您的更改,或者只是为了让自己和他人跟踪对此内容所做的更改。', logThisChange: '记录此更改', newChangeHasBeenLogged: '已记录新的更改', loggedChanges: '已记录的更改', noChangesHaveBeenLogged: '尚未记录任何更改', errorHeader: '发生错误', errorCalculatingMaxScore: '无法计算此内容的最高分。 当前最高分数设定为0。如果您觉得设置不正确,请与管理员联系。', maxScoreSemanticsMissing: '在内容中找不到预期的语义。', copyButton: '复制', copiedButton: '已复制', pasteButton: '粘贴', pasteAndReplaceButton: '粘贴并替换', pasteContent: '替换内容', confirmPasteContent: '通过此操作,您将用剪贴板中的内容替换当前内容。 当前内容将丢失。 您确定要继续吗?', confirmPasteButtonText: '替换内容', copyToClipboard: '将H5P内容复制到剪贴板', copiedToClipboard: '内容已复制到剪贴板', pasteFromClipboard: '从剪贴板粘贴H5P内容', pasteAndReplaceFromClipboard: '用剪贴板中的H5P内容替换现有内容', pasteNoContent: '剪贴板中没有H5P内容', pasteError: '无法从剪贴板粘贴', pasteContentNotSupported: '当前环境不支持H5P剪贴板中的内容', pasteContentRestricted: '剪贴板中的内容已在此站点上受到限制', pasteTooOld: 'H5P剪贴板中的内容(:clip)的版本低于当前环境(:local)中支持的版本,如果可能,请尝试升级要粘贴的内容,然后再次复制并尝试将其粘贴到此处。', pasteTooNew: 'H5P剪贴板中的内容(:clip)的版本高于当前环境(:local)中支持的版本,如果可能,请尝试先升级此内容,然后再尝试将其粘贴到此处。', ok: '我知道了', avTablistLabel: '插入使用', tabTitleBasicFileUpload: '上传文件', tabTitleInputLinkURL: '链接/URL', errorTooHighVersion: '参数中包含%used,而仅支持%supported或更早的版本。', errorNotSupported: '参数中包含不支持的%used。', errorParamsBroken: '参数已损坏。', libraryMissing: '缺少必需的库 %lib。', scriptMissing: '无法加载 %lib的升级脚本。', language: '语言', noLanguagesSupported: '没有支持的语言', changeLanguage: '更改语言为 :language?', thisWillPotentially: '这可能会重置所有文本和翻译。 您无法撤消此操作。 内容本身不会被更改。 您要继续吗?', notAllTextsChanged: '并非所有文本都已更改,:language仅部分覆盖。', contributeTranslations: '如果您想完善或帮助 :language的语言翻译,可以了解有关为H5P贡献翻译的信息', unknownLibrary: "很遗憾,此系统上未安装选定的内容类型 '%lib'。", proceedButtonLabel: '继续保存', enterFullscreenButtonLabel: '进入全屏', exitFullscreenButtonLabel: '退出全屏', noContentHeader: '没有合适的内容?', noContentSuggestion: '自己创建一个吧!', tutorials: '使用教程', contentSectionAll: '所有共享内容', popularContent: '热门内容', allPopular: '所有热门', newOnTheHub: '最新添加', allNew: '所有最新内容', filterBy: '筛选条件', filter: '筛选', filters: { level: { dropdownLabel: '程度', dialogHeader: '选择教育程度', dialogButtonLabel: '按教育程度' }, language: { dropdownLabel: '语言', dialogHeader: '选择语言', dialogButtonLabel: '按语言', searchPlaceholder: '键入以搜索语言', }, reviewed: { dropdownLabel: '已审核', dialogHeader: '已审核内容', dialogButtonLabel: '筛选', optionLabel: '仅显示已审核的内容', }, contentTypes: { dropdownLabel: '内容类型', dialogHeader: '选择内容类型', dialogButtonLabel: '按内容类型', searchPlaceholder: '键入以搜索内容类型', }, disciplines: { dropdownLabel: '学科', dialogHeader: '选择学科', dialogButtonLabel: '按学科', searchPlaceholder: '键入以搜索学科', }, licenses: { dropdownLabel: '许可证', dialogHeader: '选择许可证类型', dialogButtonLabel: '按许可证类型', options: { modified: '可以修改', commercial: '允许商业用途' }, }, }, clearFilters: '清除所有过滤器', contentSearchFieldPlaceholder: '搜索内容', loadingContentTitle: '正在为您加载内容...', loadingContentSubtitle: '请稍等', by: '作者', dropdownButton: '打开下拉菜单', paginationNavigation: '分页导航', page: '页', currentPage: '当前页面', nextPage: '转到下一页', previousPage: '转到上一页', contentPreviewButtonLabel: '预览', contentDownloadButtonLabel: '获取内容', reuseContentTabLabel: '获取共享内容', contentPublisherPanelHeader: '出版商信息', noContentFoundDesc: '没有找到符合您的搜索条件的内容。', h5pType: 'H5P类型', level: '等级', size: '大小', failedFetchingData: '获取数据失败', filterErrorMessage: '出问题了,请重新加载页面。', in: 'in', navigateToParent: '导航到父级', a11yTitleShowLabel: '显示 AT 的标签', a11yTitleHideLabel: '隐藏 AT 的标签', reuseSuccess: ':title 已成功从 H5P Hub 导入。', }; PK*\`ƅXX(h5plib/v127/joubel/editor/language/ru.jsnu[H5PEditor.language.core = { missingTranslation: '[Отсутствует перевод :key]', loading: 'Загрузка, пожалуйста подождите...', selectLibrary: 'Выберите библиотеку, которую вы хотите использовать для своего контента.', unknownFieldPath: 'Невозможно найти ":path".', notImageField: '":path" это не изображение.', notImageOrDimensionsField: '":path" не является изображением или полем для размеров.', requiredProperty: 'Это :property обязательно и должно иметь значение.', onlyNumbers: 'Это :property значение может содержать только цифры.', illegalDecimalNumber: 'Это :property может содержать только числа с максимальным количеством :decimals десятичных знаков.', exceedsMax: 'Это :property значение превышает максимум :max.', listExceedsMax: 'Список превышает максимальное количество :max элементов.', belowMin: 'Это :property значение ниже минимума :min.', listBelowMin: 'Списку необходимо как минимум :min элементов для содержимого, чтобы функционировать должным образом.', outOfStep: 'Это :property значение может быть изменено только с шагом :step.', add: 'Добавить', addFile: 'Добавить файл', removeFile: 'Удалить файл', confirmRemoval: 'Вы уверены, что хотите удалить :type?', removeImage: 'Удалить изображение', confirmImageRemoval: 'Это удалит ваше изображение. Вы уверены, что хотите продолжить?', changeFile: 'Изменить файл', changeLibrary: 'Изменить тип контента?', semanticsError: 'Ошибка семантики: :error', missingProperty: 'Поле :index отсутствует это :property свойство.', expandCollapse: 'Развернуть/Свернуть', addEntity: 'Добавить :entity', tooLong: 'Значение поля слишком длинное, должно содержать :max знаков или меньше.', invalidFormat: 'Значение поля содержит неверный формат или символы, которые запрещены.', confirmChangeLibrary: 'Делая это, вы потеряете всю работу, выполненную с текущим типом контента. Вы уверены, что хотите изменить тип контента?', commonFields: 'Переопределение текста и переводы', commonFieldsDescription: 'Здесь вы можете редактировать настройки или переводить тексты, используемые в этом контенте.', uploading: 'Загрузка, пожалуйста, подождите ...', noFollow: 'Недопустимо использовать поле ":path".', editCopyright: 'Изменить авторское право', close: 'Закрыть', tutorial: 'Руководство', editMode: 'Режим редактирования', listLabel: 'Список', uploadError: 'Ошибка загрузки файла', fileToLarge: 'Файл, который вы пытаетесь загрузить, может быть слишком большим.', unknownFileUploadError: 'Неизвестная ошибка загрузки файла', noSemantics: 'Ошибка, не удалось загрузить форму типа контента.', editImage: 'Изменить изображение', saveLabel: 'Сохранить', cancelLabel: 'Отмена', resetToOriginalLabel: 'Сброс к оригиналу', loadingImageEditor: 'Загрузка графического редактора, пожалуйста, подождите ...', selectFiletoUpload: 'Выберите файл для загрузки', or: 'или', enterAudioUrl: 'Введите URL аудио источника', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Вставить ссылку или другой URL источника аудио', enterVideoTitle: 'Вставить ссылку на YouTube или другой источник видео', uploadAudioTitle: 'Загрузить аудио файл', uploadVideoTitle: 'Загрузить видео файл', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Вставить', cancel: 'Отмена', height: 'высота', width: 'ширина', textField: 'текстовое поле', numberField: 'числовое поле', orderItemUp: 'Возрастающий порядок элементов', orderItemDown: 'Убывающий порядок элементов', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Удалить элемент', hubPanelLabel: 'Выберите тип контента', importantInstructions: 'Важные инструкции', showImportantInstructions: 'Показать инструкции', hideImportantInstructions: 'Скрыть важные инструкции', hide: 'Скрыть', example: 'Пример', createContentTabLabel: 'Создать контент', uploadTabLabel: 'Загрузить', uploadPlaceholder: 'Файл не выбран', uploadInstructionsTitle: 'Загрузить H5P файл.', uploadInstructionsContent: 'Вы можете начать с примеров из H5P.org.', uploadFileButtonLabel: 'Загрузить файл', uploadFileButtonChangeLabel: 'Изменить файл', uploadingThrobber: 'Загрузка...', uploadSuccess: ':title был успешно загружен!', unableToInterpretError: 'Невозможно интерпретировать ответ.', unableToInterpretSolution: 'Пожалуйста, проверьте ваш журнал ошибок.', h5pFileWrongExtensionTitle: 'Выбранный файл не может быть загружен', h5pFileWrongExtensionContent: 'Разрешены только файлы с расширением .h5p.', h5pFileValidationFailedTitle: 'Не удалось проверить H5P файл.', h5pFileValidationFailedContent: 'Убедитесь, что загруженный H5P содержит действительный контент H5P. H5P файлы, содержащие только библиотеки, должны быть загружены через страницу библиотек H5P.', h5pFileUploadServerErrorTitle: 'Файл H5P не может быть загружен', h5pFileUploadServerErrorContent: 'Произошла непредвиденная ошибка. Проверьте журнал ошибок вашего сервера для больших деталей.', contentTypeSectionAll: 'Все типы контента', searchResults: 'Результаты поиска', contentTypeSearchFieldPlaceholder: 'Поиск типов контента', contentTypeInstallButtonLabel: 'Установить', contentTypeInstallingButtonLabel: 'Установка', contentTypeUseButtonLabel: 'Использовать', contentTypeDetailButtonLabel: 'Подробности', contentTypeUpdateButtonLabel: 'Обновить', contentTypeUpdatingButtonLabel: 'Обновление', contentTypeGetButtonLabel: 'Получить', contentTypeBackButtonLabel: 'Назад', contentTypeIconAltText: 'Иконка', contentTypeInstallSuccess: ':contentType успешно установлен!', contentTypeUpdateSuccess: ':contentType успешно обновлен!', contentTypeInstallError: ':contentType не может быть установлен. Свяжитесь с администратором.', contentTypeLicensePanelTitle: 'Лицензия', contentTypeDemoButtonLabel: 'Демо контент', numResults: ':num результатов', show: 'Показать', recentlyUsedFirst: 'Сначала недавно использованные', popularFirst: 'Сначала популярные', newestFirst: 'Сначала самые новые', aToZ: 'от A к Z', noResultsFound: 'Результаты не найдены', noResultsFoundDesc: 'Нет типа контента, соответствующего вашим критериям поиска.', readMore: 'Читать больше', readLess: 'Читать меньше', contentTypeOwner: 'От :owner', contentTypeUnsupportedApiVersionTitle: 'Этот тип контента требует более новой версии ядра', contentTypeUnsupportedApiVersionContent: 'Обратитесь к системному администратору, чтобы предоставить вам необходимые обновления', contentTypeUpdateAvailable: 'Доступно обновление', contentTypeRestricted: 'Ограниченный тип контента', contentTypeRestrictedDesc: 'Использование этого типа контента было ограничено администратором.', contentTypeNotInstalled: 'Тип контента не установлен', contentTypeNotInstalledDesc: 'У вас нет разрешения на установку типов контента.', theContentType: 'тип контента', currentMenuSelected: 'текущий выбор', errorCommunicatingHubTitle: 'Не может соединиться с хабом.', errorCommunicatingHubContent: 'Произошла ошибка. Пожалуйста, попробуйте еще раз.', warningNoContentTypesInstalled: 'У вас не установлены типы контента', warningChangeBrowsingToSeeResults: 'Нажмите на Все чтобы получить список всех типов контента, которые вы можете установить.', warningUpdateAvailableTitle: 'Новая версия :contentType доступна.', warningUpdateAvailableBody: 'Обновление до последней версии для улучшения опыта.', licenseDescription: 'Некоторые функции этой лицензии указаны ниже. Нажмите на иконку информации выше, чтобы прочитать исходный текст лицензии.', licenseModalTitle: 'Детали лицензии', licenseModalSubtitle: 'Выберите лицензию для просмотра информации о правильном использовании', licenseUnspecified: 'Unspecified', licenseCanUseCommercially: 'Можно использовать в коммерческих целях', licenseCanModify: 'Можно изменить', licenseCanDistribute: 'Можно распространять', licenseCanSublicense: 'Может сублицензировать', licenseCanHoldLiable: 'Может нести ответственность', licenseCannotHoldLiable: 'Не может нести ответственность', licenseMustIncludeCopyright: 'Должно включать авторское право', licenseMustIncludeLicense: 'Должен включать лицензию', licenseFetchDetailsFailed: 'Не удалось получить информацию о лицензии', imageLightboxTitle: 'Изображения', imageLightBoxProgress: ':num из :total', nextImage: 'Следующее изображение', previousImage: 'Предыдущее изображение', screenshots: 'Скриншоты', reloadButtonLabel: 'Обновить', videoQuality: 'Надпись разрешения видео', videoQualityDescription: 'Эта надпись помогает пользователю определить текущее качество видео. Например. 1080p, 720p, HD или мобильный', videoQualityDefaultLabel: 'Разрешение видео :index', noContentTypesAvailable: 'Нет доступных типов контента', noContentTypesAvailableDesc: 'У вашего сайта проблемы с подключением к H5P.org и списку доступных типов контента.', contentTypeCacheOutdated: 'Список типов контента устарел', contentTypeCacheOutdatedDesc: 'Ваш сайт испытывает трудности при подключении к H5P.org для проверки наличия обновлений типа контента. Возможно, вы не сможете обновить или установить новые типы контента.', tryAgain: 'Попробуйте снова', getHelp: 'Получить помощь', untitled: 'Без названия :libraryTitle', title: 'Название', metadata: 'Метаданные', addTitle: 'Добавить название', usedForSearchingReportsAndCopyrightInformation: 'Используется для поиска, отчетов и информации об авторских правах', metadataSharingAndLicensingInfo: 'Метаданные (информация о совместном использовании и лицензировании)', fillInTheFieldsBelow: 'Заполните поля ниже', saveMetadata: 'Сохранить метаданные', addAuthor: 'Сохранить автора', confirmRemoveAuthor: 'Вы уверены, что хотите удалить этого автора?', addNewChange: 'Добавить новое изменение', confirmDeleteChangeLog: 'Вы уверены, что хотите удалить эту запись в журнале изменений?', changelogDescription: 'Некоторые лицензии требуют, чтобы изменения, внесенные в оригинальную работу или производные, регистрировались и отображались. Вы можете регистрировать свои изменения здесь по причинам лицензирования или просто для того, чтобы позволить себе и другим отслеживать изменения, внесенные в этот контент.', logThisChange: 'Зарегистрировать это изменение', newChangeHasBeenLogged: 'Новое изменение было зарегистрировано', loggedChanges: 'Зарегистрированные изменения', noChangesHaveBeenLogged: 'Изменение не было зарегистрировано', errorHeader: 'Произошла ошибка', errorCalculatingMaxScore: 'Не удалось рассчитать максимальный балл для этого контента. Максимальный балл принимается равным 0. Свяжитесь с администратором, если это не так.', maxScoreSemanticsMissing: 'Не удалось найти ожидаемую семантику в содержании.', copyButton: 'Копировать', copiedButton: 'Скопировано', pasteButton: 'Вставить', pasteAndReplaceButton: 'Вставить и Заменить', pasteContent: 'Заменить содержимое', confirmPasteContent: 'Сделав это, вы замените текущий контент содержимым из буфера обмена. Текущий контент будет потерян. Вы уверены, что хотите продолжить?', confirmPasteButtonText: 'Заменить контент', copyToClipboard: 'Скопировать содержимое H5P в буфер обмена', copiedToClipboard: 'Контент скопирован в буфер обмена', pasteFromClipboard: 'Вставить содержимое H5P из буфера обмена', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'Нет содержимого H5P в буфере обмена', pasteError: 'Не удалось вставить из буфера обмена', pasteContentNotSupported: 'Содержимое в буфере обмена H5P не поддерживается в этом контексте.', pasteContentRestricted: 'Содержимое буфера обмена было ограничено на этом сайте.', pasteTooOld: 'Содержимое буфера обмена H5P имеет более низкую версию (:clip), чем поддерживаемое в данном контексте (:local), если возможно, попытайтесь вставить обновленное содержимое, скопировать его снова и вставить его сюда.', pasteTooNew: 'Содержимое буфера обмена H5P имеет более высокую версию (:clip), чем поддерживаемое в данном контексте (:local), по возможности сначала попытайтесь обновить это содержимое, а затем попытайтесь вставить его сюда снова.', ok: 'ОК', avTablistLabel: 'Вставить с помощью', tabTitleBasicFileUpload: 'Загрузка файла', tabTitleInputLinkURL: 'Ссылка/URL', errorTooHighVersion: 'Параметры содержат %used пока только %supported или ранее поддерживаемые.', errorNotSupported: 'Параметры содержат %used которые не поддерживаются.', errorParamsBroken: 'Параметры нарушены.', libraryMissing: 'Отсутствует необходимая библиотека %lib.', scriptMissing: 'Не удалось загрузить скрипт обновления для %lib.', language: 'Язык', noLanguagesSupported: 'Языки не поддерживаются', changeLanguage: 'Изменить язык на :language?', thisWillPotentially: 'Это потенциально сбросит весь текст и переводы. Вы не можете отменить это. Сам контент не будет изменен. Вы хотите продолжить?', notAllTextsChanged: 'Не все тексты были изменены, есть только частичные переводы для :language.', contributeTranslations: 'Если вы хотите завершить перевод для :language вы можете узнать о том как внести переводы в H5P', unknownLibrary: "К сожалению, выбранный тип контента '%lib' isn не установлен в этой системе.", proceedButtonLabel: 'Перейти к сохранению', enterFullscreenButtonLabel: 'Войти в полноэкранный режим', exitFullscreenButtonLabel: 'Покинуть полноэкранный режим', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\(88+h5plib/v127/joubel/editor/language/zh-cn.jsnu[H5PEditor.language.core = { missingTranslation: '[缺少翻译 :key]', loading: '加载中,请稍候...', selectLibrary: '请选择用于创建内容的库。', unknownFieldPath: '找不到":path".', notImageField: '":path" 不是图片。', notImageOrDimensionsField: '":path" 不是图片或尺寸字段。', requiredProperty: ':property 是必需的,并且必须有一个值。', onlyNumbers: ':property 的值只能包含数字。', illegalDecimalNumber: ':property 只能包含最大为:decimals小数的数字。', exceedsMax: ':property 的值超过了:max的最大值。', listExceedsMax: '列表超过了:max个项目的上限。', belowMin: ':property 值低于:min的最小值。', listBelowMin: '该列表至少需要:min个项目,内容才能正常运行。', outOfStep: ':property 的值只能以:step为单位更改。', add: '添加', addFile: '添加文件', removeFile: '移除文件', confirmRemoval: '您确定要删除此:type吗?', removeImage: '移除图片', confirmImageRemoval: '这将删除您的图片。 您确定要继续吗?', changeFile: '更改文件', changeLibrary: '更改内容类型?', semanticsError: '语义错误::error', missingProperty: '字段:index缺少其:property属性。', expandCollapse: '展开/折叠', addEntity: '添加:entity', tooLong: '字段值太长,应包含最多:max个字母。', invalidFormat: '字段值包含无效的格式或被禁止的字符。', confirmChangeLibrary: '继续操作将丢失使用当前内容类型创建的所有工作。 您确定要更改内容类型吗?', commonFields: '文字替代和翻译', commonFieldsDescription: '您可以在此处编辑设置或翻译此内容中使用的文本。', uploading: '正在上传,请稍候...', noFollow: '无法追踪字段":path".', editCopyright: '编辑版权', close: '关闭', tutorial: '使用教程', editMode: '编辑模式', listLabel: '列表', uploadError: '文件上传错误', fileToLarge: '您尝试上传的文件可能太大了。', unknownFileUploadError: '未知文件上传错误', noSemantics: '错误,无法加载内容类型表格。', editImage: '编辑图片', saveLabel: '保存', cancelLabel: '取消', resetToOriginalLabel: '重置为原始状态', loadingImageEditor: '正在加载图片编辑器,请稍候...', selectFiletoUpload: '请选择要上传的文件', or: '或', enterAudioUrl: '请输入音频源URL', enterVideoUrl: '请输入视频源URL', enterAudioTitle: '粘贴链接或其他音频源URL', enterVideoTitle: '粘贴YouTube链接或其他视频源URL', uploadAudioTitle: '上传音频文件', uploadVideoTitle: '上传视频文件', addVideoDescription: 'H5P 支持格式为 mp4、webm 或 ogv 的所有外部视频源,如 Vimeo Pro,并支持 YouTube 和 Panopto 链接。', insert: '插入', cancel: '取消', height: '高度', width: '宽度', textField: '文本字段', numberField: '数字字段', orderItemUp: '向上', orderItemDown: '向下', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: '移除', hubPanelLabel: '选择内容类型', importantInstructions: '重要说明', showImportantInstructions: '显示重要说明', hideImportantInstructions: '隐藏重要说明', hide: '隐藏', example: '示例', createContentTabLabel: '创建内容', uploadTabLabel: '上传', uploadPlaceholder: '没有选择文件', uploadInstructionsTitle: '上传H5P文件。', uploadInstructionsContent: '您可以从H5P.org中的示例开始。', uploadFileButtonLabel: '上传文件', uploadFileButtonChangeLabel: '替换文件', uploadingThrobber: '正在上传...', uploadSuccess: ':title 已成功上传!', unableToInterpretError: '无法解释响应。', unableToInterpretSolution: '请检查您的错误日志。', h5pFileWrongExtensionTitle: '所选文件无法上传', h5pFileWrongExtensionContent: '仅允许使用扩展名为.h5p的文件。', h5pFileValidationFailedTitle: '无法验证H5P文件。', h5pFileValidationFailedContent: '确保上传的H5P包含有效的H5P内容。如果H5P仅包含库文件,则应通过“ H5P库”页面上载。', h5pFileUploadServerErrorTitle: '无法上传H5P文件', h5pFileUploadServerErrorContent: '发生意外错误。 请检查服务器错误日志中是否有更多信息。', contentTypeSectionAll: '所有内容类型', searchResults: '搜索结果', contentTypeSearchFieldPlaceholder: '搜索内容类型', contentTypeInstallButtonLabel: '安装', contentTypeInstallingButtonLabel: '正在安装', contentTypeUseButtonLabel: '应用', contentTypeDetailButtonLabel: '详细信息', contentTypeUpdateButtonLabel: '更新', contentTypeUpdatingButtonLabel: '正在更新', contentTypeGetButtonLabel: '获取', contentTypeBackButtonLabel: '返回', contentTypeIconAltText: '图标', contentTypeInstallSuccess: ':contentType 成功安装!', contentTypeUpdateSuccess: ':contentType 成功更新!', contentTypeInstallError: ':contentType 无法安装。请与您的管理员联系。', contentTypeLicensePanelTitle: '许可证', contentTypeDemoButtonLabel: '演示内容', numResults: ':num 条结果', show: '显示', recentlyUsedFirst: '最近使用', popularFirst: '热门', newestFirst: '最新', aToZ: '按名称', noResultsFound: '未找到结果', noResultsFoundDesc: '没有与您的搜索条件匹配的内容类型。', readMore: '更多', readLess: '更少', contentTypeOwner: '由 :owner', contentTypeUnsupportedApiVersionTitle: '此内容类型需要一个更新的核心版本', contentTypeUnsupportedApiVersionContent: '请与您的系统管理员联系安装必要的更新', contentTypeUpdateAvailable: '有可用更新', contentTypeRestricted: '受限内容类型', contentTypeRestrictedDesc: '管理员已限制使用此内容类型。', contentTypeNotInstalled: '内容类型未安装', contentTypeNotInstalledDesc: '您无权安装内容类型。', theContentType: '内容类型', currentMenuSelected: '当前选择', errorCommunicatingHubTitle: '无法与H5P Hub通信。', errorCommunicatingHubContent: '出错了,请再试一次。', warningNoContentTypesInstalled: '您没有安装任何内容类型。', warningChangeBrowsingToSeeResults: '单击全部以获取可以安装的所有内容类型的列表。', warningUpdateAvailableTitle: '有:contentType的更新可用。', warningUpdateAvailableBody: '更新到最新版本以获得更好的使用体验。', licenseDescription: '该许可证的某些功能如下所示。 单击上方的信息图标以阅读原始许可证文本。', licenseModalTitle: '许可证详细信息', licenseModalSubtitle: '选择一个许可证以查看有关正确使用的信息', licenseUnspecified: '未指定', licenseCanUseCommercially: '可以商业使用', licenseCanModify: '可以修改', licenseCanDistribute: '可以分发', licenseCanSublicense: '可以再许可', licenseCanHoldLiable: '承担责任', licenseCannotHoldLiable: '不承担责任', licenseMustIncludeCopyright: '必须包含版权信息', licenseMustIncludeLicense: '必须包含许可证', licenseFetchDetailsFailed: '获取许可证详细信息失败', imageLightboxTitle: '图片', imageLightBoxProgress: ':num / :total', nextImage: '下一个图片', previousImage: '上一个图片', screenshots: '屏幕截图', reloadButtonLabel: '重新加载', videoQuality: '视频质量标签', videoQualityDescription: '此标签可帮助用户识别视频的当前视频质量。 例如。 1080p,720p,高清或手机端', videoQualityDefaultLabel: '视频质量 :index', noContentTypesAvailable: '没有可用的内容类型', noContentTypesAvailableDesc: '您的网站在连接到H5P.org并列出可用的内容类型时遇到问题。', contentTypeCacheOutdated: '内容类型列表已过时', contentTypeCacheOutdatedDesc: '您的网站无法连接到H5P.org以检查内容类型更新。 您可能无法更新或安装新的内容类型。', tryAgain: '再试一次', getHelp: '获取帮助', untitled: '未命名:libraryTitle', title: '标题', metadata: '元数据', addTitle: '添加标题', usedForSearchingReportsAndCopyrightInformation: '用于搜索,报告和版权信息', metadataSharingAndLicensingInfo: '元数据(共享和许可信息)', fillInTheFieldsBelow: '请填写下面的字段', saveMetadata: '保存元数据', addAuthor: '保存作者', confirmRemoveAuthor: '您确定要删除这个作者吗?', addNewChange: '新增变更', confirmDeleteChangeLog: '您确定要删除这个更新日志条目吗?', changelogDescription: '有些许可证要求记录并显示对原始作品或衍生作品所做的更改。 您可以根据许可证要求的原因在此处记录您的更改,或者只是为了让自己和他人跟踪对此内容所做的更改。', logThisChange: '记录此更改', newChangeHasBeenLogged: '已记录新的更改', loggedChanges: '已记录的更改', noChangesHaveBeenLogged: '尚未记录任何更改', errorHeader: '发生错误', errorCalculatingMaxScore: '无法计算此内容的最高分。 当前最高分数设定为0。如果您觉得设置不正确,请与管理员联系。', maxScoreSemanticsMissing: '在内容中找不到预期的语义。', copyButton: '复制', copiedButton: '已复制', pasteButton: '粘贴', pasteAndReplaceButton: '粘贴并替换', pasteContent: '替换内容', confirmPasteContent: '通过此操作,您将用剪贴板中的内容替换当前内容。 当前内容将丢失。 您确定要继续吗?', confirmPasteButtonText: '替换内容', copyToClipboard: '将H5P内容复制到剪贴板', copiedToClipboard: '内容已复制到剪贴板', pasteFromClipboard: '从剪贴板粘贴H5P内容', pasteAndReplaceFromClipboard: '用剪贴板中的H5P内容替换现有内容', pasteNoContent: '剪贴板中没有H5P内容', pasteError: '无法从剪贴板粘贴', pasteContentNotSupported: '当前环境不支持H5P剪贴板中的内容', pasteContentRestricted: '剪贴板中的内容已在此站点上受到限制', pasteTooOld: 'H5P剪贴板中的内容(:clip)的版本低于当前环境(:local)中支持的版本,如果可能,请尝试升级要粘贴的内容,然后再次复制并尝试将其粘贴到此处。', pasteTooNew: 'H5P剪贴板中的内容(:clip)的版本高于当前环境(:local)中支持的版本,如果可能,请尝试先升级此内容,然后再尝试将其粘贴到此处。', ok: '我知道了', avTablistLabel: '插入使用', tabTitleBasicFileUpload: '上传文件', tabTitleInputLinkURL: '链接/URL', errorTooHighVersion: '参数中包含%used,而仅支持%supported或更早的版本。', errorNotSupported: '参数中包含不支持的%used。', errorParamsBroken: '参数已损坏。', libraryMissing: '缺少必需的库 %lib。', scriptMissing: '无法加载 %lib的升级脚本。', language: '语言', noLanguagesSupported: '没有支持的语言', changeLanguage: '更改语言为 :language?', thisWillPotentially: '这可能会重置所有文本和翻译。 您无法撤消此操作。 内容本身不会被更改。 您要继续吗?', notAllTextsChanged: '并非所有文本都已更改,:language仅部分覆盖。', contributeTranslations: '如果您想完善或帮助 :language的语言翻译,可以了解有关为H5P贡献翻译的信息', unknownLibrary: "很遗憾,此系统上未安装选定的内容类型 '%lib'。", proceedButtonLabel: '继续保存', enterFullscreenButtonLabel: '进入全屏', exitFullscreenButtonLabel: '退出全屏', noContentHeader: '没有合适的内容?', noContentSuggestion: '自己创建一个吧!', tutorials: '使用教程', contentSectionAll: '所有共享内容', popularContent: '热门内容', allPopular: '所有热门', newOnTheHub: '最新添加', allNew: '所有最新内容', filterBy: '筛选条件', filter: '筛选', filters: { level: { dropdownLabel: '程度', dialogHeader: '选择教育程度', dialogButtonLabel: '按教育程度' }, language: { dropdownLabel: '语言', dialogHeader: '选择语言', dialogButtonLabel: '按语言', searchPlaceholder: '键入以搜索语言', }, reviewed: { dropdownLabel: '已审核', dialogHeader: '已审核内容', dialogButtonLabel: '筛选', optionLabel: '仅显示已审核的内容', }, contentTypes: { dropdownLabel: '内容类型', dialogHeader: '选择内容类型', dialogButtonLabel: '按内容类型', searchPlaceholder: '键入以搜索内容类型', }, disciplines: { dropdownLabel: '学科', dialogHeader: '选择学科', dialogButtonLabel: '按学科', searchPlaceholder: '键入以搜索学科', }, licenses: { dropdownLabel: '许可证', dialogHeader: '选择许可证类型', dialogButtonLabel: '按许可证类型', options: { modified: '可以修改', commercial: '允许商业用途' }, }, }, clearFilters: '清除所有过滤器', contentSearchFieldPlaceholder: '搜索内容', loadingContentTitle: '正在为您加载内容...', loadingContentSubtitle: '请稍等', by: '作者', dropdownButton: '打开下拉菜单', paginationNavigation: '分页导航', page: '页', currentPage: '当前页面', nextPage: '转到下一页', previousPage: '转到上一页', contentPreviewButtonLabel: '预览', contentDownloadButtonLabel: '获取内容', reuseContentTabLabel: '获取共享内容', contentPublisherPanelHeader: '出版商信息', noContentFoundDesc: '没有找到符合您的搜索条件的内容。', h5pType: 'H5P类型', level: '等级', size: '大小', failedFetchingData: '获取数据失败', filterErrorMessage: '出问题了,请重新加载页面。', in: 'in', navigateToParent: '导航到父级', a11yTitleShowLabel: '显示 AT 的标签', a11yTitleHideLabel: '隐藏 AT 的标签', reuseSuccess: ':title 已成功从 H5P Hub 导入。', }; PK*\I;B@B@(h5plib/v127/joubel/editor/language/eu.jsnu[H5PEditor.language.core = { missingTranslation: '[Itzulpen galdua :key]', loading: 'Kargatzen, itxaron...', selectLibrary: 'Hautatu edukia garatzeko erabili nahi duzun liburutegia.', unknownFieldPath: 'Ezin da aurkitu ":path".', notImageField: '":path" ez da irudi bat.', notImageOrDimensionsField: '":path" ez da irudi edo dimentsio eremua.', requiredProperty: ':property beharrezkoa da eta balio bat izan behar du.', onlyNumbers: ':property balioa soilik zenbakiak izan behar ditu.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: ':property balioak :max maximoa gainditzen du.', listExceedsMax: 'Zerrendaren elementu kopuruak :max maximoa gainditzen du.', belowMin: ':property balioa :min minimoaren azpitik dago.', listBelowMin: 'Zerrendak gutxienez :min elementu izan behar ditu ongi funtzionatzeko.', outOfStep: ':property balioak soilik :step -ko urratsetan alda daiteke.', add: 'Gehitu', addFile: 'Gehitu fitxategia', removeFile: 'Kendu fitxategia', confirmRemoval: 'Ziur zaude :type hau kendu nahi duzula?', removeImage: 'Kendu irudia', confirmImageRemoval: 'Honek irudia kenduko du. Ziru zaude kendu nahi duzula?', changeFile: 'Aldatu fitxategia', changeLibrary: 'Aldatu ariketa mota?', semanticsError: 'Errore semantikoa: :error', missingProperty: ':index eremuak bere :property propietatea galdu du.', expandCollapse: 'Zabaldu/Bildu', addEntity: 'Gehitu :entity', tooLong: 'Eremuaren balioa luzeegia da, gehienez :max letra izan ditzake.', invalidFormat: 'Eremuaren balioak formatu baliogabea edo debekatuta dauden karaktereak dauzka.', confirmChangeLibrary: 'Hori egiten baduzu oraingo eduki motaz egindako lan guztia galduko duzu. Ziur zaude ariketa mota aldatu nahi duzula?', commonFields: 'Testu gainidazteak eta itzulpenak', commonFieldsDescription: 'Bertan ezarpenak editatzen ahal dutuzu edo ariketa honetako testua itzul dezakezu.', uploading: 'Kargatzen, itxaron...', noFollow: 'Ezin da ":path" eremua aurkitu.', editCopyright: 'Editatu copyrighta', close: 'Itxi', tutorial: 'Tutoriala', editMode: 'Edizio modua', listLabel: 'Zerrendatu', uploadError: 'Fitxategiaren karga errorea', fileToLarge: 'Kargatzen saiatzen ari zaren fitxategia handiegia izan daiteke.', unknownFileUploadError: 'Fitxategiaren karga errore ezezaguna', noSemantics: 'Errorea, ezin izan da kargatu ariketa motaren formularioa.', editImage: 'Editatu irudia', saveLabel: 'Gorde', cancelLabel: 'Utzi', resetToOriginalLabel: 'Berrezarri jatorrizkoa', loadingImageEditor: 'Irudi editorea kargatzen, itxaron...', selectFiletoUpload: 'Hautatu kargatu nahi duzun fitxategia', or: 'edo', enterAudioUrl: 'Sartu audio iturriaren URLa', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Itsatsi esteka edo bestelako audio iturriaren URLa', enterVideoTitle: 'Itsatsi YouTubeko esteka edo bestelako bideo iturriaren URLa', uploadAudioTitle: 'Kargatu audio fitxategia', uploadVideoTitle: 'Kargatu bideo fitxategia', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Txertatu', cancel: 'Utzi', height: 'altuera', width: 'zabalera', textField: 'testu eremua', numberField: 'eremu numerikoa', orderItemUp: 'Ordenean gora eraman', orderItemDown: 'Ordenean behera eraman', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Kendu elementua', hubPanelLabel: 'Hautatu ariketa mota', importantInstructions: 'Jarraibide garrantzitsuak', showImportantInstructions: 'Erakutsi jarraibideak', hideImportantInstructions: 'Ezkutatu jarraibide garrantzitsuak', hide: 'Ezkutatu', example: 'Adibidea', createContentTabLabel: 'Sortu ariketa', uploadTabLabel: 'Kargatu', uploadPlaceholder: 'Ez dago hautaturiko fitxategirik', uploadInstructionsTitle: 'Kargatu H5P fitxategi bat.', uploadInstructionsContent: 'Has zaitezke H5P.org web-orriko adibideekin.', uploadFileButtonLabel: 'Kargatu fitxategi bat', uploadFileButtonChangeLabel: 'Aldatu fitxategia', uploadingThrobber: 'Oraintxe ari da kargatzen...', uploadSuccess: ':titulua ongi kargatu da!', unableToInterpretError: 'Ezin da erantzuna interpretatu.', unableToInterpretSolution: 'Aztertu zure akatsen erregistroa.', h5pFileWrongExtensionTitle: 'Hautatu duzun fitxategia ezin da kargatu', h5pFileWrongExtensionContent: 'Soilik .h5p luzapena duten fitxategiak onartzen dira.', h5pFileValidationFailedTitle: 'Ezin da ontzat eman H5P fitxategia.', h5pFileValidationFailedContent: 'Egiaztatu igo duzun H5P fitxategia benetan H5P ariketa duela. H5p fitxategiak soilik liburutegiak badituzte kargatu daitezke H5P liburutegien orriaren bidezf.', h5pFileUploadServerErrorTitle: 'H5P fitxategia ezin izan da kargatu', h5pFileUploadServerErrorContent: 'Ustegabeko errorea gertatu da. Aztertu zure zerbitzariaren akatsen erregistroa zehaztasun gehiago izateko.', contentTypeSectionAll: 'ariketa mota guztiak', searchResults: 'Bilatu emaitzak', contentTypeSearchFieldPlaceholder: 'Bilatu ariketa motaren arabera', contentTypeInstallButtonLabel: 'Instalatu', contentTypeInstallingButtonLabel: 'Instalatzen', contentTypeUseButtonLabel: 'Erabili', contentTypeDetailButtonLabel: 'Zehaztasunak', contentTypeUpdateButtonLabel: 'Eguneratu', contentTypeUpdatingButtonLabel: 'Eguneratzen', contentTypeGetButtonLabel: 'Lortu', contentTypeBackButtonLabel: 'Atzera', contentTypeIconAltText: 'Iconoa', contentTypeInstallSuccess: ':contentType ongi instalatu da!', contentTypeUpdateSuccess: ':contentType ongi kargatu da!', contentTypeInstallError: ':contentType ezin izan da instalatu. Jarri harremanetan administratzailearekin.', contentTypeLicensePanelTitle: 'Lizentzia', contentTypeDemoButtonLabel: 'ariketa-adibidea', numResults: ':num emaitza', show: 'Erakutsi', recentlyUsedFirst: 'Lehenengo berriki erabilitakoak', popularFirst: 'Lehenengo arrakastatsuenak', newestFirst: 'Lehenengo berrienak', aToZ: 'A-tik Z-ra', noResultsFound: 'Ez da emaitzarik aurkitu', noResultsFoundDesc: 'Ez dago zure bilaketa irizpidearekin bat datorren ariketarik.', readMore: 'Irakurri gehiago', readLess: 'Irakurri gutxiago', contentTypeOwner: ':owner arabera', contentTypeUnsupportedApiVersionTitle: 'ariketa mota honek bertsio nagusi berriago bat behar du', contentTypeUnsupportedApiVersionContent: 'Jarri harremantan zure sistemaren administratzailearekin eskuratzeko behar dituzun eguneraketak', contentTypeUpdateAvailable: 'Eguneraketa eskuragarria', contentTypeRestricted: 'Ariketa mota mugatua', contentTypeRestrictedDesc: 'Administratzaileak ariketa mota honen erabilera mugatu du.', contentTypeNotInstalled: 'Ariketa mota hau ez dago instalatua', contentTypeNotInstalledDesc: 'Ez daukazu baimenik ariketa motak instalatzeko.', theContentType: 'ariketa mota', currentMenuSelected: 'uneko hautapena', errorCommunicatingHubTitle: 'Ezin da komunikatu konektorearekin.', errorCommunicatingHubContent: 'Errore bat gertatu da. Saia zaitez beranduago.', warningNoContentTypesInstalled: 'Ez daukazu inolako ariketa motarik instalatuta.', warningChangeBrowsingToSeeResults: 'Klikatu Dena ikusteko instala dezakezun ariketa mota guztien zerrenda.', warningUpdateAvailableTitle: ':contentType motaren bertsio berria eskuragarri dago.', warningUpdateAvailableBody: 'Eguneratu azken bertsiora esperientzia hobea izateko.', licenseDescription: 'Lizentzia honen hainbat berritasun behean zerrendatuta daude. Klikatu goiko info ikonoan irakurtzeko jatorrizko lizentziaren testua.', licenseModalTitle: 'Lizentziaren xehetasunak', licenseModalSubtitle: 'Hautatu lizentzia bat ikusteko erabilera egokiaren gaineko informazioa', licenseUnspecified: 'Zehazkabea', licenseCanUseCommercially: 'Komertzialki erabili daiteke', licenseCanModify: 'Aldatu daiteke', licenseCanDistribute: 'Banatu daiteke', licenseCanSublicense: 'Azpilizentziatu daiteke', licenseCanHoldLiable: 'Erantzule izan daiteke', licenseCannotHoldLiable: 'Ezin daiteke erantzule izan', licenseMustIncludeCopyright: 'Copyrighta barnean behar du', licenseMustIncludeLicense: 'Lizentzia barnean behar du', licenseFetchDetailsFailed: 'Errorea lizentziaren xehetasunak eskuratzean', imageLightboxTitle: 'Irudiak', imageLightBoxProgress: ':total -etik :num', nextImage: 'Hurrengo irudia', previousImage: 'Aurreko irudia', screenshots: 'Pantaila kapturak', reloadButtonLabel: 'Birkargatu', videoQuality: 'Kalitatezko bideoaren etiketa', videoQualityDescription: 'Etiketa honek laguntzen dio erabiltzaileari bideoaren uneko kalitatea identifikatzen. Esate baterako 1080p, 720p, HD edo Mugikorra', videoQualityDefaultLabel: 'Kalitatea :index', noContentTypesAvailable: 'Ez dago ariketa mota erabilgarririk', noContentTypesAvailableDesc: 'Zure guneak zailtasunak ditu H5P.org-ekin konektatzeko ariketa mota erabilgarriak zerrendatzeko.', contentTypeCacheOutdated: 'Ariketa moten zerrenda zaharkitua dago', contentTypeCacheOutdatedDesc: 'Zure guneak zailtasunak ditu H5P.org-ekin konektatzeko ariketa mota erabilgarriak zerrendatzeko. Ezingo duzu ariketa mota berriak instalatu edo eguneratu.', tryAgain: 'Saiatu berriro', getHelp: 'Lortu laguntza', untitled: ':libraryTitle izengabea', title: 'Titulua', metadata: 'Metadatuak', addTitle: 'Gehitu titulua', usedForSearchingReportsAndCopyrightInformation: 'Bilaketetarako, txostenetarako eta copyright informaziorako erabilgarria', metadataSharingAndLicensingInfo: 'Metadatuak (partekatze eta lizentziaren gaineko informazioa)', fillInTheFieldsBelow: 'Bete azpiko eremuetan', saveMetadata: 'Gorde metadatuak', addAuthor: 'Gorde egilea', confirmRemoveAuthor: 'Ziur zaude egile hori kendu nahi duzula?', addNewChange: 'Gehitu aldaketa berri bat', confirmDeleteChangeLog: 'Ziur zaude aldaketaren erregistro sarrera hau kendu nahi duzula?', changelogDescription: 'Lizentzi batzuk jatorrizko lanari egindako aldaketak edo lan eratorriak adierazi eta erakustea exijitzen dute. Zure aldaketak hemen adierazi ditzakezu lizentziaren betekin gisa edo besterik gabe besteei edo zure buruari edukiari egindako aldaketen berri emateko.', logThisChange: 'Erregistratu aldaketa', newChangeHasBeenLogged: 'Aldaketa berri bat erregistratu daN', loggedChanges: 'Erregistratutako aldaketak', noChangesHaveBeenLogged: 'Ez da aldaketarik erregistratu', errorHeader: 'Errore bat gertatu da', errorCalculatingMaxScore: 'Ezin da kalkulatu ariketa honen puntuazio maximoa. Suposatzen da puntuazio maximoa 0 dela. Jar zaitez harrematenetan administratzailearekin itsaten saiatzen ari dena ez bada onartzen testuinguru honetan.', maxScoreSemanticsMissing: 'Edukian ezin izan da aurkitu espero zen semantika.', copyButton: 'Kopiatu', copiedButton: 'Kopiatu da', pasteButton: 'Itsatsi', pasteAndReplaceButton: 'Itsatsi eta Ordezkatu', pasteContent: 'Ordezkatu Edukia', confirmPasteContent: 'Hau eginda oraingo edukia arbelean daukazunarekin ordezkatuko da. Oraingo edukia galduko da. Ziur jarraitu nahi duzula?', confirmPasteButtonText: 'Ordezkatu edukia', copyToClipboard: 'Kopiatu H5P edukia to the clipboard', copiedToClipboard: 'Edukia arbelera kopiatzen da', pasteFromClipboard: 'Itsatsi H5P edukia arbeletik', pasteAndReplaceFromClipboard: 'Ordezkatu oraingo edukia arbelean dagoen H5P edukiarekin', pasteNoContent: 'Ez dago H5P edukirik arbelean', pasteError: 'Ezin izan da arbeltik itsatsi', pasteContentNotSupported: 'Arbeleko H5P edukia ez da testuinguru honetan onartzen', pasteContentRestricted: 'Arbeleko edukia mugatuta dago gune honetan', pasteTooOld: 'Arbeleko H5P edukia testuinguru honetan onartzen den bertsioa (:local) baino bertsio baxuago batekoa da (:clip), posiblea bada saiatu zaitez itsatsi nahi duzun edukia eguneratzen, berriz kopiatu ezazu eta ondoren hemen itsaten saiatu zaitez.', pasteTooNew: 'Arbeleko H5P edukia testuinguru honetan onartzen den bertsioa (:local) baino bertsio altuago batekoa da (:clip), posiblea bada saiatu zaitez itsatsi nahi duzun eduki-motaren liburutegia eguneratzen, eta ondoren berriz itsaten saiatu zaitez.', ok: 'ados', avTablistLabel: 'Txertatu hau erabiltzen:', tabTitleBasicFileUpload: 'Igo fitxategia', tabTitleInputLinkURL: 'Esteka/URLa', errorTooHighVersion: 'Parametroek %used daukate baina soilik %supported edo lehenagokoak onartzen dira.', errorNotSupported: 'Parametroek %used daukate baina ez dira onartzen.', errorParamsBroken: 'Parametroak apurtuta daude.', libraryMissing: 'Beharrezkoa den %lib. biblioteka falta da.', scriptMissing: 'Ezin izan dira kargatu %lib.-rentzako eguneratze-scriptak.', language: 'Hizkuntza', noLanguagesSupported: 'Ez dago onartutako hizkuntzarik', changeLanguage: 'Aldatu hizkuntza honetara :language?', thisWillPotentially: 'Honek testu eta itzulpen guztiak berrabiarazi ditzake. Ekintza hau ezin da desegin. Edukia bera ez da aldatuko. Jarraitu nahi duzu??', notAllTextsChanged: 'Ez dira testu guztiak aldatu, :language hizkuntzaren sostengua ez da osoa.', contributeTranslations: ':language hizkuntzako itzulpena osatu nahi baduzu contributing translations to H5P estekan nola egin ikasi dezakezu', unknownLibrary: "Tamalez, aukeratutako '%lib' eduki-mota ez dago sistema honetan instalatuta.", proceedButtonLabel: 'Jarraitu eta gorde', enterFullscreenButtonLabel: 'Erabili pantaila osoko modura', exitFullscreenButtonLabel: 'Irten pantaila osoko modutik', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\k ??(h5plib/v127/joubel/editor/language/tr.jsnu[H5PEditor.language.core = { missingTranslation: '[Eksik çeviri :key]', loading: ':type yükleniyor, bekleyin ...', selectLibrary: 'İçeriğiniz için kullanmak istediğiniz kitaplığı seçin.', unknownFieldPath: '":path" bulunamadı.', notImageField: '":path" resim değil.', notImageOrDimensionsField: '":path" resim ya da boyut alanı değil.', requiredProperty: ':property gerekli ve bir değeri olmalı.', onlyNumbers: ':property değeri yalnızca sayı içerebilir.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: ':property değeri :max değerini aşıyor.', listExceedsMax: 'Liste :max items maksimum değerini aşıyor.', belowMin: ':property değeri :min değerinin altında.', listBelowMin: 'İçeriğin düzgün işlemesi için liste, en az :min öğeye ihtiyaç duymaktadır.', outOfStep: ':property değeri yalnızca :step aşamalarıyla değiştirilebilir.', add: 'Ekle', addFile: 'Dosya ekle', removeFile: 'Dosya kaldır', confirmRemoval: ':type kaldırılacak, emin misiniz?', removeImage: 'Resmi kaldır', confirmImageRemoval: 'Resim kaldırılacak. Devam etmek istediğinize emin misiniz?', changeFile: 'Dosyayı değiştir', changeLibrary: 'İçerik türü değiştirilsin mi?', semanticsError: 'Semantik hata: :error', missingProperty: ':index alanı :property değerinde eksik.', expandCollapse: 'Genişlet/Daralt', addEntity: ':entity ekle', tooLong: 'Alan değeri çok uzun; en fazla :max harf ya da daha azı olmalı.', invalidFormat: 'Alan değerinde izin verilmeyen geçersiz bir format ya da harf var.', confirmChangeLibrary: 'Bunu yaptığınızda mevcut içerik tipiyle yapılmış tüm çalışmanızı yitireceksiniz. İçerik tipini değiştirmek istediğinize emin misiniz?', commonFields: 'Ayarlar ve metinler', commonFieldsDescription: 'Burada, bu içerikte kullanılan ayarları düzenleyebilir ya da metinleri çevirebilirsiniz.', uploading: 'Yükleniyor, bekleyin ...', noFollow: '":path" alanı izlenemedi.', editCopyright: 'Telif hakkını düzenle', close: 'Kapat', tutorial: 'Kullanma yönergesi', editMode: 'Düzenleme modu', listLabel: 'Liste', uploadError: 'Dosya Yükleme Hatası', fileToLarge: 'Yüklemeye çalıştığınız dosya çok büyük olabilir.', unknownFileUploadError: 'Bilinmeyen dosya yükleme hatası', noSemantics: 'Hata; içerik türü formu yüklenemedi.', editImage: 'Resmi düzenle', saveLabel: 'Kaydet', cancelLabel: 'İptal', resetToOriginalLabel: 'Özgün biçimine sıfırla', loadingImageEditor: 'Resim düzenleyici yükleniyor, bekleyin ...', selectFiletoUpload: 'Yüklenecek dosyayı seçin', or: 'veya', enterAudioUrl: 'Ses kaynağının URLsini girin', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Linki ya da diğer ses kaynağının URLsini yapıştırın', enterVideoTitle: 'Youtube linkini ya da diğer video kaynağının URLsini yapıştırın', uploadAudioTitle: 'Ses dosyası yükle', uploadVideoTitle: 'Video dosyası yükle', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Ekle', cancel: 'Vazgeç', height: 'yükseklik', width: 'genişlik', textField: 'metin alanı', numberField: 'sayı alanı', orderItemUp: 'Öğeleri yukarıya doğru sırala', orderItemDown: 'Öğeleri aşağıya doğru sırala', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Öğeyi kaldır', hubPanelLabel: 'İçerik türünü seç', importantInstructions: 'Önemli açıklamalar', showImportantInstructions: 'Açıklamaları göster', hideImportantInstructions: 'Önemli açıklamaları gizle', hide: 'Gizle', example: 'Örnek', createContentTabLabel: 'İçerik oluştur', uploadTabLabel: 'Yükle', uploadPlaceholder: 'Herhangi bir dosya seçilmedi', uploadInstructionsTitle: 'Bir H5P dosyası yükle.', uploadInstructionsContent: 'Şu adresteki örneklerle başlayabilirsiniz H5P.org.', uploadFileButtonLabel: 'Bir dosya yükle', uploadFileButtonChangeLabel: 'Dosyayı değiştir', uploadingThrobber: 'Şu anda yükleniyor...', uploadSuccess: ':title başarıyla yüklendi!', unableToInterpretError: 'Hatanın nedeni anlaşılamadı.', unableToInterpretSolution: 'Lütfen hata log kayıtlarını inceleyin.', h5pFileWrongExtensionTitle: 'Seçilen dosya yüklenemedi', h5pFileWrongExtensionContent: 'Sadece .h5p uzantılı dosyalar kabul edilmektedir.', h5pFileValidationFailedTitle: 'H5P dosyası doğrulanamamıştır.', h5pFileValidationFailedContent: "Yüklenen H5P'nin geçerli H5P içeriklerini içerdiğinden emin olun. H5P dosyaları sadece H5P Kütüphaneleri (H5P Libraries) sayfası aracılığıyla yüklenen kütüphaneleri içerebilir.", h5pFileUploadServerErrorTitle: 'H5P dosyası yüklenemedi', h5pFileUploadServerErrorContent: 'Beklenmeyen bir hata oluştu. Daha detaylı bilgi için sunucunuzun hata log kayıtlarını inceleyin.', contentTypeSectionAll: 'Tüm İçerik Türleri', searchResults: 'Arama Sonuçları', contentTypeSearchFieldPlaceholder: 'İçerik Türü Ara', contentTypeInstallButtonLabel: 'Yükle', contentTypeInstallingButtonLabel: 'Yükleniyor', contentTypeUseButtonLabel: 'Kullan', contentTypeDetailButtonLabel: 'Detaylar', contentTypeUpdateButtonLabel: 'Güncelle', contentTypeUpdatingButtonLabel: 'Güncelleniyor', contentTypeGetButtonLabel: 'Al', contentTypeBackButtonLabel: 'Geri', contentTypeIconAltText: 'İkon', contentTypeInstallSuccess: ':contentType başarıyla yüklendi!', contentTypeUpdateSuccess: ':contentType başarıyla güncellendi!', contentTypeInstallError: ':contentType yüklenemedi. Yöneticinizle iletişime geçin.', contentTypeLicensePanelTitle: 'Lisans', contentTypeDemoButtonLabel: 'Demo İçerik', numResults: ':num sonuç', show: 'Göster', recentlyUsedFirst: 'Son Kullanılanlar', popularFirst: 'Popülerler', newestFirst: 'Yeniler', aToZ: "A'dan Z'ye", noResultsFound: 'Hiçbir sonuç bulunamadı', noResultsFoundDesc: 'Arama kriterlerinizle eşleşen içerik türü bulunamadı.', readMore: 'Daha fazla oku', readLess: 'Daha az oku', contentTypeOwner: ':owner tarafından oluşturuldu', contentTypeUnsupportedApiVersionTitle: 'Bu içerik türü yeni bir temel versiyon gerek duyuyor', contentTypeUnsupportedApiVersionContent: 'Gerekli güncellemleri yapması için sistem yöneticisiyle bağlantı kurun', contentTypeUpdateAvailable: 'Güncelleme mevcut', contentTypeRestricted: 'Kısıtlı içerik türü', contentTypeRestrictedDesc: 'Bu içerik türünün kullanımı yönetici tarafından kısıtlanmıştır.', contentTypeNotInstalled: 'İçerik türü yüklü değil', contentTypeNotInstalledDesc: 'İçerik türlerini yüklemek için yetkiye sahip değilsiniz.', theContentType: 'içerik türü', currentMenuSelected: 'mevcut seçim', errorCommunicatingHubTitle: 'Bağlantı noktası ile iletişim kurulamadı.', errorCommunicatingHubContent: 'Bir hata oluştu. Lütfen yeniden deneyin.', warningNoContentTypesInstalled: 'Yüklenmiş bir içerik türünüz yok.', warningChangeBrowsingToSeeResults: 'Yükleyebileceğiniz tüm içerik türlerinin listesi için Hepsine tıklayın.', warningUpdateAvailableTitle: ':contentType yeni bir versiyonu mevcut.', warningUpdateAvailableBody: 'Gelişmiş deneyim için son versiyona güncelleyin.', licenseDescription: 'Bu lisansın bazı özellikleri aşağıda belirtilmiştir. Orijinal lisans metnini okumak için yukarıdaki bilgi ikonuna tıklayın.', licenseModalTitle: 'Lisans Detayları', licenseModalSubtitle: 'Kurallara uygun kullanım hakkında bilgiyi görüntülemek için bir lisans seçin', licenseUnspecified: 'Tanımlanmamış', licenseCanUseCommercially: 'Ticari olarak kullanılabilir', licenseCanModify: 'Düzenlenebilir', licenseCanDistribute: 'Dağıtılabilir', licenseCanSublicense: 'Alt lisans olabilir', licenseCanHoldLiable: 'Sorumlu tutabilir', licenseCannotHoldLiable: 'Sorumlu olamaz', licenseMustIncludeCopyright: 'Telif hakkı içermelidir', licenseMustIncludeLicense: 'Lisans içermelidir', licenseFetchDetailsFailed: 'Lisans ayrıntıları alınamadı', imageLightboxTitle: 'Resimler', imageLightBoxProgress: ":total'dan :num of", nextImage: 'Sonraki resim', previousImage: 'Önceki resim', screenshots: 'Ekran görüntüleri', reloadButtonLabel: 'Tekrar yükle', videoQuality: 'Video kalite etiketi', videoQualityDescription: 'Bu etiket kullanıcının mevcut videonun kalitesini tanımlamasına yardımcı olur. Örn: 1080p, 720p, HD veya Mobil', videoQualityDefaultLabel: 'Kalite :index', noContentTypesAvailable: 'Hiçbir içerik mevcut değil', noContentTypesAvailableDesc: 'Web siteniz H5P.org sitesine bağlanmada ve mevcut içerik türlerini listelemede zorluk yaşıyor.', contentTypeCacheOutdated: 'İçerik türü listesi güncel değil', contentTypeCacheOutdatedDesc: 'Web siteniz mevcut içerik türü güncellemelerini kontrol etmek için H5P.org sitesine bağlanmada zorluk yaşıyor. Yeni içerik türlerini yükleme ve güncellemek için yetkiniz olmayabilir.', tryAgain: 'Yeniden dene', getHelp: 'Yardım al', untitled: 'Başlıksız :libraryTitle', title: 'Başlık', metadata: 'Üstveri (Metadata)', addTitle: 'Başlık ekle', usedForSearchingReportsAndCopyrightInformation: 'Arama, raporlar ve telif hakkı bilgisi için kullanılacaktır', metadataSharingAndLicensingInfo: 'Üstveri (Metadata) (paylaşma ve lisanslama bilgisi)', fillInTheFieldsBelow: 'Aşağıdaki alanları doldurunuz', saveMetadata: 'Üstveriyi (metadata) kaydet', addAuthor: 'Yazarı kaydet', confirmRemoveAuthor: 'Bu yazarı kaldırmak istediğinizden emin misiniz?', addNewChange: 'Yeni değişiklik ekle', confirmDeleteChangeLog: 'Bu değişim log kaydını silmek istediğinizden emin misiniz?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Bu değişimi logla', newChangeHasBeenLogged: 'Yeni değişiklik loglandı', loggedChanges: 'Loglanmış değişiklikler', noChangesHaveBeenLogged: 'Hiçbir değişiklik loglanmadı', errorHeader: 'Bir hata oluştu', errorCalculatingMaxScore: 'Bu içerik için maksimum puan hesaplanamadı. Maksimum puan 0 olarak kabul edilir. Doğru değilse yöneticinize başvurun.', maxScoreSemanticsMissing: 'İçerikte beklenen anlam bulunamadı.', copyButton: 'Kopyala', copiedButton: 'Kopyalandı', pasteButton: 'Yapıştır', pasteAndReplaceButton: 'Yapıştır & Değiştir', pasteContent: 'İçeriği Değiştir', confirmPasteContent: 'Bunu yaparak, mevcut içeriği panodaki içerikle değiştirirsiniz. Mevcut içerik kaybedilecek. Devam etmek istediğinize emin misiniz?', confirmPasteButtonText: 'İçeriği değiştir', copyToClipboard: 'H5P içeriğini panoya kopyalayın', copiedToClipboard: 'İçerik panoya kopyalandı', pasteFromClipboard: 'Panodan H5P içeriğini yapıştırın', pasteAndReplaceFromClipboard: 'Mevcut içeriği panodaki H5P İçeriği ile değiştir', pasteNoContent: 'Panoda H5P içeriği yok', pasteError: 'Panodan H5P içeriği yapıştırılamadı', pasteContentNotSupported: 'H5P panosundaki içerik bu bağlamda desteklenmiyor', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'H5P panosundaki içerik, bu bağlamda (:local) desteklenenden daha düşük bir sürümdür (:clip) mümkünse yapıştırmak istediğiniz içeriğin yükseltilmesini sağlayın , tekrar kopyalayın ve buraya yapıştırmayı deneyin.', pasteTooNew: 'H5P panosundaki içerik, bu bağlamda (:local) desteklenenden daha yüksek bir versiyona (:clip) sahiptir, mümkünse önce bu içeriğin yükseltilmesini sağlayın ve ardından içeriği buraya yapıştırmayı deneyin.', ok: 'TAMAM', avTablistLabel: 'Kullanarak ekle', tabTitleBasicFileUpload: 'Dosya Yükleme', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parametreler desteklenmeyen %used içerir.', errorParamsBroken: 'Parametreler bozuk.', libraryMissing: 'Gerekli kütüphane eksik %lib.', scriptMissing: '%lib için yükseltme komut dosyası yüklenemedi.', language: 'Dil', noLanguagesSupported: 'Desteklenen Dil Yok', changeLanguage: 'Dili değiştir :language?', thisWillPotentially: 'Bu, tüm metni ve çevirileri potansiyel olarak sıfırlayacaktır. Bu değişikliği sıfırlayamazsınız. İçeriğin kendisi değişmeyecek. Devam etmek istiyor musunuz?', notAllTextsChanged: 'Metinlerin tümü değişmedi, yalnızca kısmi kapsama alanı var :language.', contributeTranslations: 'Çeviriyi tamamlamak istiyorsanız :language hakkında bilgi edinebilirsiniz H5P’ye çevirilerde katkıda bulunmak', unknownLibrary: "Ne yazık ki, seçilen içerik türü '%lib ' bu sisteme yüklenmedi.", proceedButtonLabel: 'Kaydetmeye devam et', enterFullscreenButtonLabel: 'Tam ekran yap', exitFullscreenButtonLabel: 'Tam ekrandan çık', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\D[DD(h5plib/v127/joubel/editor/language/ko.jsnu[H5PEditor.language.core = { missingTranslation: '[변환 누락 :key]', loading: '로드하는 중, 잠시 기다리십시오...', selectLibrary: '콘텐츠를 위해 사용할 라이브러리를 선택하십시오.', unknownFieldPath: '":path" 를 찾을 수 없음.', notImageField: '":path"는 이미지가 아님', notImageOrDimensionsField: '":path"는 이미지 또는 치수 영역이 아님', requiredProperty: ':property 는 필수이며 값이 있어야 함', onlyNumbers: ':property 값은 숫자만 포함할 수 있음', illegalDecimalNumber: ':property는 최대 :decimals decimals를 가진 숫자만 포함할 수 있다.', exceedsMax: ':property 값이 최대값 :max 를 초과함.', listExceedsMax: '목록이 최대값 :max 항목을 초과함.', belowMin: ' :property 값이 최소값인 :min보다 낮음.', listBelowMin: '목록은 콘텐츠가 제대로 작동하려면 최소 :min 항목이 필요하다.', outOfStep: ':property 값은 :step의 단계에서만 변경할 수 있다.', add: '추가', addFile: '파일 추가', removeFile: '파일 제거', confirmRemoval: '이 :type을 제거하시겠습니까?', removeImage: '이미지 제거', confirmImageRemoval: '이렇게 하면 이미지가 제거됩니다. 정말 계속하시겠습니까?', changeFile: '파일 변경', changeLibrary: '콘텐츠 유형을 변경하시겠습니까?', semanticsError: 'Semantics error: :error', missingProperty: '영역 :index 에 :property 속성이 없습니다.', expandCollapse: '확대/축소', addEntity: ' :entity 더하기', tooLong: '영역 값이 너무 김. 최대 문자 또는 그 이하를 포함해야 함', invalidFormat: '영역 값에 금지된 형식 혹은 금지된 문자가 포함됨.', confirmChangeLibrary: '이 작업을 수행하면 현재 콘텐츠 유형으로 수행된 모든 작업이 손실됨. 콘텐츠 유형을 변경하시겠습니까?', commonFields: '텍스트 재정의 및 변환', commonFieldsDescription: '여기에서 이 콘텐츠의 설정을 편집하거나 텍스트를 변환할 수 있다.', uploading: '업로드 중, 잠시 기다리십시오...', noFollow: '필드 ":path"를 따를 수 없다.', editCopyright: '저작권 편집', close: '닫기', tutorial: '튜토리얼', editMode: '편집모드', listLabel: '목록', uploadError: '파일 업로드 오류', fileToLarge: '업로드하려는 파일이 너무 클 수 있음.', unknownFileUploadError: '알 수 없는 파일 업로드 오류', noSemantics: '오류, 콘텐츠 유형 양식을 로드할 수 없음.', editImage: '이미지 편집', saveLabel: '저장', cancelLabel: '취소', resetToOriginalLabel: '원본으로 돌아가기', loadingImageEditor: '이미지 편집기 로드 중, 잠시 기다리십시오...', selectFiletoUpload: '업로드할 파일 선택', or: '또는', enterAudioUrl: '오디오 소스 URL 입력', enterVideoUrl: '비디오 소스 URL 또는 YouTube 링크 입력', enterAudioTitle: '링크 혹은 다른 오디오 소스 URL 붙여넣기', enterVideoTitle: '유튜브 게시 링크 또는 기타 비디오 소스 URL 붙여넣기', uploadAudioTitle: '오디오 파일 업로드', uploadVideoTitle: '비디오 파일 업로드', addVideoDescription: 'H5P는 비메오 프로처럼 mp4, webm 또는 ogv로 포맷된 모든 외부 비디오 소스를 지원하며, 유튜브 링크를 지원함.', insert: '삽입', cancel: '취소', height: '높이', width: '너비', textField: '텍스트 영역', numberField: '숫자 영역', orderItemUp: '아이템 위로', orderItemDown: '아이템 아래로', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: '아이템 제거', hubPanelLabel: '콘텐츠 유형 선택', importantInstructions: '중요 지침', showImportantInstructions: '지침 보이기', hideImportantInstructions: '중요 지침 감추기', hide: '숨기기', example: '예시', createContentTabLabel: '콘텐츠 만들기', uploadTabLabel: '업로드', uploadPlaceholder: '파일 선택 없음', uploadInstructionsTitle: 'H5P 파일 업로드', uploadInstructionsContent: 'All(모두)을 클릭하십시오.', warningUpdateAvailableTitle: '새로운 버전의 :content 유형을 사용할 수 있음', warningUpdateAvailableBody: '더 나은 경험을 위해 최신 버전으로 업데이트', licenseDescription: '이 라이선스의 일부 기능은 다음과 같다. 원래 라이센스 텍스트를 읽으려면 위의 정보 아이콘을 클릭하십시오.', licenseModalTitle: '라이선스 세부 정보', licenseModalSubtitle: '적절한 사용에 대한 정보를 보려면 라이선스를 선택하십시오.', licenseUnspecified: '지정되지 않음', licenseCanUseCommercially: '상업적으로 사용할 수 있음', licenseCanModify: '수정 가능', licenseCanDistribute: '배포할 수 있음', licenseCanSublicense: '하위 라이선스(sublicense) 가능 ', licenseCanHoldLiable: '책임(liable) 포함 가능', licenseCannotHoldLiable: '책임(liable) 포함 불가능', licenseMustIncludeCopyright: '저작권을 포함해야 함', licenseMustIncludeLicense: '라이선스를 포함해야 함', licenseFetchDetailsFailed: '라이선스 세부 정보 가져오기 실패', imageLightboxTitle: '이미지', imageLightBoxProgress: '총 :total 중 :num ', nextImage: '다음 이미지', previousImage: '이전 이미지', screenshots: '스크린샷', reloadButtonLabel: '재로드', videoQuality: '비디오 품질 라벨', videoQualityDescription: '이 라벨은 사용자가 동영상의 현재 품질을 식별하는 데 도움이 됨. 예를 들어 1080p, 720p, HD 또는 Mobile', videoQualityDefaultLabel: '품질 :index', noContentTypesAvailable: '사용할 수 있는 콘텐츠 유형 없음', noContentTypesAvailableDesc: '당신의 사이트는 H5P.org에 접속하여 사용 가능한 콘텐츠 유형을 나열하는 데 어려움을 겪고 있음.', contentTypeCacheOutdated: '콘텐츠 유형 목록이 오래됨', contentTypeCacheOutdatedDesc: '당신의 사이트는 컨텐츠 유형 업데이트를 확인하기 위해 H5P.org에 연결하는 데 어려움을 겪고 있음. 새로운 콘텐츠 유형을 업데이트하거나 설치하지 못할 수 있다.', tryAgain: '재시도', getHelp: '도움', untitled: '제목없음 :libraryTitle', title: '제목', metadata: '메타데이터', addTitle: '제목추가', usedForSearchingReportsAndCopyrightInformation: '검색, 보고서 및 저작권 정보에 사용됨', metadataSharingAndLicensingInfo: '메타데이터 (공유 및 라이센싱 정보)', fillInTheFieldsBelow: '아래 영역에 입력', saveMetadata: '메타데이터 저장', addAuthor: '작성자 저장', confirmRemoveAuthor: '이 작성자를 제거하시겠습니까?', addNewChange: '새 변화 추가', confirmDeleteChangeLog: '이 변경 로그 항목을 삭제하시겠습니까?', changelogDescription: '일부 라이선스는 원본 작업에 대한 변경 사항을 요구하거나 파생 모델을 기록하여 표시해야 한다. 라이센싱상의 이유로 변경사항을 여기에 기록하거나 자신과 다른 사람이 이 콘텐츠에 대한 변경사항을 추적할 수 있도록 허용하십시오.', logThisChange: '변경 기록', newChangeHasBeenLogged: '새 변경 사항이 기록됨', loggedChanges: '변경 기록', noChangesHaveBeenLogged: '변경 사항이 기록되지 않음', errorHeader: '에러가 발생함', errorCalculatingMaxScore: '이 컨텐츠의 최대 점수를 계산할 수 없음. 최대 점수는 0으로 가정한다. 올바르지 않으면 관리자에게 문의하십시오.', maxScoreSemanticsMissing: '콘텐츠에서 기대되는 의미 있는 문장(semantics)를 찾을 수 없음.', copyButton: '복사', copiedButton: '복사완료', pasteButton: '붙여넣기', pasteAndReplaceButton: '붙여넣기 및 대체하기', pasteContent: '콘텐츠 대체하기', confirmPasteContent: '이 작업을 수행하면 현재 내용을 클립보드의 내용으로 바꿀 수 있음. 현재 내용은 손실됨. 계속하시겠습니까?', confirmPasteButtonText: '콘텐츠 대체하기', copyToClipboard: 'H5P콘텐츠를 클립보드에 복사하기', copiedToClipboard: '콘텐츠가 클립보드로 복사되었습니다.', pasteFromClipboard: '클립보드에서 H5P 콘텐츠 붙여넣기', pasteAndReplaceFromClipboard: '클립보드의 H5P 콘텐츠로 기존 콘텐츠 바꾸기', pasteNoContent: '클립보드에 H5P 콘텐츠 없음', pasteError: '클립보드에서 붙여넣을 수 없음', pasteContentNotSupported: 'H5P 클립보드의 콘텐츠는 이 컨텍스트에서 지원되지 않음', pasteContentRestricted: '클립보드의 콘텐츠가 이 사이트에서 제한됨', pasteTooOld: 'H5P 클립보드의 콘텐츠는 이 컨텍스트(:local)에서 지원되는 것보다 낮은 버전(:clip)이며, 가능하면 붙여넣을 콘텐츠를 업그레이드한 후 다시 복사한 후 여기에 붙여 넣으십시오.', pasteTooNew: 'H5P 클립보드의 콘텐츠는 이 컨텍스트에서 지원되는 것보다 더 높은 버전(:clip)이며, 가능하면 이 콘텐츠를 먼저 업그레이드한 다음 여기에 다시 붙여 넣으십시오.', ok: 'OK', avTablistLabel: '삽입하기', tabTitleBasicFileUpload: '파일업로드', tabTitleInputLinkURL: '링크/URL', errorTooHighVersion: '%Supported 혹은 이전 버전이 지원됨에도 매개 변수가 %used를 포함함.', errorNotSupported: '매개변수는 지원되지 않는 %used를 포함한다.', errorParamsBroken: '매개변수 오류', libraryMissing: '필요한 라이브러리 %lib 누락', scriptMissing: '%lib에 대한 업그레이드 스크립트를 로드할 수 없음.', language: '언어', noLanguagesSupported: '지원되는 언어 없음', changeLanguage: '언어를 :language 로 변경하시겠습니까?', thisWillPotentially: '이것은 잠재적으로 모든 텍스트와 변환을 재설정할 것이다. 이는 되돌릴 수 없고 콘텐츠 자체가 바뀌지 않을 것입니다. 계속하시겠습니까?', notAllTextsChanged: '모든 텍스트가 변경된 것은 아니며 :language 에 대한 부분적인 적용 범위만 있을 뿐임.', contributeTranslations: ':language 에 대한 번역을 완료하려면, contributing translations to H5P (H5P 번역에 기여) 에 대해 배울 수 있음.', unknownLibrary: "불행히도 선택한 콘텐츠 유형 '%lib'이(가) 이 시스템에 설치되지 않았음.", proceedButtonLabel: '저장 진행', enterFullscreenButtonLabel: '전체화면', exitFullscreenButtonLabel: '전체화면 종료', noContentHeader: '알맞은 콘텐츠가 없습니까?', noContentSuggestion: '직접 콘텐츠를 만들어 보세요!', tutorials: '튜토리얼', contentSectionAll: '모든 공유 콘텐츠', popularContent: '인기 콘텐츠', allPopular: '모든 인기 콘텐츠', newOnTheHub: '허브의 새 콘텐츠', allNew: '모든 새 콘텐츠', filterBy: '검색 조건', filter: '검색', filters: { level: { dropdownLabel: '레벨', dialogHeader: '교육 레벨 선택', dialogButtonLabel: '교육 레벨에 따라 검색' }, language: { dropdownLabel: '언어', dialogHeader: '언어 선택', dialogButtonLabel: '언어에 따라 검색', searchPlaceholder: '하나 이상의 언어 선택', }, reviewed: { dropdownLabel: '검토됨', dialogHeader: '검토가 된 콘텐츠', dialogButtonLabel: '검색', optionLabel: '검토된 내용만 표시', }, contentTypes: { dropdownLabel: '콘텐츠 유형', dialogHeader: '콘텐츠 유형 선택', dialogButtonLabel: '콘텐츠 유형 검색', searchPlaceholder: '하나 이상의 콘텐츠 유형 선택', }, disciplines: { dropdownLabel: '과목', dialogHeader: '과목 선택', dialogButtonLabel: '과목 검색', searchPlaceholder: '하나 이상의 과목 선택', }, licenses: { dropdownLabel: '라이선스', dialogHeader: '선호하는 사용 권한 선택', dialogButtonLabel: '라이선스에 따라 검색', options: { modified: '수정할 수 있음', commercial: '상업적 사용 허용' }, }, }, clearFilters: '모든 검색 조건 지우기', contentSearchFieldPlaceholder: '콘텐츠 검색', loadingContentTitle: '컨텐츠를 로드하는 중...', loadingContentSubtitle: '잠시만 기다리십시오', by: '저작자', dropdownButton: '드랍다운 열기', paginationNavigation: '페이징 네비게이션', page: '페이지', currentPage: '현재 페이지', nextPage: '다음 페이지로 이동', previousPage: '이전 페이지로 이동', contentPreviewButtonLabel: '미리보기', contentDownloadButtonLabel: '콘텐츠 가져오기', reuseContentTabLabel: '공유 콘텐츠 가져오기', contentPublisherPanelHeader: '게시자 정보', noContentFoundDesc: '검색 기준에 맞는 콘텐츠가 없음.', h5pType: 'H5P 유형', level: '레벨', size: '크기', failedFetchingData: '데이터 가져오기 실패', filterErrorMessage: '오류가 있습니다. 페이지를 다시 로드하십시오.', in: 'in', navigateToParent: '상위 탐색', a11yTitleShowLabel: 'AT 에 대한 라벨 표시', a11yTitleHideLabel: 'AT 에 대한 레이블 숨기기', reuseSuccess: ':title 이 H5P 허브에서 성공적으로 가져오기 되었습니다.', }; PK*\ۓf>>(h5plib/v127/joubel/editor/language/nb.jsnu[H5PEditor.language.core = { missingTranslation: '[Mangler oversettelse :key]', loading: 'Laster, vennligst vent...', selectLibrary: 'Velg biblioteket du ønsker å bruke for innholdet ditt.', unknownFieldPath: 'Kan ikke finne ":path".', notImageField: '":path" er ikke et bilde.', notImageOrDimensionsField: '":path" er verken et bilde- eller dimensjonsfelt.', requiredProperty: '":property" er påkrevd og må ha en verdi.', onlyNumbers: '":property" kan bare innholde tall.', illegalDecimalNumber: ':property kan bare inneholde tall med maksimalt :decimals desimaler.', exceedsMax: '":property" overstiger maksverdien på :max.', listExceedsMax: 'Antallet elementer i listen overstiger maksantallet på :max elementer.', belowMin: '":property" er mindre enn minimumsverdien på :min.', listBelowMin: 'Listen trenger minst :min elementer for at innholdet skal virke.', outOfStep: '":property" kan bare endres i steg på :step.', add: 'Legg til', addFile: 'Legg til fil', removeFile: 'Fjern fil', confirmRemoval: 'Er du sikker på at du ønsker å fjerne denne :type?', removeImage: 'Fjern bilde', confirmImageRemoval: 'Er du sikker på at du ønsker å fjerne dette bildet?', changeFile: 'Bytt fil', changeLibrary: 'Endre innholdstype', semanticsError: 'Semantikkfeil: :error', missingProperty: 'Feltet :index mangler :property attributten sin.', expandCollapse: 'Utvid/Slå sammen', addEntity: 'Legg til :entity', tooLong: 'Feltets verdi er for lang, den må være på :max tegn eller mindre.', invalidFormat: 'Feltets verdi har ugyldig format eller bruker ulovlige tegn.', confirmChangeLibrary: 'Ved å gjøre dette mister du alt arbeid gjort med nåværende innholdstype. Er du sikker på at du ønsker å bytte innholdstype?', commonFields: 'Innstillinger og tekster', commonFieldsDescription: 'Her kan du redigere innstillinger eller oversette tekster som brukes i dette innholdet.', uploading: 'Laster opp fil, vennligst vent...', noFollow: 'Kunne ikke følge feltet ":path".', editCopyright: 'Rediger opphavsrett', close: 'Lukk', tutorial: 'Veiledning', editMode: 'Redigeringsmodus', listLabel: 'Liste', uploadError: 'Filopplasting feilet', fileToLarge: 'Filen du prøver å laste opp kan være for stor.', unknownFileUploadError: 'Ukjent filopplastingsfeil', noSemantics: 'Feil: kunne ikke laste skjemaet for innholdstypen.', editImage: 'Rediger bilde', saveLabel: 'Lagre', cancelLabel: 'Avbryt', resetToOriginalLabel: 'Tilbakestill bilde', loadingImageEditor: 'Laster inn bilderedigering, vennligst vent...', selectFiletoUpload: 'Velg fil som skal lastes opp', or: 'eller', enterAudioUrl: 'Skriv inn nettadresse til lydkilde', enterVideoUrl: 'Skriv inn nettadresse til video', enterAudioTitle: 'Lim inn link eller annen lydkilde URL', enterVideoTitle: 'Lim inn YouTube lenke eller annen videokilde URL', uploadAudioTitle: 'Last opp lydfil', uploadVideoTitle: 'Last opp videofil', addVideoDescription: 'H5P støtter alle eksterne videokilder på formatene mp4, webm eller ogv, slik som Vimeo Pro, og har støtte for YouTube-lenker og Panopto-lenker.', insert: 'Sett inn', cancel: 'Avbryt', height: 'Høyde', width: 'Bredde', textField: 'Tekstfelt', numberField: 'Nummerfelt', orderItemUp: 'Flytt element opp', orderItemDown: 'Flytt element ned', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Fjern element', hubPanelLabel: 'Velg innholdstype', importantInstructions: 'Viktige instruksjoner', showImportantInstructions: 'Vis instruksjoner', hideImportantInstructions: 'Skjul viktige instruksjoner', hide: 'Skjul', example: 'Eksempel', createContentTabLabel: 'Lag innhold', uploadTabLabel: 'Last opp', uploadPlaceholder: 'Ingen fil er valgt', uploadInstructionsTitle: 'Last opp en .h5p fil.', uploadInstructionsContent: 'Du kan starte med eksempler fra H5P.org.', uploadFileButtonLabel: 'Last opp en fil', uploadFileButtonChangeLabel: 'Bytt fil', uploadingThrobber: 'Laster opp...', uploadSuccess: ':title ble lastet opp!', unableToInterpretError: 'Kan ikke tolke respons.', unableToInterpretSolution: 'Vennligst sjekk feilloggen din.', h5pFileWrongExtensionTitle: '.h5p-fil ble ikke funnet.', h5pFileWrongExtensionContent: 'Du må laste opp en fil med fil-endelsen .h5p', h5pFileValidationFailedTitle: 'Kunne ikke validere H5P-filen.', h5pFileValidationFailedContent: 'Pass på at .h5p filen du laster opp inneholder valid H5P innhold. H5P filer som bare inneholder biblioteker skal lastes opp på bibliotekssiden og kan ikke lastes opp som innhold.', h5pFileUploadServerErrorTitle: 'H5P-filen kunne ikke bli lastet opp.', h5pFileUploadServerErrorContent: 'En uventet feil har oppstått. Sjekk din serverlogg for detaljer.', contentTypeSectionAll: 'Alle innholdstyper', searchResults: 'Søkeresultater', contentTypeSearchFieldPlaceholder: 'Søk etter innholdstyper', contentTypeInstallButtonLabel: 'Installer', contentTypeInstallingButtonLabel: 'Installerer', contentTypeUseButtonLabel: 'Bruk', contentTypeDetailButtonLabel: 'Detaljer', contentTypeUpdateButtonLabel: 'Oppdater', contentTypeUpdatingButtonLabel: 'Oppdaterer', contentTypeGetButtonLabel: 'Hent', contentTypeBackButtonLabel: 'Tilbake', contentTypeIconAltText: 'Ikon', contentTypeInstallSuccess: ':contentType ble installert!', contentTypeUpdateSuccess: ':contentType ble oppdatert!', contentTypeInstallError: ':contentType kunne ikke bli installert. Kontakt administrator for siden.', contentTypeLicensePanelTitle: 'Lisens', contentTypeDemoButtonLabel: 'Innholdsdemonstrasjon', numResults: ':num treff', show: 'Vis', recentlyUsedFirst: 'Nylig brukt først', popularFirst: 'Populære først', newestFirst: 'Nyeste først', aToZ: 'A til Å', noResultsFound: 'Ingen resultater', noResultsFoundDesc: 'Det finnes ingen innholdstype som samsvarer med søkekriteriene dine.', readMore: 'Vis mer', readLess: 'Vis mindre', contentTypeOwner: 'Av :owner', contentTypeUnsupportedApiVersionTitle: 'Denne innholdstypen krever en ny versjon av H5P Core', contentTypeUnsupportedApiVersionContent: 'Kontakt din systemadministrator for nødvendige oppdateringer.', contentTypeUpdateAvailable: 'Oppdatering tilgjengelig', contentTypeRestricted: 'Begrenset tilgang til innholdstype', contentTypeRestrictedDesc: 'Bruken av denne innholdstypen er begrenset av en administrator.', contentTypeNotInstalled: 'Inneholdstype ikke installert', contentTypeNotInstalledDesc: 'Du har ikke tilgang til å installere innholdstyper.', theContentType: 'Innholdstypen', currentMenuSelected: 'Gjeldende valg', errorCommunicatingHubTitle: 'Klarte ikke å kommunisere med H5P Hub.', errorCommunicatingHubContent: 'En feil har oppstått. Vennligst prøv igjen.', warningNoContentTypesInstalled: 'Du har ingen installerte innholdstyper.', warningChangeBrowsingToSeeResults: 'Klikk Alle for å få en liste over alle innholdstyper du kan installere.', warningUpdateAvailableTitle: 'En ny versjon av :contentType er tilgjengelig.', warningUpdateAvailableBody: 'Oppdater til siste versjon for en best mulig opplevelse.', licenseDescription: 'Noen av egenskapene til denne lisensen indikeres under. Klikk på informasjonsikonet for å lese lisensteksten.', licenseModalTitle: 'License Details', licenseModalSubtitle: 'Velg en lisens for å se en oversikt over riktig bruk', licenseUnspecified: 'Uspesifisert', licenseCanUseCommercially: 'Kan bruke kommersielt', licenseCanModify: 'Kan endre', licenseCanDistribute: 'Kan distribuere', licenseCanSublicense: 'Kan viderelisensiere', licenseCanHoldLiable: 'Kan holde ansvarlig', licenseCannotHoldLiable: 'Kan ikke holde ansvarlig', licenseMustIncludeCopyright: 'Må inkludere opphavsrettsinformasjon', licenseMustIncludeLicense: 'Må inkludere lisens', licenseFetchDetailsFailed: 'Feil ved henting av lisens-detaljer', imageLightboxTitle: 'Bilder', imageLightBoxProgress: ':num av :total', nextImage: 'Neste bilde', previousImage: 'Forrige bilde', screenshots: 'Skjermbilder', reloadButtonLabel: 'Last på nytt', videoQuality: 'Navn på videokvalitet', videoQualityDescription: 'Dette navnet hjelper brukeren med å identifisere den aktuelle videokvaliteten. F.eks. 1080p, 720p, HD eller for mobil', videoQualityDefaultLabel: 'Kvalitet :index', noContentTypesAvailable: 'Ingen innholdstyper er tilgjengelig', noContentTypesAvailableDesc: 'Nettstedet ditt har problemer med å koble til H5P.org og kan ikke liste tilgjengelige innholdstyper.', contentTypeCacheOutdated: 'Innholdstype-listen er utdatert', contentTypeCacheOutdatedDesc: 'Nettstedet ditt har problemer med å koble til H5P.org for å se etter innholdstype-oppdateringer. Det kan hende at du ikke får oppdatert eller installert nye innholdstyper.', tryAgain: 'Prøv på nytt', getHelp: 'Få hjelp', untitled: 'Uten tittel :libraryTitle', title: 'Tittel', metadata: 'Metadata', addTitle: 'Legg til tittel', usedForSearchingReportsAndCopyrightInformation: 'Brukes til søk, rapporter og copyright-informasjon', metadataSharingAndLicensingInfo: 'Metadata (deling- og lisensinformasjon)', fillInTheFieldsBelow: 'Fyll inn feltene nedenfor', saveMetadata: 'Lagre metadata', addAuthor: 'Lagre forfatter', confirmRemoveAuthor: 'Er du sikker på at du ønsker å fjerne denne forfatteren?', addNewChange: 'Legg til endring', confirmDeleteChangeLog: 'Er du sikker på at du ønsker å slette denne loggoppføringen?', changelogDescription: 'Enkelte lisenser krever at endringer gjort på det originale verket, eller verk avledet av dette, loggføres og vises. Du kan loggføre endringene dine her for lisenshensyn, slik at du og andre skal kunne holde styr på endringene som er gjort på dette innholdet.', logThisChange: 'Loggfør denne endringen', newChangeHasBeenLogged: 'Ny endring er blitt loggført', loggedChanges: 'Loggførte endringer', noChangesHaveBeenLogged: 'Ingen endring er blitt loggført', errorHeader: 'En feil har oppstått', errorCalculatingMaxScore: 'Kunne ikke kalkulerer maks poengsum for denne innholdstypen. Maks poengsum er antatt til å være 0. Kontakt administrator dersom dette ikke er korrekt.', maxScoreSemanticsMissing: 'Kunne ikke finne den forventede semantikken i den valgte innholdstypen.', copyButton: 'Kopier', copiedButton: 'Kopiert', pasteButton: 'Lim inn', pasteAndReplaceButton: 'Lim inn og erstatt', pasteContent: 'Erstatt innhold', confirmPasteContent: 'Dette vil erstatte det eksisterende innholdet med innholdet på din utklippstavle. Det eksisterende innholdet vil gå tapt. Er du sikker på at du ønsker å fortsette? ', confirmPasteButtonText: 'Erstatt innhold', copyToClipboard: 'Kopier H5P-innhold til utklippstavlen', copiedToClipboard: 'Innholdet er kopiert til utklippstavlen', pasteFromClipboard: 'Lim inn H5P-innhold fra utklippstavlen', pasteAndReplaceFromClipboard: 'Erstatt eksisterende innhold med H5P-innhold fra utklippstavlen', pasteNoContent: 'Utklippstavlen har ikke H5P-innhold', pasteError: 'Kan ikke lime inn fra utklippstavlen', pasteContentNotSupported: 'Innholdet på utklippstavlen støttes ikke i denne sammenhengen', pasteContentRestricted: 'Innholdet på utklippstavlen er begrenset på denne siden.', pasteTooOld: 'Innholdet på utklippstavlen har lavere versjon (:clip) enn det som er støttet i denne sammenhengen (:local). Om det er mulig, kan du oppdatere innholdet du ønsker å kopiere, for så å forsøke og kopiere og lime det inn på nytt.', pasteTooNew: 'Innholdet på utklippstavlen har høyere versjon (:clip) enn det som er støttet i denne sammenhengen (:local). Om det er mulig, kan du oppdatere innholdet du ønsker å kopiere til, for så å forsøke og kopiere og lime det inn på nytt.', ok: 'OK', avTablistLabel: 'Sett inn via', tabTitleBasicFileUpload: 'Filopplasting', tabTitleInputLinkURL: 'Lenke/URL', errorTooHighVersion: 'Parameterene innholder %used mens kun %supported eller tidligere er støttet.', errorNotSupported: 'Parameterene inneholder %used som ikke er støttet.', errorParamsBroken: 'Parameterene er ødelagt.', libraryMissing: 'Mangler påkrevd bibliotek %lib.', scriptMissing: 'Kunne ikke laste oppgraderingsskript for %lib.', language: 'Språk', noLanguagesSupported: 'Ingen språk støttet', changeLanguage: 'Bytt språk til :language?', thisWillPotentially: 'Dette kan potensielt tilbakestille all teksten og oversettelsene. Du kan ikke omgjøre dette. Innholdet vil ikke bli endret. Vil du fortsette?', notAllTextsChanged: 'Ikke alle tekstene ble endret, det er kun delvis støtte for :language.', contributeTranslations: 'Hvis du vil fullføre oversettelsen for :language kan du lære mer om bidra med oversettelser til H5P', unknownLibrary: "Dessverre var ikke den valgte '%lib'-innholdstypen installert på dette systemet.", proceedButtonLabel: 'Fortsett for å lagre', enterFullscreenButtonLabel: 'Åpne i fullskjerm', exitFullscreenButtonLabel: 'Avslutt fullskjerm', noContentHeader: 'Ikke noe innhold som passer?', noContentSuggestion: 'Lag innhold selv!', tutorials: 'Veiledninger', contentSectionAll: 'Alt delt innhold', popularContent: 'Populært innhold', allPopular: 'Alt populært innhold', newOnTheHub: 'Nytt på H5P Hub', allNew: 'Alt nytt', filterBy: 'Filtrer etter', filter: 'Filtrer', filters: { level: { dropdownLabel: 'Nivå', dialogHeader: 'Velg utdanningsnivå', dialogButtonLabel: 'Filtrer etter utdanningsnivå', }, language: { dropdownLabel: 'Språk', dialogHeader: 'Velg språk', dialogButtonLabel: 'Filtrer etter språk', searchPlaceholder: 'Velg ett eller flere språk', }, reviewed: { dropdownLabel: 'Gjennomgått', dialogHeader: 'Gjennomgått innhold', dialogButtonLabel: 'Filtrer', optionLabel: 'Vis bare gjennomgått innhold', }, contentTypes: { dropdownLabel: 'Innholdstyper', dialogHeader: 'Velg innholdstype(r)', dialogButtonLabel: 'Filtrer på innholdstyper', searchPlaceholder: 'Velg en eller flere innholdstyper', }, disciplines: { dropdownLabel: 'Disiplin', dialogHeader: 'Velg din disiplin', dialogButtonLabel: 'Filtrer disipliner', searchPlaceholder: 'Velg en eller flere disipliner', }, licenses: { dropdownLabel: 'Lisens', dialogHeader: 'Velg rettigheter for bruk', dialogButtonLabel: 'Filtrer på lisenser', options: { modified: 'Kan endres', commercial: 'Tillater kommersiell bruk' }, }, }, clearFilters: 'Nullstill alle filtre', contentSearchFieldPlaceholder: 'Søk etter innhold', loadingContentTitle: 'Vi laster innhold for deg...', loadingContentSubtitle: 'Vennligst vent', by: 'Av', dropdownButton: 'Åpne nedtrekksmeny', paginationNavigation: 'Sidenavigasjon', page: 'Side', currentPage: 'Gjeldende side', nextPage: 'Gå til neste side', previousPage: 'Gå til forrige side', contentPreviewButtonLabel: 'Forhåndsvis', contentDownloadButtonLabel: 'Hent innhold', reuseContentTabLabel: 'Finn delt innhold', contentPublisherPanelHeader: 'Informasjon om publiserer', noContentFoundDesc: 'Det finnes ikke noe innhold som samsvarer med ditt søk.', h5pType: 'H5P-type', level: 'Nivå', size: 'Størrelse', failedFetchingData: 'Henting av data mislyktes', filterErrorMessage: 'Noe gikk galt. Vennligst last siden på nytt.', in: 'i', navigateToParent: 'Naviger til overordnet nivå', a11yTitleShowLabel: 'Vis etikett for tilgjengelighet', a11yTitleHideLabel: 'Skjul etikett for tilgjengelighet', reuseSuccess: ':title ble vellykket importert fra H5P Hub.', }; PK*\#AA(h5plib/v127/joubel/editor/language/es.jsnu[H5PEditor.language.core = { missingTranslation: '[Falta la traducción :key]', loading: 'Cargando, por favor espera...', selectLibrary: 'Selecciona la librería que quieres usar con tu contenido.', unknownFieldPath: 'No se puede encontrar ":path".', notImageField: '":path" no es una imagen.', notImageOrDimensionsField: '":path" no es una imagen o un campo de dimensiones.', requiredProperty: 'La :property es requerida y debe tener un valor.', onlyNumbers: 'El valor de :property solo puede contener números.', illegalDecimalNumber: ':property solamente puede contenr números con máximo :decimals decimales.', exceedsMax: 'El valor de :property excede el máximo de :max.', listExceedsMax: 'La lista excede el máximo de :max elementos.', belowMin: 'El valor de :property excede el mínimo de :min.', listBelowMin: 'La lista necesita al menos :min elementos para que el contenido funcione adecuadamente.', outOfStep: 'El valor de :property solo puede ser cambiado en pasos de :step.', add: 'Añadir', addFile: 'Añadir archivo', removeFile: 'Eliminar archivo', confirmRemoval: '¿Estás seguro de que quieres eliminar este :type?', removeImage: 'Eliminar imagen', confirmImageRemoval: 'Esto eliminará la imagen. ¿Seguro que desea continuar?', changeFile: 'Cambiar archivo', changeLibrary: 'Cambiar el tipo de contenido', semanticsError: 'Error en semántica: :error', missingProperty: 'El campo :index no contiene la propiedad :property.', expandCollapse: 'Expandir/Colapsar', addEntity: 'Añadir :entity', tooLong: 'El valor del campo es demasiado largo, debería contener un máximo de :max letras.', invalidFormat: 'El valor del campo contiene un formato no válido o caracteres prohibidos.', confirmChangeLibrary: 'Al hacer esto perderás todo el trabajo realizado con el tipo de contenido actual. ¿Estás seguro de que quieres cambiar el tipo de contenido?', commonFields: 'Parámetros y textos', commonFieldsDescription: 'Aquí puedes editar parámetros o traducir textos utilizados en este contenido.', uploading: 'Subiendo, por favor espera...', noFollow: 'No se puede seguir el campo ":path".', editCopyright: 'Editar copyright', close: 'Cerrar', tutorial: 'Tutorial', editMode: 'Modo de edición', listLabel: 'Lista', uploadError: 'Error en la subida del archivo', fileToLarge: 'El archivo que intentas subir es demasiado grande.', unknownFileUploadError: 'Error de carga de archivo desconocido', noSemantics: 'Error, no se ha podido cargar el formulario del tipo de contenido.', editImage: 'Editar imagen', saveLabel: 'Guardar', cancelLabel: 'Cancelar', resetToOriginalLabel: 'Restablecer el original', loadingImageEditor: 'Cargando editor de imagen, por favor espere...', selectFiletoUpload: 'Selecciona el fichero a subir', or: 'o', enterAudioUrl: 'Introduzca la URL del origen del audio', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Pegue el link u otra fuente de audio', enterVideoTitle: 'Peque el link de Youtube o la URL de la fuente del video', uploadAudioTitle: 'Subir fichero de audio', uploadVideoTitle: 'Subir fichero de video', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Insertar', cancel: 'Cancelar', height: 'altura', width: 'ancho', textField: 'campo de texto', numberField: 'campo numérico', orderItemUp: 'Ordenar elemento arriba', orderItemDown: 'Ordenar elemento abajo', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Eliminar elemento', hubPanelLabel: 'Seleccionar tipo de contenido', importantInstructions: 'Instrucciones importantes', showImportantInstructions: 'Mostrar instrucciones', hideImportantInstructions: 'Ocultar instrucciones importantes', hide: 'Ocultar', example: 'Ejemplo', createContentTabLabel: 'Crear Contenido', uploadTabLabel: 'Subir', uploadPlaceholder: 'Ningún fichero seleccionado', uploadInstructionsTitle: 'Subir un fichero H5P.', uploadInstructionsContent: 'Usted puede comenzar con ejemplos de H5P.org.', uploadFileButtonLabel: 'Subir un fichero', uploadFileButtonChangeLabel: 'Cambiar fichero', uploadingThrobber: 'Subiendo ahora...', uploadSuccess: ':title se subió correctamente!', unableToInterpretError: 'Incapaz de interpretar la respuesta.', unableToInterpretSolution: 'Por favor compruebe su log de errores.', h5pFileWrongExtensionTitle: 'El fichero elegido no se puede subir', h5pFileWrongExtensionContent: 'Solo se permiten ficheros con la extensión .h5p.', h5pFileValidationFailedTitle: 'No se puede validar el fichero H5P.', h5pFileValidationFailedContent: 'Asegúrese de que el H5P cargado contiene contenido H5P válido. H5P Los archivos que contienen sólo bibliotecas deben cargarse a través de la página Bibliotecas H5P.', h5pFileUploadServerErrorTitle: 'El fichero H5P no se ha podido cargar', h5pFileUploadServerErrorContent: 'Ocurrió un error inesperado. Compruebe el registro de errores del servidor para obtener más detalles.', contentTypeSectionAll: 'Todos los tipos de contenidos', searchResults: 'Resultados de búsqueda', contentTypeSearchFieldPlaceholder: 'Buscar tipos de contenido', contentTypeInstallButtonLabel: 'Instalar', contentTypeInstallingButtonLabel: 'Instalando', contentTypeUseButtonLabel: 'Usar', contentTypeDetailButtonLabel: 'Detalles', contentTypeUpdateButtonLabel: 'Actualizar', contentTypeUpdatingButtonLabel: 'Actualizando', contentTypeGetButtonLabel: 'Obtener', contentTypeBackButtonLabel: 'Atrás', contentTypeIconAltText: 'Icono', contentTypeInstallSuccess: ':contentType instalado con éxito!', contentTypeUpdateSuccess: ':contentType actualizado con éxito!', contentTypeInstallError: ':contentType no puede ser instalado. Contacte con su administrador.', contentTypeLicensePanelTitle: 'Licencia', contentTypeDemoButtonLabel: 'Demo de Contenido', numResults: ':num resultados', show: 'Mostrar', recentlyUsedFirst: 'Usado recientemente Primero', popularFirst: 'Popular primero', newestFirst: 'Lo mas nuevo primero', aToZ: 'A a la Z', noResultsFound: 'No se han encontrado resultados', noResultsFoundDesc: 'No hay ningún tipo de contenido que coincida con sus criterios de búsqueda.', readMore: 'Leer más', readLess: 'Leer menos', contentTypeOwner: 'Por :owner', contentTypeUnsupportedApiVersionTitle: 'Este tipo de contenido requiere una nueva versión del core', contentTypeUnsupportedApiVersionContent: 'Póngase en contacto con el responsable del sistema para obtener las actualizaciones necesarias.', contentTypeUpdateAvailable: 'Actualización disponible', contentTypeRestricted: 'Tipo de contenido restringido', contentTypeRestrictedDesc: 'El uso de este tipo de contenido ha sido restringido por un administrador.', contentTypeNotInstalled: 'Tipo de contenido no instalado', contentTypeNotInstalledDesc: 'No tiene permiso para instalar tipos de contenido.', theContentType: 'el tipo de contenido', currentMenuSelected: 'selección actual', errorCommunicatingHubTitle: 'No se puede comunicar con el hub.', errorCommunicatingHubContent: 'Ha ocurrido un error. Por favor, inténtelo de nuevo.', warningNoContentTypesInstalled: 'No tiene ningún tipo de contenido instalado.', warningChangeBrowsingToSeeResults: 'Click Todos para obtener la lista de todos los tipos de contenido que puede instalar .', warningUpdateAvailableTitle: 'Una nueva versión de :contentType está disponible.', warningUpdateAvailableBody: 'Actualización a la última versión para una experiencia mejorada.', licenseDescription: 'Algunas de las características de esta licencia se indican a continuación. Haga clic en el icono de información de arriba para leer el texto original de la licencia.', licenseModalTitle: 'Detalles de la Licencia', licenseModalSubtitle: 'Seleccione una licencia para ver información sobre el uso adecuado', licenseUnspecified: 'Sin especificar', licenseCanUseCommercially: 'Uso comercial', licenseCanModify: 'Se puede modificar', licenseCanDistribute: 'Se puede distribuir', licenseCanSublicense: 'Se puede sublicenciar', licenseCanHoldLiable: 'Se puede declarar responsable', licenseCannotHoldLiable: 'No puede declararse responsable', licenseMustIncludeCopyright: 'Debe incluir copyright', licenseMustIncludeLicense: 'Debe incluir licencia', licenseFetchDetailsFailed: 'Fallo en la obtención de los detalles de la licencia', imageLightboxTitle: 'Imágenes', imageLightBoxProgress: ':num de :total', nextImage: 'Siguiente imagen', previousImage: 'Imagen anterior ', screenshots: 'Capturas de pantalla', reloadButtonLabel: 'Recargar', videoQuality: 'Etiqueta de calidad de vídeo', videoQualityDescription: 'Esta etiqueta ayuda al usuario a identificar la calidad actual del vídeo. Por ejemplo, 1080p, 720p, HD o móvil', videoQualityDefaultLabel: 'Calidad :index', noContentTypesAvailable: 'No hay tipos de contenido disponibles', noContentTypesAvailableDesc: 'Su sitio tiene dificultades para conectarse a H5P.org y para listar los tipos de contenido disponibles.', contentTypeCacheOutdated: 'Lista de tipos de contenido obsoleta', contentTypeCacheOutdatedDesc: 'Su sitio tiene dificultades para conectarse a H5P.org para comprobar si hay actualizaciones del tipo de contenido. Es posible que no pueda actualizar o instalar nuevos tipos de contenido.', tryAgain: 'Inténtelo de nuevo', getHelp: 'Obtener ayuda', untitled: 'Sin título :libraryTitle', title: 'Título', metadata: 'Metadata', addTitle: 'Añadir título', usedForSearchingReportsAndCopyrightInformation: 'Utilizado para búsquedas, informes e información de derechos de autor', metadataSharingAndLicensingInfo: 'Metadata (información sobre uso compartido y licencias)', fillInTheFieldsBelow: 'Rellene los siguientes campos', saveMetadata: 'Guardar metadatos', addAuthor: 'Guardar autor', confirmRemoveAuthor: '¿Está seguro de que desea eliminar a este autor?', addNewChange: 'Añadir nuevo cambio', confirmDeleteChangeLog: '¿Está seguro de que desea borrar esta entrada del registro de cambios?', changelogDescription: 'Algunas licencias requieren que los cambios realizados en la obra original o los derivados se registren y visualicen. Usted puede registrar sus cambios aquí por razones de licencia o simplemente para permitirse a usted y a otros mantener un registro de los cambios realizados en este contenido.', logThisChange: 'Registrar este cambio', newChangeHasBeenLogged: 'Se ha registrado un nuevo cambio', loggedChanges: 'Cambios registrados', noChangesHaveBeenLogged: 'No se ha registrado ningún cambio', errorHeader: 'Se ha producido un error', errorCalculatingMaxScore: 'No se pudo calcular la puntuación máxima para este contenido. La puntuación máxima se supone que es 0. Contacte con su administrador si esto no es correcto.', maxScoreSemanticsMissing: 'No se pudo encontrar la semántica esperada en el contenido.', copyButton: 'Copiar', copiedButton: 'Copiado', pasteButton: 'Pegar', pasteAndReplaceButton: 'Pegar y Reemplazar', pasteContent: 'Reemplazar contenido', confirmPasteContent: 'Al hacer esto usted reemplazará el contenido actual con el contenido de su portapapeles. El contenido actual se perderá. ¿Está seguro de que quiere continuar?', confirmPasteButtonText: 'Reemplazar contenido', copyToClipboard: 'Copiar el contenido H5P al portapapeles', copiedToClipboard: 'El contenido se ha copiado al portapapeles', pasteFromClipboard: 'Pegar el contenido H5P del portapapeles', pasteAndReplaceFromClipboard: 'Reemplazar el contenido existente con contenido H5P del portapapeles', pasteNoContent: 'Ningún contenido H5P en el portapapeles', pasteError: 'No se puede pegar desde el portapapeles', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insertar usando', tabTitleBasicFileUpload: 'Subir fichero', tabTitleInputLinkURL: 'Enlace/URL', errorTooHighVersion: 'Los parámetros contienen %used mientras que solo %supported o anterior están soportados.', errorNotSupported: 'Los parámetros contienen %used que no está soportado.', errorParamsBroken: 'Los parámetros están rotos.', libraryMissing: 'Falta la biblioteca requerida %lib.', scriptMissing: 'No se pudo cargar el script de actualizaciones para %lib.', language: 'Idioma', noLanguagesSupported: 'No hay idiomas soportados', changeLanguage: '¿Cambiar el idioma a :language?', thisWillPotentially: 'Esto potencialmente restablecerá todo el texto y las traducciones. No puedes deshacer esto. El contenido en sí no será cambiado. ¿Desea proceder?', notAllTextsChanged: 'No todos los textos fueron cambiados, solo hay una cobertura parcial para :language.', contributeTranslations: 'Si desea completar la traducción para :language, puede obtener información sobre contribuir con traducciones a H5P ', unknownLibrary: "Desafortunadamente, el tipo de contendo seleccionado '%lib' no está instalado en este sistema.", proceedButtonLabel: 'Proceder a guardar', enterFullscreenButtonLabel: 'Ir a pantalla completa', exitFullscreenButtonLabel: 'Salir de pantalla completa', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\??(h5plib/v127/joubel/editor/language/nl.jsnu[H5PEditor.language.core = { missingTranslation: '[Vertaling ontbreekt :key]', loading: 'Laden, wachten alstublieft ...', selectLibrary: 'Selecteer de library die je wilt gebruiken voor je content.', unknownFieldPath: 'Kon ":path" niet vinden.', notImageField: '":path" is geen afbeelding.', notImageOrDimensionsField: '":path" is geen afbeelding of een veld voor afmetingen.', requiredProperty: 'De :property is vereist en moet een waarde hebben.', onlyNumbers: 'De :property waarde mag alleen cijfers bevatten.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: 'De :property waarde is hoger dan het maximum :max.', listExceedsMax: 'De lijst is groter dan het maximum van :max items.', belowMin: 'De :property waarde is lager dan het minimum :min.', listBelowMin: 'De lijst moet ten minste :min items bevatten voor het correct werken van de content.', outOfStep: 'De :property waarde kan alleen worden gewijzigd in stappen van :step.', add: 'Toevoegen', addFile: 'Voeg bestand toe', removeFile: 'Verwijder bestand', confirmRemoval: 'Weet je zeker dat je dit :type wilt verwijderen?', removeImage: 'Verwijder afbeelding', confirmImageRemoval: 'Hiermee wordt je afbeelding verwijderd. Weet je zeker dat je wilt doorgaan?', changeFile: 'Wijzig bestand', changeLibrary: 'Content type wijzigen?', semanticsError: 'Semantics fout: :error', missingProperty: 'Veld :index mist :property eigenschap.', expandCollapse: 'Uitvouwen/Invouwen', addEntity: 'Voeg :entity toe', tooLong: 'Veldwaarde is te lang, mag :max letters of minder bevatten.', invalidFormat: 'Veldwaarde bevat een ongeldig format of karakters die verboden zijn.', confirmChangeLibrary: 'Hierdoor verlies je al het werk dat je met het huidige content type hebt gedaan. Weet je zeker dat je het content type wilt wijzigen?', commonFields: 'Tekst overschrijven en vertalingen', commonFieldsDescription: 'Hier kun je instellingen bewerken of in dit content type gebruikte teksten vertalen.', uploading: 'Uploaden, wachten alstublieft ...', noFollow: 'Kan veld ":path" niet volgen.', editCopyright: 'Copyright bewerken', close: 'Sluiten', tutorial: 'Tutorial beschikbaar', editMode: 'Bewerkmodus', listLabel: 'Lijst', uploadError: 'Fout bij uploaden bestand', fileToLarge: 'Het bestand dat je probeert te uploaden kan te groot zijn.', unknownFileUploadError: 'Onbekende fout bij uploaden bestand', noSemantics: 'Fout, kon het content type formulier niet laden.', editImage: 'Afbeelding bewerken', saveLabel: 'Opslaan', cancelLabel: 'Annuleren', resetToOriginalLabel: 'Terugzetten naar oorspronkelijk', loadingImageEditor: 'Afbeeldingseditor laden, wachten alstublieft ...', selectFiletoUpload: 'Selecteer bestand om te uploaden', or: 'of', enterAudioUrl: 'Voer audio bron URL in', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Plak link of andere URL van audiobron', enterVideoTitle: 'Plak YouTube-link of andere URL van videobron', uploadAudioTitle: 'Upload audiobestand', uploadVideoTitle: 'Upload videobestand', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Invoegen', cancel: 'Annuleren', height: 'hoogte', width: 'breedte', textField: 'tekstveld', numberField: 'getalveld', orderItemUp: 'Oplopend sorteren', orderItemDown: 'Aflopend sorteren', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Item verwijderen', hubPanelLabel: 'Selecteer content type', importantInstructions: 'Belangrijke instructies', showImportantInstructions: 'Toon instructies', hideImportantInstructions: 'Verberg belangrijke instructies', hide: 'Verberg', example: 'Voorbeeld', createContentTabLabel: 'Creëer inhoud', uploadTabLabel: 'Uploaden', uploadPlaceholder: 'Geen bestand gekozen', uploadInstructionsTitle: 'Een H5P bestand uploaden.', uploadInstructionsContent: 'Je kunt beginnen met voorbeelden van H5P.org.', uploadFileButtonLabel: 'Upload een bestand', uploadFileButtonChangeLabel: 'Wijzig bestand', uploadingThrobber: 'Uploaden...', uploadSuccess: ':title is met succes geüpload!', unableToInterpretError: 'Kon reactie niet interpreteren.', unableToInterpretSolution: 'Controleer je foutenlog.', h5pFileWrongExtensionTitle: 'Het geselecteerde bestand kon niet worden geüpload', h5pFileWrongExtensionContent: 'Alleen bestanden met de .h5p extensie toegestaan.', h5pFileValidationFailedTitle: 'Kon het H5P bestand niet valideren.', h5pFileValidationFailedContent: 'Zorg ervoor dat de geüploade H5P geldige H5P content bevat. H5P bestanden die alleen bibliotheken bevatten, dienen te worden geüpload via de H5P Bibliotheken pagina.', h5pFileUploadServerErrorTitle: 'Het H5P bestand kon niet worden geüpload', h5pFileUploadServerErrorContent: 'Er is een onverwachte fout opgetreden. Controleer het server log voor meer informatie.', contentTypeSectionAll: 'Alle Content Types', searchResults: 'Zoekresultaten', contentTypeSearchFieldPlaceholder: 'Zoeken naar Content Types', contentTypeInstallButtonLabel: 'Installeren', contentTypeInstallingButtonLabel: 'Bezig met installeren', contentTypeUseButtonLabel: 'Gebruik', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'Updaten', contentTypeUpdatingButtonLabel: 'Bezig met updaten', contentTypeGetButtonLabel: 'Ophalen', contentTypeBackButtonLabel: 'Terug', contentTypeIconAltText: 'Icoon', contentTypeInstallSuccess: ':contentType succesvol geïnstalleerd!', contentTypeUpdateSuccess: ':contentType succesvol geüpdatet!', contentTypeInstallError: ':contentType kon niet worden geïnstalleerd. Neem contact op met je site beheerder.', contentTypeLicensePanelTitle: 'Licentie', contentTypeDemoButtonLabel: 'Content Demo', numResults: ':num resultaten', show: 'Toon', recentlyUsedFirst: 'Recent gebruikt eerst', popularFirst: 'Populairste eerst', newestFirst: 'Nieuwste eerst', aToZ: 'A tot Z', noResultsFound: 'Geen resultaten gevonden', noResultsFoundDesc: 'Er is geen content type dat overeenkomt met je zoekcriteria.', readMore: 'Meer lezen', readLess: 'Minder lezen', contentTypeOwner: 'Door :owner', contentTypeUnsupportedApiVersionTitle: 'Dit content type vereist een nieuwere core versie', contentTypeUnsupportedApiVersionContent: 'Neem contact op met je site beheerder voor de benodigde updates', contentTypeUpdateAvailable: 'Update beschikbaar', contentTypeRestricted: 'Beperkt content type', contentTypeRestrictedDesc: 'Het gebruik van dit content type is beperkt door een site beheerder.', contentTypeNotInstalled: 'Content type niet geïnstalleerd', contentTypeNotInstalledDesc: 'Je hebt geen toestemming om content types te installeren.', theContentType: 'het content type', currentMenuSelected: 'huidige selectie', errorCommunicatingHubTitle: 'Kan niet communiceren met hub.', errorCommunicatingHubContent: 'Er is een fout opgetreden. Probeer het opnieuw.', warningNoContentTypesInstalled: 'Je hebt geen geïnstalleerde content types.', warningChangeBrowsingToSeeResults: 'Klik Alle om de lijst op te halen van alle content types die je kunt installeren.', warningUpdateAvailableTitle: 'Er is een nieuwe versie van :contentType beschikbaar.', warningUpdateAvailableBody: 'Update naar de laatste versie voor een verbeterde ervaring.', licenseDescription: 'Sommige van de kenmerken van deze licentie zijn hieronder weergegeven. Klik op het info icoon hierboven om de oorspronkelijke tekst van de licentie te lezen.', licenseModalTitle: 'Details van licentie', licenseModalSubtitle: 'Selecteer een licentie om informatie te krijgen over het correcte gebruik ervan', licenseUnspecified: 'Niet gespecificeerd', licenseCanUseCommercially: 'Mag commercieel gebruiken', licenseCanModify: 'Mag aanpassen', licenseCanDistribute: 'Mag distribueren', licenseCanSublicense: 'Mag sublicenties verstrekken', licenseCanHoldLiable: 'Mag aansprakelijk houden', licenseCannotHoldLiable: 'Mag niet aansprakelijk houden', licenseMustIncludeCopyright: 'Moet copyright bijvoegen', licenseMustIncludeLicense: 'Moet licentie bijvoegen', licenseFetchDetailsFailed: 'Details van licentie ophalen mislukt', imageLightboxTitle: 'Afbeeldingen', imageLightBoxProgress: ':num van :total', nextImage: 'Volgende afbeelding', previousImage: 'Vorige afbeelding', screenshots: 'Screenshots', reloadButtonLabel: 'Opnieuw laden', videoQuality: 'Videokwaliteitslabel', videoQualityDescription: 'Dit label helpt de gebruiker bij het vaststelllen van de huidige kwaliteit van de video. Bijv. 1080p, 720p, HD of Mobile', videoQualityDefaultLabel: 'Kwaliteit :index', noContentTypesAvailable: 'Geen content types beschikbaar', noContentTypesAvailableDesc: 'Je site heeft problemen bij het verbinden met H5P.org en het tonen van de beschikbare content types.', contentTypeCacheOutdated: 'Content types lijst is verlopen', contentTypeCacheOutdatedDesc: 'Je site heeft problemen bij het verbinden met H5P.org om te controleren op updates voor content types. Het kan zijn dat je geen content types kunt updaten of installeren.', tryAgain: 'Probeer nogmaals', getHelp: 'Vraag hulp', untitled: 'Zonder titel :libraryTitle', title: 'Titel', metadata: 'Metadata', addTitle: 'Voeg titel toe', usedForSearchingReportsAndCopyrightInformation: 'Gebruikt voor zoeken, rapportage en copyright informatie', metadataSharingAndLicensingInfo: 'Metadata (deel- en licentie-info)', fillInTheFieldsBelow: 'Vul de velden hieronder in', saveMetadata: 'Bewaar metadata', addAuthor: 'Bewaar auteur', confirmRemoveAuthor: 'Weet je zeker dat je deze auteur wilt verwijderen?', addNewChange: 'Voeg nieuwe wijziging toe', confirmDeleteChangeLog: 'Weet je zeker dat je deze invoer van het wijzigingslog wilt verwijderen?', changelogDescription: 'Sommige licenties vereisen dat wijzigingen aan het originele werk, of afgeleiden daarvan, worden gelogd en getoond. U kunt hier uw wijzigingen vanwege licentieredenen loggen of alleen om uzelf en anderen te informeren over wijzigingen aan deze inhoud.', logThisChange: 'Log deze wijziging', newChangeHasBeenLogged: 'Nieuwe wijziging is gelogd', loggedChanges: 'Gelogde wijzigingen', noChangesHaveBeenLogged: 'Er zijn geen wijzigingen gelogd', errorHeader: 'Er is een fout opgetreden', errorCalculatingMaxScore: 'Kon de maximumscore voor deze inhoud niet berekenen. De maximumscore lijkt 0 te zijn. Neem contact op met uw beheerder als dit niet juist is.', maxScoreSemanticsMissing: 'Kon de verwachte semantics in de content niet vinden.', copyButton: 'Kopiëren', copiedButton: 'Gekopieerd', pasteButton: 'Plakken', pasteAndReplaceButton: 'Plak en vervang', pasteContent: 'Plak inhoud', confirmPasteContent: 'Hiermee vervang je de huidige inhoud door de inhoud van het klembord. De huidige inhoud gaat verloren. Weet je zeker dat je wilt doorgaan?', confirmPasteButtonText: 'Vervang inhoud', copyToClipboard: 'Kopieer H5P inhoud naar het klembord', copiedToClipboard: 'Inhoud is gekopieerd naar het klembord', pasteFromClipboard: 'Plak H5P inhoud van het klembord', pasteAndReplaceFromClipboard: 'Vervang bestaande inhoud met H5P inhoud van het klembord', pasteNoContent: 'Geen H5P inhoud op het klembord', pasteError: 'Kan niet plakkken van klembord', pasteContentNotSupported: 'De inhoud in het H5P klembord wordt niet ondersteund in deze context', pasteContentRestricted: 'De inhoud in het H5P klembord bevat afgeschermde content', pasteTooOld: 'De inhoud in het H5P klembord is van een lagere versie (:clip) dan wat wordt ondersteund in deze context (:local), probeer indien mogelijk de inhoud die u wilt plakken te upgraden, kopieer het opnieuw en plak het hier opnieuw.', pasteTooNew: 'De inhoud in het H5P klembord is van een hogere versie (:clip) dan wat wordt ondersteund in deze context (:local), probeer indien mogelijk deze content eerst te upgraden, en probeer dan opnieuw de inhoud hier te plakken.', ok: 'OK', avTablistLabel: 'Invoegen m.b.v.', tabTitleBasicFileUpload: 'Bestandsupload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters bevat %used terwijl alleen %supported of vroeger wordt ondersteund.', errorNotSupported: 'Parameters bevat %used wat niet wordt ondersteund.', errorParamsBroken: 'Parameters zijn corrupt.', libraryMissing: 'Ontbrekende vereiste library %lib.', scriptMissing: 'Kon upgrade-script voor %lib niet laden.', language: 'Taal', noLanguagesSupported: 'Geen taal ondersteuning', changeLanguage: 'Wijzig taal naar :language?', thisWillPotentially: 'Mogelijk stelt dit alle tekst en vertalingen opnieuw in. Je kunt dit niet ongedaan maken. De content zelf wordt niet gewijzigd. Wil je doorgaan?', notAllTextsChanged: 'Niet alle teksten zijn gewijzigd, er is slechts gedeeltelijke dekking voor :language.', contributeTranslations: 'Als je de vertaling voor :language wilt completeren, kun je hier meer leren over het bijdragen van vertalingen aan H5P', unknownLibrary: "Jammer genoeg is het geselecteerde content type '%lib' niet geïnstalleerd op dit systeem.", proceedButtonLabel: 'Doorgaan naar opslaan', enterFullscreenButtonLabel: 'In volledig scherm werken', exitFullscreenButtonLabel: 'Volledig scherm afsluiten', a11yTitleShowLabel: 'Toon label voor AT', a11yTitleHideLabel: 'Verberg label voor AT', reuseSuccess: ':title is met succes geïmporteerd van de H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\8K=K=(h5plib/v127/joubel/editor/language/nn.jsnu[H5PEditor.language.core = { missingTranslation: '[Manglar oversettelse :key]', loading: 'Lastar, ver venleg og vent...', selectLibrary: 'Vel biblioteket du ønskjer å bruke for innhaldet ditt.', unknownFieldPath: 'Kan ikkje finne ":path".', notImageField: '":path" er ikkje eit bilete.', notImageOrDimensionsField: '":path" er korkje eit bilete- eller dimensjonsfelt.', requiredProperty: '":property" er påkravd og må ha ein verdi.', onlyNumbers: '":property" kan berre innhalde tal.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: '":property" overstig maksverdien på :max.', listExceedsMax: 'Antallet elementer i listen overstiger maksantallet på :max elementer.', belowMin: '":property" er mindre enn minimumsverdien på :min.', listBelowMin: 'Listen trenger minst :min elementer for at innholdet skal virke.', outOfStep: '":property" kan berre endrast i steg på :step.', add: 'Legg til', addFile: 'Legg til fil', removeFile: 'Fjern fil', confirmRemoval: 'Er du sikker på at du ønskjer å fjerne denne :type?', removeImage: 'Fjern bilde', confirmImageRemoval: 'Er du sikker på at du ønskjer å fjerne dette bildet?', changeFile: 'Bytt fil', changeLibrary: 'Endre innholdstype', semanticsError: 'Semantikkfeil: :error', missingProperty: 'Feltet :index manglar :property attributten sin.', expandCollapse: 'Utvid/Slå saman', addEntity: 'Legg til :entity', tooLong: 'Feltets verdi er for lang, den må vere på :max tegn eller mindre.', invalidFormat: 'Feltets verdi er på eit ugyldig format eller bruker ulovlege tegn.', confirmChangeLibrary: 'Gjør du dette mister du alt arbeid gjort med nåværande innhaldstype. Er du sikker på at du ønskjer å byte innhaldstype?', commonFields: 'Innstillinger og tekstar', commonFieldsDescription: 'Her kan du redigere innstillinger eller oversette tekstar som brukast i dette innhaldet.', uploading: 'Lastar opp fil, ver venleg og vent...', noFollow: 'Kunne ikkje følge feltet ":path".', editCopyright: 'Rediger opphavsrett', close: 'Lukk', tutorial: 'Veiledning', editMode: 'Redigeringsmodus', listLabel: 'Liste', uploadError: 'Filopplasting feilet', fileToLarge: 'Filen du prøver å laste opp kan være for stor.', unknownFileUploadError: 'Ukjent filopplastingsfeil', noSemantics: 'Feil, kunne ikke laste skjemaet for innholdstypen.', editImage: 'Rediger bilete', saveLabel: 'Lagre', cancelLabel: 'Avbryt', resetToOriginalLabel: 'Tilbakestill bilde', loadingImageEditor: 'Laster inn bilderedigering, vennligst vent...', selectFiletoUpload: 'Velg fil som skal lastes opp', or: 'eller', enterAudioUrl: 'Skriv inn nettadresse til lydkjelde', enterVideoUrl: 'Skriv inn nettadresse til video', enterAudioTitle: 'Lim inn link eller annan lydkjelde URL', enterVideoTitle: 'Lim inn YouTube lenke eller annen videokjelde URL', uploadAudioTitle: 'Last opp lydfil', uploadVideoTitle: 'Last opp videofil', addVideoDescription: 'H5P støtter alle eksterne videokilder på formatene mp4, webm eller ogv, slik som Vimeo Pro, og har støtte for YouTube-lenker og Panopto-lenker.', insert: 'Sett inn', cancel: 'Avbryt', height: 'Høyde', width: 'Bredde', textField: 'Tekstfelt', numberField: 'Nummerfelt', orderItemUp: 'Flytt element opp', orderItemDown: 'Flytt element ned', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Fjern element', hubPanelLabel: 'Select content type', importantInstructions: 'Viktige instruksjonar', showImportantInstructions: 'Vis instruksjonar', hideImportantInstructions: 'Skjul viktige instruksjonar', hide: 'Skjul', example: 'Eksempel', createContentTabLabel: 'Create Content', uploadTabLabel: 'Upload', uploadPlaceholder: 'No file chosen', uploadInstructionsTitle: 'Upload an H5P file.', uploadInstructionsContent: 'You may start with examples from H5P.org.', uploadFileButtonLabel: 'Upload a file', uploadFileButtonChangeLabel: 'Change file', uploadingThrobber: 'Now uploading...', uploadSuccess: ':title ble lastet opp!', unableToInterpretError: 'Kan ikke tolke respons.', unableToInterpretSolution: 'Vennligst sjekk feilloggen din.', h5pFileWrongExtensionTitle: 'The selected file could not be uploaded', h5pFileWrongExtensionContent: 'Only files with the .h5p extension are allowed.', h5pFileValidationFailedTitle: 'Could not validate H5P file.', h5pFileValidationFailedContent: 'Make sure the uploaded H5P contains valid H5P content. H5P files containing only libraries should be uploaded through the H5P Libraries page.', h5pFileUploadServerErrorTitle: 'The H5P file could not be uploaded', h5pFileUploadServerErrorContent: 'An unexpected error occured. Check your server error log for more details.', contentTypeSectionAll: 'Alle innhaldstypar', searchResults: 'Søkeresultater', contentTypeSearchFieldPlaceholder: 'Search for Content Types', contentTypeInstallButtonLabel: 'Install', contentTypeInstallingButtonLabel: 'Installing', contentTypeUseButtonLabel: 'Use', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'Update', contentTypeUpdatingButtonLabel: 'Updating', contentTypeGetButtonLabel: 'Get', contentTypeBackButtonLabel: 'Back', contentTypeIconAltText: 'Icon', contentTypeInstallSuccess: ':contentType successfully installed!', contentTypeUpdateSuccess: ':contentType successfully updated!', contentTypeInstallError: ':contentType could not be installed. Contact your administrator.', contentTypeLicensePanelTitle: 'License', contentTypeDemoButtonLabel: 'Content Demo', numResults: ':num treff', show: 'Vis', recentlyUsedFirst: 'Nylig brukt først', popularFirst: 'Populære først', newestFirst: 'Nyeste først', aToZ: 'A til Z', noResultsFound: 'Ingen resultater', noResultsFoundDesc: 'Det finnes ingen innholdstype som samsvarer med søkekriteriene dine.', readMore: 'Read more', readLess: 'Read less', contentTypeOwner: 'By :owner', contentTypeUnsupportedApiVersionTitle: 'This content type requires a newer core version', contentTypeUnsupportedApiVersionContent: 'Contact your system administrator to provide you with the necessary updates', contentTypeUpdateAvailable: 'Update available', contentTypeRestricted: 'Begrenset tilgong til innhaldstype', contentTypeRestrictedDesc: 'Bruken av denne innhaldstypen er begrenset av ein administrator.', contentTypeNotInstalled: 'Innehaldstype ikkje installert', contentTypeNotInstalledDesc: 'Du har ikkje tilgong til å installere innhaldstypar.', theContentType: 'the content type', currentMenuSelected: 'current selection', errorCommunicatingHubTitle: 'Not able to communicate with hub.', errorCommunicatingHubContent: 'An error occured. Please try again.', warningNoContentTypesInstalled: "You don't have any content types installed.", warningChangeBrowsingToSeeResults: 'Click All to get the list of all the content types you can install.', warningUpdateAvailableTitle: 'A new version of :contentType is available.', warningUpdateAvailableBody: 'Update to the latest version for an improved experience.', licenseDescription: 'Some of the features of this license are indicated below. Click the info icon above to read the original license text.', licenseModalTitle: 'License Details', licenseModalSubtitle: 'Select a license to view information about proper usage', licenseUnspecified: 'Unspecified', licenseCanUseCommercially: 'Can use commercially', licenseCanModify: 'Can modify', licenseCanDistribute: 'Can distribute', licenseCanSublicense: 'Can sublicense', licenseCanHoldLiable: 'Can hold liable', licenseCannotHoldLiable: 'Cannot hold liable', licenseMustIncludeCopyright: 'Must include copyright', licenseMustIncludeLicense: 'Must include license', licenseFetchDetailsFailed: 'Failed fetching license details', imageLightboxTitle: 'Images', imageLightBoxProgress: ':num of :total', nextImage: 'Next image', previousImage: 'Previous image', screenshots: 'Screenshots', reloadButtonLabel: 'Reload', videoQuality: 'Navn på videokvalitet', videoQualityDescription: 'Dette navnet hjelper brukeren med å identifisere den aktuelle videokvaliteten. F.eks. 1080p, 720p, HD or Mobile', videoQualityDefaultLabel: 'Kvalitet :index', noContentTypesAvailable: 'Ingen innhaldstyper er tilgjengeleg', noContentTypesAvailableDesc: 'Nettstedet ditt har problemer med å koble til H5P.org og liste tilgjengelege innhaldstyper.', contentTypeCacheOutdated: 'Innhaldstype-lista er utdatert', contentTypeCacheOutdatedDesc: 'Nettstedet ditt har problemer med å koble til H5P.org for å se etter innhaldstype-oppdateringer. Det kan hende at du ikke får oppdatert eller installert nye innhaldstyper.', tryAgain: 'Prøv på nytt', getHelp: 'Get help', untitled: 'Untitled :libraryTitle', title: 'Title', metadata: 'Metadata', addTitle: 'Add title', usedForSearchingReportsAndCopyrightInformation: 'Used for searching, reports and copyright information', metadataSharingAndLicensingInfo: 'Metadata (sharing and licensing info)', fillInTheFieldsBelow: 'Fill in the fields below', saveMetadata: 'Save metadata', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Add new change', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Log this change', newChangeHasBeenLogged: 'New change has been logged', loggedChanges: 'Logged changes', noChangesHaveBeenLogged: 'No changes have been logged', errorHeader: 'An error occured', errorCalculatingMaxScore: 'Could not calculate the max score for this content. The max score is assumed to be 0. Contact your administrator if this isn’t correct.', maxScoreSemanticsMissing: 'Could not find the expected semantics in the content.', copyButton: 'Kopier', copiedButton: 'Kopiert', pasteButton: 'Lim inn', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Copy H5P content to the clipboard', copiedToClipboard: 'Content is copied to the clipboard', pasteFromClipboard: 'Paste H5P content from the clipboard', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'No H5P content on the clipboard', pasteError: 'Cannot paste from clipboard', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: "Dessverre var ikke den valgte '%lib'-innholdstypen installert på dette systemet.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\>yO==(h5plib/v127/joubel/editor/language/sv.jsnu[H5PEditor.language.core = { missingTranslation: '[Saknar översättning :key]', loading: 'Laddar, vänta ...', selectLibrary: 'Välj det bibliotek som du vill använda för ditt innehåll.', unknownFieldPath: 'Kunde inte hitta ":path".', notImageField: '":path" är inte en bild.', notImageOrDimensionsField: '":path" är inte en bild eller dimensionsfält.', requiredProperty: ':property krävs och måste ha ett värde.', onlyNumbers: 'Värdet :property kan endast innehålla nummer.', illegalDecimalNumber: ':property kan endast innehålla nummer med max :decimals decimaler.', exceedsMax: 'Värdet :property överskrider maxvärdet :max.', listExceedsMax: 'Listan överskrider maxvärdet :max poster.', belowMin: 'Värdet :property är under minimum :min.', listBelowMin: 'Listan behöver mninst :min poster för att innehållet ska fungera korrekt.', outOfStep: 'Värdet :property kan endast ändras i steg om :step.', add: 'Lägg till', addFile: 'Lägg till fil', removeFile: 'Ta bort fil', confirmRemoval: 'Är du säker på att du vill ta bort :type?', removeImage: 'Ta bort bild', confirmImageRemoval: 'Detta kommer ta bort din bild. Är du säker?', changeFile: 'Byt ut fil', changeLibrary: 'Ändra innehållstyp?', semanticsError: 'Semantikfel: :error', missingProperty: 'Fält :index saknar dess :property egenskap.', expandCollapse: 'Expandera/Komprimera', addEntity: 'Lägg till :entity', tooLong: 'Fältvärdet är för långt, får max innehålla :max tecken eller färre.', invalidFormat: 'Fältvärdet innehåller ett ogiltigt format eller tecken som är förbjudna.', confirmChangeLibrary: 'Om du gör detta så kommer du förlora allt du gjort med nuvarande innehållstyp. Är du säker på att du vill byta innehållstyp?', commonFields: 'Textersättningar och översättningar', commonFieldsDescription: 'Här kan du ändra eller översätta texter som används i detta innehåll.', uploading: 'Laddar upp, vänta ...', noFollow: 'Kan inte följa fält ":path".', editCopyright: 'Redigera copyright', close: 'Stäng', tutorial: 'Guide', editMode: 'Redigeringsläge', listLabel: 'Lista', uploadError: 'Fel vid filuppladdning', fileToLarge: 'Filen som du försöker ladda upp kan vara för stor.', unknownFileUploadError: 'Okänt fel vid filuppladdning', noSemantics: 'Fel, kunde inte ladda formatet för innehållstypen', editImage: 'Redigera bild', saveLabel: 'Spara', cancelLabel: 'Avbryt', resetToOriginalLabel: 'Återställ till original', loadingImageEditor: 'Laddar bildredigerare,vänta ...', selectFiletoUpload: 'Välj fil att ladda upp', or: 'eller', enterAudioUrl: 'Lägg till URL för ljudkälla', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Klistra in länk eller annan URL till ljudkälla', enterVideoTitle: 'Klistra in YouTube-länk eller annan URL till videokälla', uploadAudioTitle: 'Ladda upp ljudfil', uploadVideoTitle: 'Ladda upp videofil', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Infoga', cancel: 'Avbryt', height: 'höjd', width: 'bredd', textField: 'textfält', numberField: 'nummerfält', orderItemUp: 'Flytta post uppåt', orderItemDown: 'Flytta post nedåt', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Ta bort post', hubPanelLabel: 'Välj innehållstyp', importantInstructions: 'Viktiga instruktioner', showImportantInstructions: 'Visa instruktioner', hideImportantInstructions: 'Dölj viktiga instruktioner', hide: 'Dölj', example: 'Exempel', createContentTabLabel: 'Skapa innehåll', uploadTabLabel: 'Ladda upp', uploadPlaceholder: 'Ingen fil vald', uploadInstructionsTitle: 'Ladda upp en H5P-fil.', uploadInstructionsContent: 'Du kan börja med exempel från H5P.org.', uploadFileButtonLabel: 'Ladda upp en fil', uploadFileButtonChangeLabel: 'Byt ut fil', uploadingThrobber: 'Laddar upp ...', uploadSuccess: ':title uppladdad!', unableToInterpretError: 'Kunde inte tolka svar.', unableToInterpretSolution: 'Kontrollera din fellogg.', h5pFileWrongExtensionTitle: 'Den valda filen kunde inte laddas upp', h5pFileWrongExtensionContent: 'Endast filer med filändelsen .h5p tillåts.', h5pFileValidationFailedTitle: 'Kunde inte validera H5P-fil.', h5pFileValidationFailedContent: 'Kontrollera att uppladdad H5P innehåller giltigt H5P innehåll. H5P filer som enbart innehåller bibliotek ska laddas upp via sidan H5P-bibliotek.', h5pFileUploadServerErrorTitle: 'H5P-filen kunde inte laddas upp', h5pFileUploadServerErrorContent: 'Ett fel har uppstått. Kontrollera din fellogg på servern för mer information.', contentTypeSectionAll: 'Alla innehållstyper', searchResults: 'Sökrsultat', contentTypeSearchFieldPlaceholder: 'Sök innehållstyper', contentTypeInstallButtonLabel: 'Installera', contentTypeInstallingButtonLabel: 'Installerar', contentTypeUseButtonLabel: 'Använd', contentTypeDetailButtonLabel: 'Uppgifter', contentTypeUpdateButtonLabel: 'Uppdatera', contentTypeUpdatingButtonLabel: 'Uppdaterar', contentTypeGetButtonLabel: 'Hämta', contentTypeBackButtonLabel: 'Tillbaka', contentTypeIconAltText: 'Ikon', contentTypeInstallSuccess: ':contentType installerad!', contentTypeUpdateSuccess: ':contentType uppdaterad!', contentTypeInstallError: ':contentType kunde inte installeras. Kontakta din administratör.', contentTypeLicensePanelTitle: 'Licens', contentTypeDemoButtonLabel: 'Innehållsdemo', numResults: ':num resultat', show: 'Visa', recentlyUsedFirst: 'Senast använda först', popularFirst: 'Populära först', newestFirst: 'Nyast först', aToZ: 'A till Ö', noResultsFound: 'Inga resultat', noResultsFoundDesc: 'Det finns ingen innehållstyp som matchar din sökning.', readMore: 'Läs mer', readLess: 'Läs mindre', contentTypeOwner: 'Av :owner', contentTypeUnsupportedApiVersionTitle: 'Denna innehållstyp kräver en nyare core-version', contentTypeUnsupportedApiVersionContent: 'Kontakta din systemadministratör för att få tillgång till nödvändiga uppdateringar', contentTypeUpdateAvailable: 'Uppdatering tillgänglig', contentTypeRestricted: 'Begränsad innehållstyp', contentTypeRestrictedDesc: 'Användningen av denna innehållstyp har begränsats av en administratör.', contentTypeNotInstalled: 'Innehållstyp inte installerad', contentTypeNotInstalledDesc: 'Du har inte rättighet att installera innehållstyper.', theContentType: 'innehållstypen', currentMenuSelected: 'nuvarande urval', errorCommunicatingHubTitle: 'Kan inte kommunicera med hubben.', errorCommunicatingHubContent: 'Ett fel uppstod. Försök igen.', warningNoContentTypesInstalled: 'Du har inte någon innehållstyp installerad.', warningChangeBrowsingToSeeResults: 'Klicka Alla för att få listan med alla innehållstyper som du kan installera.', warningUpdateAvailableTitle: 'En ny version av :contentType är tillgänglig.', warningUpdateAvailableBody: 'Uppdatera till senaste version för en förbättrad upplevelse.', licenseDescription: 'Vissa egenskaper för denna licens framgår nedan. Klicka på info-ikonen ovanför för att läsa licenstexten i original.', licenseModalTitle: 'Licensuppgifter', licenseModalSubtitle: 'Välj en licens för att ta del av information om korrekt användning', licenseUnspecified: 'Ospecificerad', licenseCanUseCommercially: 'Kan använda kommersiellt', licenseCanModify: 'Kan modifiera', licenseCanDistribute: 'Kan distribuera', licenseCanSublicense: 'Kan underlicensiera', licenseCanHoldLiable: 'Kan hållas ansvarig', licenseCannotHoldLiable: 'Kan inte hållas ansvarig', licenseMustIncludeCopyright: 'Måste inkludera copyright', licenseMustIncludeLicense: 'Måste inkludera licens', licenseFetchDetailsFailed: 'Misslyckades med hämtning av licensuppgifter', imageLightboxTitle: 'Bilder', imageLightBoxProgress: ':num av :total', nextImage: 'Nästa bild', previousImage: 'Föregående bild', screenshots: 'Skärmbilder', reloadButtonLabel: 'Ladda om', videoQuality: 'Etikett för videokvalitet', videoQualityDescription: 'Denna etikett underlättar för användaren att identifiera nuvarande kvalitet på videon. T ex 1080p, 720p, HD eller mobil', videoQualityDefaultLabel: 'Kvalitet :index', noContentTypesAvailable: 'Inga innehållstyper är tillgängliga', noContentTypesAvailableDesc: 'Din webbplats har problem med att ansluta till H5P.org och listan över tillgängliga innehållstyper.', contentTypeCacheOutdated: 'Lista över innehållstyper behöver uppdateras.', contentTypeCacheOutdatedDesc: 'Din webbplats har problem med att ansluta till H5P.org för att leta efter uppdateringar av innehållstyper. Det kan hända att du inte kan uppdatera eller installera nya innehållstyper.', tryAgain: 'Försök igen', getHelp: 'Få hjälp', untitled: 'Utan titel :libraryTitle', title: 'Titel', metadata: 'Metadata', addTitle: 'Lägg till titel', usedForSearchingReportsAndCopyrightInformation: 'Används för sökning, rapporter och copyright-information', metadataSharingAndLicensingInfo: 'Metadata (info om delning och licensiering)', fillInTheFieldsBelow: 'Fyll i fälten nedan', saveMetadata: 'Spara metadata', addAuthor: 'Spara författare', confirmRemoveAuthor: 'Är du säker på att du vill ta bort denna författare?', addNewChange: 'Lägg till ny ändring', confirmDeleteChangeLog: 'Är du säker på att du vill radera denna post i ändringsloggen?', changelogDescription: 'Vissa licenser kräver att ändringar till originalet, eller derivat, loggas och visas. Du kan logga dina ändringar här av licensskäl eller bara för din egen eller andras skull.', logThisChange: 'Logga denna ändring', newChangeHasBeenLogged: 'Ny ändring har loggats', loggedChanges: 'Loggade ändringar', noChangesHaveBeenLogged: 'Inga ändringar har loggats', errorHeader: 'Ett fel uppstod', errorCalculatingMaxScore: 'Kunde inte beräkna maxpoäng för detta innehåll. Maxpoäng förväntas vara 0. Kontakta din administratör om detta inte är korrekt.', maxScoreSemanticsMissing: 'Kunde inte hitta förväntad semantik i detta innehåll.', copyButton: 'Kopiera', copiedButton: 'Kopierad', pasteButton: 'Klistra in', pasteAndReplaceButton: 'Klistra in & ersätt', pasteContent: 'Ersätt innehåll', confirmPasteContent: 'Om du gör detta så kommer du ersätta befintligt innehåll med ditt kopierade innehåll från urklipp. Nuvarande innehåll kommer att försvinna. Är du säker på att du vill fortsätta?', confirmPasteButtonText: 'Ersätt innehåll', copyToClipboard: 'Kopiera H5P-innehåll till urklipp', copiedToClipboard: 'Innehåll är kopierat till urklipp', pasteFromClipboard: 'Klistra in H5P-innehåll från urklipp', pasteAndReplaceFromClipboard: 'Ersätt nuvarande inehåll med H5P-innehåll från urklipp', pasteNoContent: 'Inget H5P-innehåll i urklipp', pasteError: 'Kan inte klistra in från urklipp', pasteContentNotSupported: 'Innehållet i urklipp stöds inte i detta sammanhang', pasteContentRestricted: 'Innehållet i urklipp har begränsats på denna webbplats', pasteTooOld: 'Innehållet i urklipp har en lägre version (:clip) än vad som stöds i detta sammanhang (:local), om möjligt, uppgradera innehållet du vill klistra in och försök sen igen.', pasteTooNew: 'Innehållet i urklipp har en högre version (:clip) än vad som stöds i detta sammanhang (:local), om möjligt, uppgradera innehållet här först och försök sen igen.', ok: 'OK', avTablistLabel: 'Infoga genom', tabTitleBasicFileUpload: 'Filuppladdning', tabTitleInputLinkURL: 'Länk/URL', errorTooHighVersion: 'Parametrar innehåller %used där endast %supported eller tidigare stöds.', errorNotSupported: 'Parametrar innehåller %used som inte stöds.', errorParamsBroken: 'Parametrar är trasiga .', libraryMissing: 'Saknar obligatoriskt bibliotek %lib.', scriptMissing: 'Kunde inte ladda upp uppgraderingsscript för %lib.', language: 'Språk', noLanguagesSupported: 'Inga språk stöd', changeLanguage: 'Ändra språk till :language?', thisWillPotentially: 'Detta kan nollställa alla textändringar och översättningar här. Du kan inte ångra detta. Själva innehållet kommer däremot inte att påverkas. Vill du fortsätta?', notAllTextsChanged: 'Inte alla texter ändrades, det finns endast delvis stöd för :language.', contributeTranslations: 'Om du vill bidra till översättningen av :language så kan du läsa mer här contributing translations to H5P', unknownLibrary: "Tyvärr, innehållstypen '%lib' är inte installerad på denna webbplats.", proceedButtonLabel: 'Fortsätt för att spara', enterFullscreenButtonLabel: 'Helskärmsläge', exitFullscreenButtonLabel: 'Avsluta helskärm', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', }; PK*\M)Ot??(h5plib/v127/joubel/editor/language/sl.jsnu[H5PEditor.language.core = { missingTranslation: '[Manjka prevod :key]', loading: 'Nalagam, počakajte prosim ...', selectLibrary: 'Izberite knjižnico, ki jo želite uporabiti za svojo vsebino.', unknownFieldPath: 'Ni mogoče najti ":path".', notImageField: '":path" ni slika.', notImageOrDimensionsField: '":path" ni slika oz. ustreznih dimenzij.', requiredProperty: ':property se zahteva in mora vsebovati vrednost.', onlyNumbers: ':property lahko vsebuje le števila.', illegalDecimalNumber: ':property lahko vsebuje le števila z največ naslednjim številom decimalnih mest: :decimals.', exceedsMax: ':property presega največjo dovoljeno vrednost :max.', listExceedsMax: 'Seznam presega največje dovoljeno vrednost :max.', belowMin: ':property je pod najmanjšo dovoljeno vrednostjo :min.', listBelowMin: 'Seznam mora za pravilno delovanje obsegati vsaj naslednje število elementov: :min.', outOfStep: ':property se lahko spremeni samo v korakih :step.', add: 'Dodaj', addFile: 'Dodaj datoteko', removeFile: 'Izbriši datoteko', confirmRemoval: 'Resnično izbrišem datoteko :type?', removeImage: 'Izbriši sliko', confirmImageRemoval: 'Resnično izbrišem sliko?', changeFile: 'Spremeni datoteko', changeLibrary: 'Sprememba tipa vsebine', semanticsError: 'Semantična napaka: :error', missingProperty: 'Za polje :index manjka :property.', expandCollapse: 'Razširi/zloži', addEntity: 'Dodaj :entity', tooLong: 'Polje je predolgo. Vsebovati mora največ naslednje število črk: :max.', invalidFormat: 'Vrednost polja vsebuje neveljaven format ali nedovoljene znake.', confirmChangeLibrary: 'S spremembo boste izgubili vso opravljeno delo v trenutni vsebini. Ali ste prepričani, da želite nadaljevati?', commonFields: 'Preglasitve besed in prevodi', commonFieldsDescription: 'Spremembe besed v tem razdelku bodo veljale le za to vsebino.', uploading: 'Nalagam, počakajte prosim ... ', noFollow: 'Polju ni mogoče slediti ":path".', editCopyright: 'Uredi avtorske pravice', close: 'Zapri', tutorial: 'Pomoč', editMode: 'Urejevalni način', listLabel: 'Seznam', uploadError: 'Napaka pri nalaganju datoteke', fileToLarge: 'Datoteka, ki jo poskušate naložiti, je morda prevelika.', unknownFileUploadError: 'Neznana napaka pri nalaganju datoteke', noSemantics: 'Napaka. Obrazca z vsebino ni bilo mogoče naložiti.', editImage: 'Uredi sliko', saveLabel: 'Shrani', cancelLabel: 'Prekliči', resetToOriginalLabel: 'Ponastavi na privzeto', loadingImageEditor: 'Nalagam urejevalnik slik, počakajte prosim ...', selectFiletoUpload: 'Izberite datoteko za prenos', or: 'ali', enterAudioUrl: 'Vpis spletnega naslova (URL)', enterVideoUrl: 'Dodaj spletni naslov (URL) do videoposnetka', enterAudioTitle: 'Dodaj spletni naslov (URL) do zvočnega posnetka', enterVideoTitle: 'Dodaj spletni naslov (URL) do YouTube ali drugega videoposnetka', uploadAudioTitle: 'Naloži zvočni posnetek', uploadVideoTitle: 'Naloži videoposnetek', addVideoDescription: 'H5P podpira vse zunanje videoposnetke v formatu mp4, webm ali ogv. Tudi povezave do posnetkov na Vimeo Pro, YouTube in Panopto.', insert: 'Vstavi', cancel: 'Prekliči', height: 'višina', width: 'širina', textField: 'polje za vnos besedila', numberField: 'polje za vnos števila', orderItemUp: 'Premakni navzgor', orderItemDown: 'Premakni navzdol', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Odstrani', hubPanelLabel: 'Izberi tip vsebine', importantInstructions: 'Pomembna navodila', showImportantInstructions: 'Prikaži navodila', hideImportantInstructions: 'Skrij navodila', hide: 'Skrij', example: 'Primer', createContentTabLabel: 'Ustvari vsebino', uploadTabLabel: 'Naloži iz datoteke', uploadPlaceholder: 'Izbrana ni nobena datoteka', uploadInstructionsTitle: 'Naloži datoteko H5P.', uploadInstructionsContent: 'Začnete lahko s primeri iz H5P.org.', uploadFileButtonLabel: 'Naloži', uploadFileButtonChangeLabel: 'Zamenjaj datoteko', uploadingThrobber: 'Nalagam datoteko ...', uploadSuccess: 'Vsebina :title je bila uspešno naložena!', unableToInterpretError: 'Ni mogoče razbrati odziva.', unableToInterpretSolution: 'Preverite dnevnik napak.', h5pFileWrongExtensionTitle: 'Izbrane datoteke ni mogoče naložiti', h5pFileWrongExtensionContent: 'Dovoljene so le datoteke s končnico .h5p.', h5pFileValidationFailedTitle: 'Datoteke H5P ni bilo mogoče preveriti.', h5pFileValidationFailedContent: 'Prepričajte se, da naložena datoteka vsebuje veljavno vsebino H5P. Datoteke knjižnic je treba naložiti preko strani H5P knjižnic.', h5pFileUploadServerErrorTitle: 'Datoteke H5P ni bilo mogoče naložiti', h5pFileUploadServerErrorContent: 'Prišlo je do neznane napake. Preverite dnevnik napak za več informacij.', contentTypeSectionAll: 'Vsi tipi vsebin', searchResults: 'Rezultati iskanja', contentTypeSearchFieldPlaceholder: 'Iskanje tipov vsebin', contentTypeInstallButtonLabel: 'Namesti', contentTypeInstallingButtonLabel: 'Nameščanje', contentTypeUseButtonLabel: 'Uporabi', contentTypeDetailButtonLabel: 'Podrobno', contentTypeUpdateButtonLabel: 'Posodobitev', contentTypeUpdatingButtonLabel: 'Posodabljanje', contentTypeGetButtonLabel: 'Pridobi', contentTypeBackButtonLabel: 'Nazaj', contentTypeIconAltText: 'Ikona', contentTypeInstallSuccess: 'Tip vsebine :contentType uspešno nameščen!', contentTypeUpdateSuccess: 'Tip vsebine :contentType uspešno posodobljen!', contentTypeInstallError: 'Tipa vsebine :contentType ni mogoče namestiti. Obrnite se na vašega administratorja.', contentTypeLicensePanelTitle: 'Licenca', contentTypeDemoButtonLabel: 'Demonstracija vsebine', numResults: 'zadetki: :num', show: 'Prikaži', recentlyUsedFirst: 'Nedavni najprej', popularFirst: 'Priljubljeni najprej', newestFirst: 'Novi najprej', aToZ: 'A do Z', noResultsFound: 'Ni zadetkov', noResultsFoundDesc: 'Ni vsebine, ki bi ustrezala kriterijem iskanja.', readMore: 'Preberi več', readLess: 'Preberi manj', contentTypeOwner: 'Avtor :owner', contentTypeUnsupportedApiVersionTitle: 'Ta vrsta vsebine zahteva novejšo različico jedra', contentTypeUnsupportedApiVersionContent: 'Za zagotovitev potrebnih posodobitev se obrnite na administratorja sistema', contentTypeUpdateAvailable: 'Na voljo posodobitev', contentTypeRestricted: 'Vsebina z omejenim dostopom', contentTypeRestrictedDesc: 'Uporabo te vrste vsebine je omejil administrator.', contentTypeNotInstalled: 'Tip vsebine ni nameščen', contentTypeNotInstalledDesc: 'Nimate dovoljenja za namestitev novih tipov vsebine.', theContentType: 'tip vsebine', currentMenuSelected: 'trenutni izbor', errorCommunicatingHubTitle: 'Ni mogoče komunicirati s središčem H5P.', errorCommunicatingHubContent: 'Prišlo je do neznane napake. Poskusite znova.', warningNoContentTypesInstalled: 'Nimate nameščenih nobenih tipov vsebine.', warningChangeBrowsingToSeeResults: 'Izberite All za prikaz seznama vseh tipov vsebine, ki jih lahko namestite.', warningUpdateAvailableTitle: 'Na voljo je nova različica tipa vsebine :contentType.', warningUpdateAvailableBody: 'Posodobitev na najnovejšo različico izboljša uporabniško izkušnjo.', licenseDescription: 'Nekatere značilnosti te licence so navedene spodaj. Ogled izvornih informacij o licenci je dosegljiv s klikom na ikono(i) zgoraj.', licenseModalTitle: 'Podrobnosti o licenci', licenseModalSubtitle: 'Izberite licenco za ogled informacij o pravilni uporabi', licenseUnspecified: 'Neopredeljeno', licenseCanUseCommercially: 'Lahko se uporablja komercialno', licenseCanModify: 'Lahko se spreminja', licenseCanDistribute: 'Lahko se deli', licenseCanSublicense: 'Lahko se podeli podlicenca', licenseCanHoldLiable: 'Lahko prenaša odgovornost', licenseCannotHoldLiable: 'Ne prenaša odgovornosti', licenseMustIncludeCopyright: 'Vsebovati mora avtorske pravice', licenseMustIncludeLicense: 'Vsebovati mora licenco', licenseFetchDetailsFailed: 'Podatkov o licenci ni bilo mogoče pridobiti', imageLightboxTitle: 'Slike', imageLightBoxProgress: ':num od :total', nextImage: 'Naslednja slika', previousImage: 'Prejšnja slika', screenshots: 'Zaslonski posnetek', reloadButtonLabel: 'Ponovno naloži', videoQuality: 'Oznaka kakovosti videoposnetka', videoQualityDescription: 'Ta oznaka pomaga uporabniku prepoznati trenutno kakovost videoposnetka. Npr. 1080p, 720p, HD ali Mobilne naprave', videoQualityDefaultLabel: 'Kakovost :index', noContentTypesAvailable: 'Na voljo ni nobenega tipa vsebine', noContentTypesAvailableDesc: 'Vaše spletno mesto ima težave pri povezovanju s H5P.org in pripravo seznama razpoložljivih tipov vsebine.', contentTypeCacheOutdated: 'Seznam tipov vsebine je zastarel', contentTypeCacheOutdatedDesc: 'Vaše spletno mesto ima težave pri povezovanju s H5P.org in preverjanju posodobitev za tipe vsebine. Morda ne boste mogli posodobiti ali namestiti novih tipov vsebine.', tryAgain: 'Poskusite znova', getHelp: 'Pridobi pomoč', untitled: 'Brez naslova :libraryTitle', title: 'Naslov', metadata: 'Metapodatki', addTitle: 'Dodaj naslov', usedForSearchingReportsAndCopyrightInformation: 'Uporablja se za iskanje, poročila in informacije o avtorskih pravicah', metadataSharingAndLicensingInfo: 'Metapodatki (informacije o skupni rabi in licenciranju)', fillInTheFieldsBelow: 'Izpolnite spodnja polja', saveMetadata: 'Shrani metapodatke', addAuthor: 'Shrani avtorja', confirmRemoveAuthor: 'Ali ste prepričani, da želite odstraniti tega avtorja?', addNewChange: 'Dodaj nov zapis', confirmDeleteChangeLog: 'Ali ste prepričani, da želite odstraniti zapis te spremembe?', changelogDescription: 'Nekatere licence zahtevajo, da se beležijo in prikazujejo vse spremembe prvotnega dela ali njegovih različic. Na tem mestu lahko beležite svoje spremembe iz razloga izdaje licence ali zgolj zato, da sebi in drugim omogočite lažje sledenje sprememb v tej vsebini.', logThisChange: 'Shrani spremembo', newChangeHasBeenLogged: 'Nova sprememba je zabeležena', loggedChanges: 'Zabeležene spremembe', noChangesHaveBeenLogged: 'Ni zabeleženih sprememb', errorHeader: 'Prišlo je do napake', errorCalculatingMaxScore: 'Najboljšega rezultata za to vsebino ni mogoče izračunati. Predvideva se, da je število enako 0. Če to ni pravilno, se obrnite na svojega administratorja.', maxScoreSemanticsMissing: 'V vsebini ni bilo mogoče najti pričakovane semantike.', copyButton: 'Kopiraj', copiedButton: 'Kopirano', pasteButton: 'Prilepi', pasteAndReplaceButton: 'Prilepi & Zamenjaj', pasteContent: 'Zamenjaj vsebino', confirmPasteContent: 'S tem boste trenutno vsebino nadomestili z vsebino iz odložišča in bo izgubljena. Ali ste prepričani, da želite nadaljevati?', confirmPasteButtonText: 'Zamenjaj vsebino', copyToClipboard: 'Kopiraj vsebino H5P v odložišče', copiedToClipboard: 'Vsebina H5P je kopirana v odložišče', pasteFromClipboard: 'Prilepi vsebino H5P iz odložišča', pasteAndReplaceFromClipboard: 'Zamenjaj trenutno vsebino z vsebino H5P iz odložišča', pasteNoContent: 'V odložišču ni vsebine H5P', pasteError: 'Iz odložišča ni mogoče prilepiti vsebine H5P', pasteContentNotSupported: 'Vsebina H5P v odložišču v tej različici ni podprta', pasteContentRestricted: 'Vsebina H5P v odložišču ima na tej strani omejen dostop', pasteTooOld: 'Vsebina H5P v odložišču je pripravljena v nižji različici (:clip), kot je podprta tukaj (:local). Če je mogoče, poskušajte najprej vsebino nadgraditi in jo šele nato prilepiti sem.', pasteTooNew: 'Vsebina H5P v odložišču je pripravljena v višji različici (:clip), kot je podprta tukaj (:local). Če je mogoče, poskušajte najprej nadgraditi to vsebino in šele nato prilepiti sem želeno.', ok: 'V redu', avTablistLabel: 'Vstavljanje', tabTitleBasicFileUpload: 'Naloži datoteko', tabTitleInputLinkURL: 'Povezava/URL', errorTooHighVersion: 'Parametri vsebujejo %used, medtem ko so podprti samo %supported ali predhodni.', errorNotSupported: 'Parametri vsebujejo %used, ki niso podprti.', errorParamsBroken: 'Parametri ne delujejo.', libraryMissing: 'Manjka zahtevana knjižnica %lib.', scriptMissing: 'Ni mogoče naložiti skripte nadgradenj za %lib.', language: 'Jezik', noLanguagesSupported: 'Jeziki niso podprti', changeLanguage: 'Spremenim jezik v :language?', thisWillPotentially: 'To bi lahko vplivalo na ponastavitev vseh preglasitev besed in prevodov, medtem ko bo sama vsebina ostala nespremenjena. Tega ne morete razveljaviti. Ali želite nadaljevati?', notAllTextsChanged: 'Vse besede niso bile spremenjene, saj manjkajo prevodi za jezik :language.', contributeTranslations: 'Več o prispevanju prevodov za jezik :language najdete na spletni strani H5P', unknownLibrary: "Na žalost izbran tip vsebine '%lib' ni nameščen na tem spletnem mestu", proceedButtonLabel: 'Shrani', enterFullscreenButtonLabel: 'Vklopi celozaslonski način', exitFullscreenButtonLabel: 'Izklopi celozaslonski način', reuseSuccess: ':title uspešno uvožen iz središča H5P Hub.', noContentHeader: 'Ni ustrezne vsebine?', noContentSuggestion: 'Ustvarite svojo!', tutorials: 'Vodiči', contentSectionAll: 'Vsa deljena vsebina', popularContent: 'Priljubljena vsebina', allPopular: 'Vse priljubljene', newOnTheHub: 'Novo na H5P Hub', allNew: 'Vse novo', filterBy: 'Filtriraj po', filter: 'Filter', filters: { level: { dropdownLabel: 'Stopnja', dialogHeader: 'Izberi stopnjo izobrazbe', dialogButtonLabel: 'Filtriraj po stopnji izobrazbe', }, language: { dropdownLabel: 'Jezik', dialogHeader: 'Izberi jezik', dialogButtonLabel: 'Filtriraj po jeziku', searchPlaceholder: 'Vnos jezika za iskanje', }, reviewed: { dropdownLabel: 'Pregledano', dialogHeader: 'Pregledana vsebina', dialogButtonLabel: 'Filtriraj pregledano', optionLabel: 'Prikaži samo pregledano vsebino', }, contentTypes: { dropdownLabel: 'Tip vsebine', dialogHeader: 'Izberi tip vsebine', dialogButtonLabel: 'Filtriraj po tipu vsebine', searchPlaceholder: 'Vnos tipa vsebine za iskanje', }, disciplines: { dropdownLabel: 'Področje', dialogHeader: 'Izberi področje', dialogButtonLabel: 'Filtriraj po področju', searchPlaceholder: 'Vnos področja za iskanje', }, licenses: { dropdownLabel: 'Licence', dialogHeader: 'Izberi licenco uporabe', dialogButtonLabel: 'Filtriraj po licenci', options: { modified: 'Dovoljene spremembe', commercial: 'Dovoljena komercialna raba' }, }, }, clearFilters: 'Počisti vse filtre', contentSearchFieldPlaceholder: 'Iskanje vsebine', loadingContentTitle: 'Nalagamo vsebino ...', loadingContentSubtitle: 'Prosim, počakajte', by: 'Od', dropdownButton: 'Odpri spustni seznam', paginationNavigation: 'Navigacija po straneh', page: 'Stran', currentPage: 'Trenutna stran', nextPage: 'Pojdi na naslednjo stran', previousPage: 'Pojdi na prejšnjo stran', contentPreviewButtonLabel: 'Predogled', contentDownloadButtonLabel: 'Pridobi vsebino', reuseContentTabLabel: 'Pridobite vsebino v skupni rabi', contentPublisherPanelHeader: 'Informacije o založniku', noContentFoundDesc: 'Ni vsebine, ki bi ustrezala iskalnim kriterijem.', h5pType: 'Tip H5P', level: 'Stopnja', size: 'Velikost', failedFetchingData: 'Pridobivanje podatkov ni uspelo', filterErrorMessage: 'Nekaj je šlo narobe. Ponovno naložite stran.', in: 'v', navigateToParent: 'Pomakni se do starša', a11yTitleShowLabel: 'Pokaži za bralnik zaslona', a11yTitleHideLabel: 'Skrij za bralnik zaslona', }; PK*\f…>>(h5plib/v127/joubel/editor/language/cs.jsnu[H5PEditor.language.core = { missingTranslation: '[Chybí překlad :key]', loading: 'Načítám, čekejte prosím ...', selectLibrary: 'Vyberte knihovnu, kterou chcete pro svůj obsah použít.', unknownFieldPath: 'Nelze najít ":path".', notImageField: '":path" není obrázek.', notImageOrDimensionsField: '":path" není obrázku nebo pole dimenze.', requiredProperty: ' :property je povinné a musí mít hodnotu.', onlyNumbers: ' :property hodnota může obsahovat pouze čísla.', illegalDecimalNumber: ':property může obsahovat pouze čísla s maximálně :decimals desetinných míst.', exceedsMax: ' :property hodnota překračuje maximum :max.', listExceedsMax: 'Seznam překračuje maximum :max položek.', belowMin: ' :property hodnota je pod minimem :min.', listBelowMin: 'Seznam musí obsahovat alespoň :min položek, aby obsah fungoval správně.', outOfStep: ' :property hodnotu lze změnit pouze v krocích :step.', add: 'Přidat', addFile: 'Přidat soubor', removeFile: 'Odstranit soubor', confirmRemoval: 'Opravdu chcete odstranit :type?', removeImage: 'Odstranit obrázek', confirmImageRemoval: 'Tím se odstraní váš obrázek. Opravdu chcete pokračovat?', changeFile: 'Změnit soubor', changeLibrary: 'Změnit typ obsahu?', semanticsError: 'Sémantická chyba: :error', missingProperty: 'Poli :index chybí jeho :property vlastnost.', expandCollapse: 'Rozbalit/Sbalit', addEntity: 'Přidat :entity', tooLong: 'Hodnota pole je příliš dlouhá, měla by obsahovat :max znaků nebo méně.', invalidFormat: 'Hodnota pole obsahuje neplatný formát nebo znaky, které jsou zakázány.', confirmChangeLibrary: 'Tím ztratíte veškerou práci s aktuálním typem obsahu. Opravdu chcete změnit typ obsahu?', commonFields: 'Přepisy a překlady textu', commonFieldsDescription: 'Zde můžete upravovat nastavení nebo překládat texty použité v tomto obsahu.', uploading: 'Nahrávám, počkejte prosím...', noFollow: 'Nelze sledovat pole ":path".', editCopyright: 'Upravit autorská práva', close: 'Zavřít', tutorial: 'Tutoriál', editMode: 'Režim úprav', listLabel: 'Seznam', uploadError: 'Chyba nahrávání souboru', fileToLarge: 'Soubor, který se pokoušíte nahrát, může být příliš velký.', unknownFileUploadError: 'Chyba při nahrávání neznámého souboru', noSemantics: 'Chyba, nelze načíst formulář typu obsahu.', editImage: 'Upravit obrázek', saveLabel: 'Uložit', cancelLabel: 'Zrušit', resetToOriginalLabel: 'Obnovit původní', loadingImageEditor: 'Načítání editoru obrázků, počkejte prosím...', selectFiletoUpload: 'Vyberte soubor, který chcete nahrát', or: 'nebo', enterAudioUrl: 'Zadejte adresu URL zdroje zvuku', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Vložte odkaz nebo jinou adresu URL zdroje zvuku', enterVideoTitle: 'Vložte odkaz na YouTube nebo jinou adresu URL zdroje videa', uploadAudioTitle: 'Nahrajte zvukový soubor', uploadVideoTitle: 'Nahrajte soubor videa', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Vložit', cancel: 'Zrušit', height: 'výška', width: 'šířka', textField: 'textové pole', numberField: 'numerické pole', orderItemUp: 'Seřaďte položky vzestupně', orderItemDown: 'Seřaďte položky sestupně', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Odstranit položku', hubPanelLabel: 'Vyberte typ obsahu', importantInstructions: 'Důležité pokyny', showImportantInstructions: 'Zobrazit pokyny', hideImportantInstructions: 'Skrýt důležité pokyny', hide: 'Skrýt', example: 'Příklad', createContentTabLabel: 'Vytvořit obsah', uploadTabLabel: 'Nahrát', uploadPlaceholder: 'Nebyl vybrán soubor', uploadInstructionsTitle: 'Nahrát H5P soubor.', uploadInstructionsContent: 'Můžete začít příklady z H5P.org.', uploadFileButtonLabel: 'Nahrát soubor', uploadFileButtonChangeLabel: 'Změnit soubor', uploadingThrobber: 'Nyní se nahrává...', uploadSuccess: ':title byl úspěšně nahrán!', unableToInterpretError: 'Odpověď nelze interpretovat.', unableToInterpretSolution: 'Zkontrolujte prosím svůj protokol chyb.', h5pFileWrongExtensionTitle: 'Vybraný soubor nelze nahrát', h5pFileWrongExtensionContent: 'Povoleny jsou pouze soubory s příponou .h5p.', h5pFileValidationFailedTitle: 'Nelze ověřit soubor H5P.', h5pFileValidationFailedContent: 'Ujistěte se, že nahraný H5P obsahuje platný obsah H5P. H5P soubory obsahující pouze knihovny by měly být nahrány přes stránku Knihovny H5P.', h5pFileUploadServerErrorTitle: 'The H5P file could not be uploaded', h5pFileUploadServerErrorContent: 'Došlo k neočekávané chybě. Zkontrolujte protokol chyb serveru kde je více informací.', contentTypeSectionAll: 'Všechny typy obsahu', searchResults: 'Search Results', contentTypeSearchFieldPlaceholder: 'Vyhledejte typy obsahu', contentTypeInstallButtonLabel: 'Instalovat', contentTypeInstallingButtonLabel: 'Instalování', contentTypeUseButtonLabel: 'Použít', contentTypeDetailButtonLabel: 'Detaily', contentTypeUpdateButtonLabel: 'Aktualizovat', contentTypeUpdatingButtonLabel: 'Aktualizování', contentTypeGetButtonLabel: 'Získat', contentTypeBackButtonLabel: 'Zpět', contentTypeIconAltText: 'Ikona', contentTypeInstallSuccess: ':contentType úspěšně nainstalován!', contentTypeUpdateSuccess: ':contentType úspěšně aktualizován!', contentTypeInstallError: ':contentType nelze nainstalovat. Obraťte se na správce.', contentTypeLicensePanelTitle: 'Licence', contentTypeDemoButtonLabel: 'Ukázka obsahu', numResults: ':num výsledky', show: 'Zobrazit', recentlyUsedFirst: 'Naposledy použité ', popularFirst: 'Nejpopulárnější', newestFirst: 'Nejnovější', aToZ: 'A to Z', noResultsFound: 'Nebyly nalezeny žádné výsledky', noResultsFoundDesc: 'Vyhledávacím kritériím neodpovídá žádný typ obsahu.', readMore: 'Přečíst více', readLess: 'Přečíst méně', contentTypeOwner: 'Podle :owner', contentTypeUnsupportedApiVersionTitle: 'Tento typ obsahu vyžaduje novější základní verzi', contentTypeUnsupportedApiVersionContent: 'Obraťte se na správce systému, který vám poskytne potřebné aktualizace', contentTypeUpdateAvailable: 'Aktualizace je k dispozici', contentTypeRestricted: 'Zakázaný typ obsahu', contentTypeRestrictedDesc: 'Použití tohoto typu obsahu bylo omezeno správcem.', contentTypeNotInstalled: 'Typ obsahu není nainstalován', contentTypeNotInstalledDesc: 'Nemáte oprávnění k instalaci typů obsahu.', theContentType: 'typ obsahu', currentMenuSelected: 'aktuální výběr', errorCommunicatingHubTitle: 'Nelze komunikovat s hubem.', errorCommunicatingHubContent: 'Nastala chyba. Prosím zkuste to znov.', warningNoContentTypesInstalled: 'YNemáte nainstalován žádný typ obsahu.', warningChangeBrowsingToSeeResults: 'Kliknutím na Vše získáte seznam všech typů obsahu, které můžete nainstalovat.', warningUpdateAvailableTitle: 'K dispozici je nová verze :contentType .', warningUpdateAvailableBody: 'Aktualizace na nejnovější verzi pro lepší zážitek.', licenseDescription: 'Některé funkce této licence jsou uvedeny níže. Kliknutím na ikonu informace výše zobrazíte původní text licence.', licenseModalTitle: 'Detail licences', licenseModalSubtitle: 'Vyberte licenci pro zobrazení informací o správném použití', licenseUnspecified: 'Nespecifikováno', licenseCanUseCommercially: 'Lze použít komerčně', licenseCanModify: 'Lze upravit', licenseCanDistribute: 'Může se šířit', licenseCanSublicense: 'Může se sublicencovat', licenseCanHoldLiable: 'Může se nést odpovědnost', licenseCannotHoldLiable: 'Nelze nést odpovědnost', licenseMustIncludeCopyright: 'Musí zahrnovat autorská práva', licenseMustIncludeLicense: 'Musí obsahovat licenci', licenseFetchDetailsFailed: 'Nepodařilo se načíst podrobnosti o licenci', imageLightboxTitle: 'Obrázky', imageLightBoxProgress: ':num ze :total', nextImage: 'Další obrázek', previousImage: 'Předchozí obrázek', screenshots: 'Ukázky', reloadButtonLabel: 'Znovu načíst', videoQuality: 'Popisek kvality videa', videoQualityDescription: 'Tento popisek pomáhá uživateli zjistit aktuální kvalitu videa. Např. 1080p, 720p, HD nebo Mobile', videoQualityDefaultLabel: 'Kvalita :index', noContentTypesAvailable: 'Nejsou k dispozici žádné typy obsahu', noContentTypesAvailableDesc: 'Váš web má potíže s připojením k H5P.org a se seznamem dostupných typů obsahu.', contentTypeCacheOutdated: 'Seznam typů obsahu je zastaralý', contentTypeCacheOutdatedDesc: 'Váš web má potíže s připojením k serveru H5P.org, aby mohl zkontrolovat aktualizace typu obsahu. Možná nebudete moci aktualizovat nebo instalovat nové typy obsahu.', tryAgain: 'Zkusit znovu', getHelp: 'Získat pomoc', untitled: 'Nepojmenovaná :libraryTitle', title: 'Název', metadata: 'Metadata', addTitle: 'Přidat název', usedForSearchingReportsAndCopyrightInformation: 'Používá se pro vyhledávání, zprávy a informace o autorských právech', metadataSharingAndLicensingInfo: 'Metadata (informace o sdílení a licenci)', fillInTheFieldsBelow: 'Vyplnit v poli níže', saveMetadata: 'Uložit metadata', addAuthor: 'Uložit autora', confirmRemoveAuthor: 'Opravdu chcete tohoto autora odebrat?', addNewChange: 'Přidat novou změnu', confirmDeleteChangeLog: 'Opravdu chcete odstranit tuto položku protokolu změn?', changelogDescription: 'Některé licence vyžadují, aby změny provedené v původním díle nebo derivátech byly zaznamenány a zobrazeny. Můžete zde protokolovat své změny z licenčních důvodů nebo jen proto, abyste sami a ostatní mohli sledovat změny provedené v tomto obsahu.', logThisChange: 'Protokolovat tuto změnu', newChangeHasBeenLogged: 'Byla zaznamenána nová změna', loggedChanges: 'Protokolované změny', noChangesHaveBeenLogged: 'Nebyly zaznamenány žádné změny', errorHeader: 'Nastala chyba', errorCalculatingMaxScore: 'Nelze vypočítat maximální skóre pro tento obsah. Předpokládá se, že maximální skóre je 0. Pokud to není správné, kontaktujte svého správce.', maxScoreSemanticsMissing: 'Nelze najít očekávanou sémantiku v obsahu.', copyButton: 'Kopírovat', copiedButton: 'Zkopírováno', pasteButton: 'Vložit', pasteAndReplaceButton: 'Vložit a nahradit', pasteContent: 'Nahradit obsah', confirmPasteContent: 'Tímto způsobem nahradíte aktuální obsah obsahem ze své schránky. Aktuální obsah bude ztracen. Opravdu chcete pokračovat?', confirmPasteButtonText: 'Nahradit obsah', copyToClipboard: 'Zkopírovat obsah H5P do schránky', copiedToClipboard: 'Obsah je zkopírován do schránky', pasteFromClipboard: 'Vložit obsah H5P ze schránky', pasteAndReplaceFromClipboard: 'Nahradit stávající obsah obsahem H5P ze schránky', pasteNoContent: 'Ve schránce není žádný obsah H5P', pasteError: 'Nelze vložit ze schránky', pasteContentNotSupported: 'Obsah schránky H5P není v tomto kontextu podporován', pasteContentRestricted: 'Obsah schránky byl na tomto webu omezen', pasteTooOld: 'Obsah ve schránce H5P je nižší verze (: clip), než co je v tomto kontextu podporováno (:local), pokud je to možné, zkuste aktualizovat obsah, který chcete vložit, zkopírujte znovu a zkuste jej vložit sem.', pasteTooNew: 'Obsah ve schránce H5P má vyšší verzi (: clip), než je v tomto kontextu podporováno (:local), pokud je to možné, zkuste nejprve aktualizovat tento obsah a potom zkuste vložit obsah sem znovu.', ok: 'OK', avTablistLabel: 'Vložit pomocí', tabTitleBasicFileUpload: 'Nahrát souboru', tabTitleInputLinkURL: 'Odkaz/URL', errorTooHighVersion: 'Parametry obsahují %used, zatímco podporovány jsou pouze %supported nebo starší.', errorNotSupported: 'Parametry obsahují %used, které není podporován.', errorParamsBroken: 'Parametry jsou poškozené.', libraryMissing: 'Chybí požadovaná knihovna %lib.', scriptMissing: 'Skript aktualizace nelze načíst %lib.', language: 'Jazyk', noLanguagesSupported: 'Nejsou podporovány žádné jazyky', changeLanguage: 'Změnit jazyk na :language?', thisWillPotentially: 'Tím se potenciálně resetuje veškerý text a překlady. Toto nemůžete vrátit zpět. Samotný obsah se nezmění. Chcete pokračovat?', notAllTextsChanged: 'Ne všechny texty byly změněny, pouze částečné pokrytí :language.', contributeTranslations: 'Pokud chcete dokončit překlad pro :language, můžete se dozvědět o přispívání překladů do H5P', unknownLibrary: "Bohužel vybraný typ obsahu '%lib' není v tomto systému nainstalován.", proceedButtonLabel: 'Pokračovat k uložení', enterFullscreenButtonLabel: 'Přejít na celou obrazovku', exitFullscreenButtonLabel: 'Ukončit celou obrazovku', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', }; PK*\qQQ(h5plib/v127/joubel/editor/language/el.jsnu[H5PEditor.language.core = { missingTranslation: '[Λείπει μετάφραση :key]', loading: 'Φόρτωση, παρακαλούμε περιμένετε...', selectLibrary: 'Επιλέξτε τη βιβλιοθήκη την οποία θέλετε να χρησιμοποιήσετε για το περιεχόμενό σας.', unknownFieldPath: 'Δεν είναι δυνατή η εύρεση του ":path".', notImageField: 'Το ":path" δεν είναι εικόνα.', notImageOrDimensionsField: 'Το ":path" δεν είναι εικόνα ή πεδίο διαστάσεων.', requiredProperty: 'Η ιδιότητα :property απαιτείται, και πρέπει να έχει μια τιμή.', onlyNumbers: 'Η τιμή της ιδιότητας :property μπορεί να περιέχει μόνο αριθμούς.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: 'Η τιμή της ιδιότητας :property υπερβαίνει το μέγιστο :max.', listExceedsMax: 'Ο κατάλογος υπερβαίνει το μέγιστο των :max στοιχείων.', belowMin: 'Η τιμή της ιδιότητας :property είναι μικρότερη από το ελάχιστο :min.', listBelowMin: 'Η λίστα χρειάζεται τουλάχιστον :min στοιχεία για να λειτουργεί σωστά το περιεχόμενο.', outOfStep: 'Η τιμή της ιδιότητας :property μπορεί να αλλάξει μόνο σε :step βήματα.', add: 'Προσθήκη', addFile: 'Προσθήκη αρχείου', removeFile: 'Αφαίρεση αρχείου', confirmRemoval: 'Είστε σίγουροι οτι επιθυμείτε να αφαιρέσετε το :type;', removeImage: 'Αφαίρεση εικόνας', confirmImageRemoval: 'Αυτή η ενέργεια θα αφαιρέσει την εικόνα σας. Είστε σίγουροι οτι θέλετε να προχωρήσετε;', changeFile: 'Αλλαγή αρχείου', changeLibrary: 'Αλλαγή τύπου περιεχομένου;', semanticsError: 'Σφάλμα σημασιολογίας: :error', missingProperty: 'Το πεδίο :index υπολείπεται της ιδιότητας :property.', expandCollapse: 'Ανάπτυξη/Σύμπτυξη', addEntity: 'Προσθήκη :entity', tooLong: 'Η τιμή του πεδίου είναι πολύ μεγάλη, πρέπει να περιέχει :max γράμματα ή λιγότερα.', invalidFormat: 'Η τιμή του πεδίου περιέχει μια μη έγκυρη μορφή ή χαρακτήρες οι οποίοι απαγορεύονται.', confirmChangeLibrary: 'Κάνοντας αυτό θα χάσετε όλη την εργασία που έχει γίνει με τον τρέχοντα τύπο περιεχομένου. Είστε βέβαιοι ότι θέλετε να αλλάξετε τύπο περιεχομένου;', commonFields: 'Παραλλαγές κειμένου και μεταφράσεις', commonFieldsDescription: 'Εδώ μπορείτε να επεξεργαστείτε ρυθμίσεις ή να μεταφράσετε κείμενα τα οποία χρησιμοποιούνται σε αυτό το περιεχόμενο.', uploading: 'Μεταφόρτωση, παρακαλούμε περιμένετε...', noFollow: 'Δεν είναι δυνατή η παρακολούθηση του πεδίου ":path".', editCopyright: 'Επεξεργασία πνευματικών δικαιωμάτων', close: 'Κλείσιμο', tutorial: 'Μάθημα', editMode: 'Λειτουργία επεξεργασίας', listLabel: 'Λίστα', uploadError: 'Σφάλμα Μεταφόρτωσης Αρχείου', fileToLarge: 'Το αρχείο το οποίο προσπαθείτε να μεταφορτώσετε, ενδέχεται να είναι πολύ μεγάλο.', unknownFileUploadError: 'Άγνωστο σφάλμα μεταφόρτωσης αρχείου', noSemantics: 'Σφάλμα, δεν ήταν δυνατή η φόρτωση της φόρμας τύπου περιεχομένου.', editImage: 'Επεξεργασία εικόνας', saveLabel: 'Αποθήκευση', cancelLabel: 'ακύρωση', resetToOriginalLabel: 'Επαναφορά στο πρωτότυπο', loadingImageEditor: 'Φόρτωση επεξεργαστή εικόνας, παρακαλούμε περιμένετε...', selectFiletoUpload: 'Επιλέξτε αρχείο προς μεταφόρτωση', or: 'ή', enterAudioUrl: 'Εισαγάγετε διεύθυνση URL ήχου', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Επικολλήστε σύνδεσμο ή άλλη διεύθυνση URL ήχου', enterVideoTitle: 'Επικολλήστε σύνδεσμο YouTube ή άλλη διεύθυνση URL βίντεο', uploadAudioTitle: 'Μεταφορτώστε αρχείο ήχου', uploadVideoTitle: 'Μεταφορτώστε αρχείο video', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Εισαγωγή', cancel: 'Ακύρωση', height: 'ύψος', width: 'πλάτος', textField: 'πεδίο κειμένου', numberField: 'αριθμητικό πεδίο', orderItemUp: 'Ταξινόμηση στοιχείου προς τα επάνω', orderItemDown: 'Ταξινόμηση στοιχείου προς τα κάτω', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Αφαίρεση στοιχείου', hubPanelLabel: 'Επιλέξτε τύπο περιεχομένου', importantInstructions: 'Σημαντικές οδηγίες', showImportantInstructions: 'Εμφάνιση οδηγιών', hideImportantInstructions: 'Απόκρυψη σημαντικών οδηγιών', hide: 'Απόκρυψη', example: 'Παράδειγμα', createContentTabLabel: 'Δημιουργία Περιεχομένου', uploadTabLabel: 'Μεταφόρτωση', uploadPlaceholder: 'Δεν έχει επιλεγεί αρχείο', uploadInstructionsTitle: 'Μεταφορτώστε ένα αρχείο H5P.', uploadInstructionsContent: 'Μπορείτε να ξεκινήσετε με παραδείγματα από το H5P.org.', uploadFileButtonLabel: 'Μεταφόρτωση αρχείου', uploadFileButtonChangeLabel: 'Αλλαγή αρχείου', uploadingThrobber: 'Γίνεται μεταφόρτωση...', uploadSuccess: ':title was successfully uploaded!', unableToInterpretError: 'Unable to interpret response.', unableToInterpretSolution: 'Please check your error log.', h5pFileWrongExtensionTitle: 'Δεν ήταν δυνατή η μεταφόρτωση του επιλεγμένου αρχείου', h5pFileWrongExtensionContent: 'Μόνο αρχεία με επέκταση .h5p επιτρέπονται.', h5pFileValidationFailedTitle: 'Δεν ήταν δυνατή η επικύρωση του αρχείου H5P.', h5pFileValidationFailedContent: 'Βεβαιωθείτε ότι το φορτωμένο H5P περιέχει έγκυρο περιεχόμενο H5P. Τα αρχεία H5P τα οποία περιέχουν μόνο βιβλιοθήκες, θα πρέπει να μεταφορτωθούν μέσω της σελίδας Βιβλιοθήκες H5P.', h5pFileUploadServerErrorTitle: 'Δεν ήταν δυνατή η μεταφόρτωση του αρχείου H5P', h5pFileUploadServerErrorContent: 'Προέκυψε ένα μη αναμενόμενο σφάλμα. Ελέγξτε το αρχείο σφαλμάτων του διακομιστή σας για περισσότερες λεπτομέρειες.', contentTypeSectionAll: 'All Content Types', searchResults: 'Search Results', contentTypeSearchFieldPlaceholder: 'Αναζητήστε Τύπους Περιεχομένου', contentTypeInstallButtonLabel: 'Εγκατάσταση', contentTypeInstallingButtonLabel: 'Εγκατάσταση', contentTypeUseButtonLabel: 'Χρήση', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'Ενημέρωση', contentTypeUpdatingButtonLabel: 'Ενημέρωση', contentTypeGetButtonLabel: 'Λήψη', contentTypeBackButtonLabel: 'Πίσω', contentTypeIconAltText: 'Εικονίδιο', contentTypeInstallSuccess: ':contentType εγκαταστάθηκε με επιτυχία!', contentTypeUpdateSuccess: ':contentType ενημερώθηκε με επιτυχία!', contentTypeInstallError: ':contentType δεν ήταν δυνατόν να εγκατασταθεί. Επικοινωνήστε με το διαχειριστή σας.', contentTypeLicensePanelTitle: 'Άδεια', contentTypeDemoButtonLabel: 'Δείγμα Περιεχομένου', numResults: ':num results', show: 'Show', recentlyUsedFirst: 'Recently Used First', popularFirst: 'Popular First', newestFirst: 'Newest First', aToZ: 'A to Z', noResultsFound: 'No results found', noResultsFoundDesc: 'There is no content type that matches your search criteria.', readMore: 'Διαβάστε περισσότερα', readLess: 'Διαβάστε λιγότερα', contentTypeOwner: 'Από :owner', contentTypeUnsupportedApiVersionTitle: 'Αυτός ο τύπος περιεχομένου απαιτεί νεότερη έκδοση', contentTypeUnsupportedApiVersionContent: 'Επικοινωνήστε με το διαχειριστή του συστήματός σας, για την παροχή των απαραίτητων ενημερώσεων', contentTypeUpdateAvailable: 'Υπάρχει διαθέσιμη ενημέρωση', contentTypeRestricted: 'Περιορισμένος τύπος περιεχομένου', contentTypeRestrictedDesc: 'Η χρήση αυτού του τύπου περιεχομένου έχει περιοριστεί από τον διαχειριστή.', contentTypeNotInstalled: 'Ο τύπος περιεχομένου δεν εγκαταστάθηκε', contentTypeNotInstalledDesc: 'Δεν έχετε άδεια για την εγκατάσταση τύπων περιεχομένου.', theContentType: 'τον τύπο περιεχομένου', currentMenuSelected: 'τρέχουσα επιλογή', errorCommunicatingHubTitle: 'Δεν είναι σε θέση να επικοινωνήσει με το διανομέα.', errorCommunicatingHubContent: 'Παρουσιάστηκε σφάλμα. Παρακαλούμε προσπαθήστε ξανα.', warningNoContentTypesInstalled: 'Δεν έχετε εγκατεστημένους τύπους περιεχομένου.', warningChangeBrowsingToSeeResults: 'Κάντε κλικ στο κουμπί Όλα για να λάβετε τη λίστα με όλους τους τύπους περιεχομένου τους οποίους μπορείτε να εγκαταστήσετε.', warningUpdateAvailableTitle: 'Μια νέα έκδοση του :contentType είναι διαθέσιμη.', warningUpdateAvailableBody: 'Ενημερώστε στην τελευταία έκδοση για βελτιωμένη εμπειρία χρήσης.', licenseDescription: 'Ορισμένα από τα χαρακτηριστικά αυτής της άδειας αναφέρονται παρακάτω. Κάντε κλικ στο παραπάνω εικονίδιο πληροφοριών για να διαβάσετε το πρωτότυπο κείμενο της άδειας χρήσης.', licenseModalTitle: 'Λεπτομέρειες Άδειας Χρήσης', licenseModalSubtitle: 'Επιλέξτε μια άδεια χρήσης για να δείτε πληροφορίες σχετικά με τη σωστή χρήση', licenseUnspecified: 'Απροσδιόριστο', licenseCanUseCommercially: 'Μπορεί να χρησιμοποιηθεί για εμπορικό σκοπό', licenseCanModify: 'Μπορεί να τροποποιηθεί', licenseCanDistribute: 'Μπορεί να διανείμει', licenseCanSublicense: 'Μπορεί να χορηγήσει περαιτέρω άδεια', licenseCanHoldLiable: 'Μπορεί να θεωρηθεί υπεύθυνος', licenseCannotHoldLiable: 'Δεν μπορεί να θεωρηθεί υπεύθυνος', licenseMustIncludeCopyright: 'Πρέπει να περιλαμβάνει δικαιώματα πνευματικής ιδιοκτησίας', licenseMustIncludeLicense: 'Πρέπει να περιλαμβάνει άδεια', licenseFetchDetailsFailed: 'Αποτυχία λήψης λεπτομερειών άδειας', imageLightboxTitle: 'Εικόνες', imageLightBoxProgress: ':num από :total', nextImage: 'Επόμενη εικόνα', previousImage: 'Προηγούμενη εικόνα', screenshots: 'Στιγμιότυπα', reloadButtonLabel: 'Επαναφόρτωση', videoQuality: 'Ετικέτα ποιότητας βίντεο', videoQualityDescription: 'Αυτή η ετικέτα βοηθά τον χρήστη να αναγνωρίσει την τρέχουσα ποιότητα του βίντεο. Για παράδειγμα 1080p, 720p, HD ή Mobile', videoQualityDefaultLabel: 'Ποιότητα :index', noContentTypesAvailable: 'No content types are available', noContentTypesAvailableDesc: 'Your site is having difficulties connecting to H5P.org and listing the available content types.', contentTypeCacheOutdated: 'Content type list outdated', contentTypeCacheOutdatedDesc: 'Your site is having difficulties connecting to H5P.org to check for content type updates. You may not be able to update or install new content types.', tryAgain: 'Try again', getHelp: 'Get help', untitled: 'Untitled :libraryTitle', title: 'Title', metadata: 'Metadata', addTitle: 'Add title', usedForSearchingReportsAndCopyrightInformation: 'Used for searching, reports and copyright information', metadataSharingAndLicensingInfo: 'Metadata (sharing and licensing info)', fillInTheFieldsBelow: 'Fill in the fields below', saveMetadata: 'Save metadata', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Add new change', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Log this change', newChangeHasBeenLogged: 'New change has been logged', loggedChanges: 'Logged changes', noChangesHaveBeenLogged: 'No changes have been logged', errorHeader: 'An error occured', errorCalculatingMaxScore: 'Could not calculate the max score for this content. The max score is assumed to be 0. Contact your administrator if this isn’t correct.', maxScoreSemanticsMissing: 'Could not find the expected semantics in the content.', copyButton: 'Copy', copiedButton: 'Copied', pasteButton: 'Paste', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Copy H5P content to the clipboard', copiedToClipboard: 'Content is copied to the clipboard', pasteFromClipboard: 'Paste H5P content from the clipboard', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'No H5P content on the clipboard', pasteError: 'Cannot paste from clipboard', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: "Unfortunately, the selected content type '%lib' isn't installed on this system.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\D AA+h5plib/v127/joubel/editor/language/es-mx.jsnu[H5PEditor.language.core = { missingTranslation: '[Falta la traducción :key]', loading: 'Cargando, por favor espera...', selectLibrary: 'Selecciona la librería que quieres usar con tu contenido.', unknownFieldPath: 'No se puede encontrar ":path".', notImageField: '":path" no es una imagen.', notImageOrDimensionsField: '":path" no es una imagen o un campo de dimensiones.', requiredProperty: 'La :property es requerida y debe tener un valor.', onlyNumbers: 'El valor de :property solo puede contener números.', illegalDecimalNumber: ':property solamente puede contener números con un máximo de :decimals decimales.', exceedsMax: 'El valor de :property excede el máximo de :max.', listExceedsMax: 'La lista excede el máximo de :max elementos.', belowMin: 'El valor de :property excede el mínimo de :min.', listBelowMin: 'La lista necesita al menos :min elementos para que el contenido funcione adecuadamente.', outOfStep: 'El valor de :property solo puede ser cambiado en pasos de :step.', add: 'Añadir', addFile: 'Añadir archivo', removeFile: 'Eliminar archivo', confirmRemoval: '¿Estás seguro que quieres eliminar este :type?', removeImage: 'Eliminar imagen', confirmImageRemoval: 'Esto eliminará la imagen. ¿Seguro que desea continuar?', changeFile: 'Cambiar archivo', changeLibrary: 'Cambiar el tipo de contenido', semanticsError: 'Error en semántica: :error', missingProperty: 'El campo :index no contiene la propiedad :property.', expandCollapse: 'Expandir/Colapsar', addEntity: 'Añadir :entity', tooLong: 'El valor del campo es demasiado largo, debería contener un máximo de :max letras.', invalidFormat: 'El valor del campo contiene un formato no válido o caracteres prohibidos.', confirmChangeLibrary: 'Al hacer esto perderás todo el trabajo realizado con el tipo de contenido actual. ¿Estás seguro de que quieres cambiar el tipo de contenido?', commonFields: 'Parámetros y textos', commonFieldsDescription: 'Aquí puedes editar parámetros o traducir textos utilizados en este contenido.', uploading: 'Subiendo, por favor espera...', noFollow: 'No se puede seguir el campo ":path".', editCopyright: 'Editar copyright', close: 'Cerrar', tutorial: 'Tutorial', editMode: 'Modo de edición', listLabel: 'Lista', uploadError: 'Error en la subida del archivo', fileToLarge: 'El archivo que intenta subir es demasiado grande.', unknownFileUploadError: 'Error de carga de archivo desconocido', noSemantics: 'Error, no se ha podido cargar el formato del tipo de contenido.', editImage: 'Editar imagen', saveLabel: 'Guardar', cancelLabel: 'Cancelar', resetToOriginalLabel: 'Restablecer el original', loadingImageEditor: 'Cargando editor de imagen, por favor espere...', selectFiletoUpload: 'Seleccione el archivo a subir', or: 'o', enterAudioUrl: 'Introduzca la URL del origen del audio', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Pegue el link u otra fuente de audio', enterVideoTitle: 'Peque el link de Youtube o la URL de la fuente del video', uploadAudioTitle: 'Subir archivo de audio', uploadVideoTitle: 'Subir archivo de video', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Insertar', cancel: 'Cancelar', height: 'altura', width: 'ancho', textField: 'campo de texto', numberField: 'campo numérico', orderItemUp: 'Ordenar elemento arriba', orderItemDown: 'Ordenar elemento abajo', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Eliminar elemento', hubPanelLabel: 'Seleccionar tipo de contenido', importantInstructions: 'Instrucciones importantes', showImportantInstructions: 'Mostrar instrucciones', hideImportantInstructions: 'Ocultar instrucciones importantes', hide: 'Ocultar', example: 'Ejemplo', createContentTabLabel: 'Crear Contenido', uploadTabLabel: 'Subir', uploadPlaceholder: 'Ningún archivo seleccionado', uploadInstructionsTitle: 'Subir un archivo H5P.', uploadInstructionsContent: 'Usted puede comenzar con ejemplos de H5P.org.', uploadFileButtonLabel: 'Subir un archivo', uploadFileButtonChangeLabel: 'Cambiar archivo', uploadingThrobber: 'Subiendo ahora...', uploadSuccess: ':title se subió correctamente!', unableToInterpretError: 'No se puede interpretar la respuesta.', unableToInterpretSolution: 'Por favor revise su bitácora de errores.', h5pFileWrongExtensionTitle: 'El archivo elegido no se puede subir', h5pFileWrongExtensionContent: 'Solo se permiten archivos con la extensión .h5p.', h5pFileValidationFailedTitle: 'No se puede validar el archivo H5P.', h5pFileValidationFailedContent: 'Asegúrese de que el H5P cargado contiene contenido H5P válido. H5P Los archivos que contienen sólo bibliotecas deben cargarse a través de la página Bibliotecas H5P.', h5pFileUploadServerErrorTitle: 'El archivo H5P no se ha podido cargar', h5pFileUploadServerErrorContent: 'Ocurrió un error inesperado. Compruebe el registro de errores del servidor para obtener más detalles.', contentTypeSectionAll: 'Todos los tipos de contenidos', searchResults: 'Resultados de búsqueda', contentTypeSearchFieldPlaceholder: 'Buscar tipos de contenido', contentTypeInstallButtonLabel: 'Instalar', contentTypeInstallingButtonLabel: 'Instalando', contentTypeUseButtonLabel: 'Usar', contentTypeDetailButtonLabel: 'Detalles', contentTypeUpdateButtonLabel: 'Actualizar', contentTypeUpdatingButtonLabel: 'Actualizando', contentTypeGetButtonLabel: 'Obtener', contentTypeBackButtonLabel: 'Atrás', contentTypeIconAltText: 'Icono', contentTypeInstallSuccess: ':contentType instalado con éxito!', contentTypeUpdateSuccess: ':contentType actualizado con éxito!', contentTypeInstallError: ':contentType no puede ser instalado. Póngase en contacto con su administrador.', contentTypeLicensePanelTitle: 'Licencia', contentTypeDemoButtonLabel: 'Demo de Contenido', numResults: ':num resultados', show: 'Mostrar', recentlyUsedFirst: 'Usado recientemente Primero', popularFirst: 'Popular primero', newestFirst: 'Lo mas nuevo primero', aToZ: 'A a la Z', noResultsFound: 'No se han encontrado resultados', noResultsFoundDesc: 'No hay ningún tipo de contenido que coincida con sus criterios de búsqueda.', readMore: 'Leer más', readLess: 'Leer menos', contentTypeOwner: 'Por :owner', contentTypeUnsupportedApiVersionTitle: 'Este tipo de contenido requiere una nueva versión del core', contentTypeUnsupportedApiVersionContent: 'Póngase en contacto con el responsable del sistema para obtener las actualizaciones necesarias.', contentTypeUpdateAvailable: 'Actualización disponible', contentTypeRestricted: 'Tipo de contenido restringido', contentTypeRestrictedDesc: 'El uso de este tipo de contenido ha sido restringido por un administrador.', contentTypeNotInstalled: 'Tipo de contenido no instalado', contentTypeNotInstalledDesc: 'No tiene permiso para instalar tipos de contenido.', theContentType: 'el tipo de contenido', currentMenuSelected: 'selección actual', errorCommunicatingHubTitle: 'No se puede comunicar con el hub.', errorCommunicatingHubContent: 'Ha ocurrido un error. Por favor, inténtelo de nuevo.', warningNoContentTypesInstalled: 'No tiene ningún tipo de contenido instalado.', warningChangeBrowsingToSeeResults: 'Click Todos para obtener la lista de todos los tipos de contenido que puede instalar .', warningUpdateAvailableTitle: 'Una nueva versión de :contentType está disponible.', warningUpdateAvailableBody: 'Actualización a la última versión para una experiencia mejorada.', licenseDescription: 'Algunas de las características de esta licencia se indican a continuación. Haga clic en el icono de información de arriba para leer el texto original de la licencia.', licenseModalTitle: 'Detalles de la Licencia', licenseModalSubtitle: 'Seleccione una licencia para ver información sobre el uso adecuado', licenseUnspecified: 'Sin especificar', licenseCanUseCommercially: 'Uso comercial', licenseCanModify: 'Se puede modificar', licenseCanDistribute: 'Se puede distribuir', licenseCanSublicense: 'Se puede sublicenciar', licenseCanHoldLiable: 'Se puede declarar responsable', licenseCannotHoldLiable: 'No puede declararse responsable', licenseMustIncludeCopyright: 'Debe incluir copyright', licenseMustIncludeLicense: 'Debe incluir licencia', licenseFetchDetailsFailed: 'Fallo en la obtención de los detalles de la licencia', imageLightboxTitle: 'Imágenes', imageLightBoxProgress: ':num de :total', nextImage: 'Siguiente imagen', previousImage: 'Imagen anterior ', screenshots: 'Capturas de pantalla', reloadButtonLabel: 'Recargar', videoQuality: 'Etiqueta de calidad de vídeo', videoQualityDescription: 'Esta etiqueta ayuda al usuario a identificar la calidad actual del vídeo. Por ejemplo, 1080p, 720p, HD o móvil', videoQualityDefaultLabel: 'Calidad :index', noContentTypesAvailable: 'No hay tipos de contenido disponibles', noContentTypesAvailableDesc: 'Su sitio tiene dificultades para conectarse a H5P.org y para listar los tipos de contenido disponibles.', contentTypeCacheOutdated: 'Lista de tipos de contenido obsoleta', contentTypeCacheOutdatedDesc: 'Su sitio tiene dificultades para conectarse a H5P.org para comprobar si hay actualizaciones del tipo de contenido. Es posible que no pueda actualizar o instalar nuevos tipos de contenido.', tryAgain: 'Inténtelo de nuevo', getHelp: 'Obtener ayuda', untitled: 'Sin título :libraryTitle', title: 'Título', metadata: 'Metadatos', addTitle: 'Añadir título', usedForSearchingReportsAndCopyrightInformation: 'Utilizado para búsquedas, informes e información de derechos de autor', metadataSharingAndLicensingInfo: 'Metadatos (información sobre uso compartido y licencias)', fillInTheFieldsBelow: 'Rellene los siguientes campos', saveMetadata: 'Guardar metadatos', addAuthor: 'Guardar autor', confirmRemoveAuthor: '¿Está seguro de que desea eliminar a este autor?', addNewChange: 'Añadir nuevo cambio', confirmDeleteChangeLog: '¿Está seguro de que desea borrar esta entrada del registro de cambios?', changelogDescription: 'Algunas licencias requieren que los cambios realizados en la obra original o los derivados se registren y visualicen. Usted puede registrar sus cambios aquí por razones de licencia o simplemente para permitirse a usted y a otros mantener un registro de los cambios realizados en este contenido.', logThisChange: 'Registrar este cambio', newChangeHasBeenLogged: 'Se ha registrado un nuevo cambio', loggedChanges: 'Cambios registrados', noChangesHaveBeenLogged: 'No se ha registrado ningún cambio', errorHeader: 'Se ha producido un error', errorCalculatingMaxScore: 'No se pudo calcular la puntuación máxima para este contenido. La puntuación máxima se supone que es 0. Póngse en contacto con su administrador si esto no es correcto.', maxScoreSemanticsMissing: 'No se pudo encontrar la semántica esperada en el contenido.', copyButton: 'Copiar', copiedButton: 'Copiado', pasteButton: 'Pegar', pasteAndReplaceButton: 'Pegar y Reemplazar', pasteContent: 'Reemplazar contenido', confirmPasteContent: 'Al hacer esto usted reemplazará el contenido actual con el contenido de su portapapeles. El contenido actual se perderá. ¿Está seguro de que quiere continuar?', confirmPasteButtonText: 'Reemplazar contenido', copyToClipboard: 'Copiar el contenido H5P al portapapeles', copiedToClipboard: 'El contenido se ha copiado al portapapeles', pasteFromClipboard: 'Pegar el contenido H5P del portapapeles', pasteAndReplaceFromClipboard: 'Reemplazar el contenido existente con contenido H5P del portapapeles', pasteNoContent: 'Ningún contenido H5P content en el portapapeles', pasteError: 'No se puede pegar desde el portapapeles', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insertar usando', tabTitleBasicFileUpload: 'Subir archivo', tabTitleInputLinkURL: 'Enlace/URL', errorTooHighVersion: 'Los parámetros contienen %used mientras que solamente %supported o anteriores están soportados.', errorNotSupported: 'Los parámetros contienen %used que no está soportado.', errorParamsBroken: 'Los parámetros están rotos.', libraryMissing: 'Falta la biblioteca requerida %lib.', scriptMissing: 'No se pudo cargar el script de actualizaciones para %lib.', language: 'Idioma', noLanguagesSupported: 'No hay idiomas soportados', changeLanguage: '¿Cambiar el idioma a :language?', thisWillPotentially: 'Esto potencialmente restablecerá todo el texto y las traducciones. No puedes deshacer esto. El contenido en sí no será cambiado. ¿Desea proceder?', notAllTextsChanged: 'No todos los textos fueron cambiados, solo hay una cobertura parcial para :language.', contributeTranslations: 'Si desea completar la traducción para :language, puede obtener información sobre contribuir con traducciones al H5P ', unknownLibrary: "Desafortunadamente, el tipo de contenido seleccionado '%lib' no está instalado en este sistema.", proceedButtonLabel: 'Proceder a guardar', enterFullscreenButtonLabel: 'Ir a pantalla completa', exitFullscreenButtonLabel: 'Salir de pantalla completa', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\6Y>>(h5plib/v127/joubel/editor/language/bs.jsnu[H5PEditor.language.core = { missingTranslation: '[Nedostaje prijevod :key]', loading: 'Učitava se, molimo sačekajte...', selectLibrary: 'Odaberite biblioteku koju želite koristiti za vaš sadržaj.', unknownFieldPath: 'Nije pronađeno ":path".', notImageField: '":path" nije slika.', notImageOrDimensionsField: '":path" nije slika niti polje sa dimenzijama.', requiredProperty: ':property polje mora biti popunjeno.', onlyNumbers: ':property polje može sadržavati samo brojeve.', illegalDecimalNumber: ':property can only contain numbers with max :decimals decimals.', exceedsMax: ':property sadržaj polja je veći od maksimuma :max.', listExceedsMax: 'Lista je veća od maksimuma :max.', belowMin: ':property sadržaj polja je manji od minimuma :min.', listBelowMin: 'Lista zahtjeva najmanje :min elemenata kako bi sadržaj funkcionirao pravilno.', outOfStep: ':property sadržaj može biti promijenjen samo u koracima :step.', add: 'Dodati', addFile: 'Dodati fajl', removeFile: 'Ukloniti fajl', confirmRemoval: 'Jeste li sigurni da želite ukloniti :type?', removeImage: 'Uklonite sliku', confirmImageRemoval: 'Ovo će ukloniti sliku. Želite li nastaviti dalje?', changeFile: 'Promjenite fajl', changeLibrary: 'Promjenite vrstu sadržaja?', semanticsError: 'Semantics error: :error', missingProperty: 'Polju :index nedostaje :property sadržaj.', expandCollapse: 'Raširiti/Sažeti', addEntity: 'Dodati :entity', tooLong: 'Sadržaj polja je previše dug. Može sadržavati :max slova ili manje od toga.', invalidFormat: 'Sadržaj polja sadrži netačan format ili znakove koji nisu dozvoljeni.', confirmChangeLibrary: 'Ako ovo uradite ovaj interaktivni sadržaj će biti izgubljen. Jeste li sigurni da želite promijeniti vrstu sadržaja?', commonFields: 'Prijevod teksta', commonFieldsDescription: 'Ovdje možete urediti podešavanja ili ili tekst korišten u ovoj sadržaju.', uploading: 'Učitava se, molimo sačekajte...', noFollow: 'Ne možemo slijediti polje ":path".', editCopyright: 'Urednite autorska prava', close: 'Zatvoriti', tutorial: 'Tutorijal', editMode: 'Mod za uređivanje', listLabel: 'Lista', uploadError: 'Greška kod uploada fajla', fileToLarge: 'Fajl koji pokušavate uploadovati je možda prevelik.', unknownFileUploadError: 'Nepoznata greška kod uploada fajla', noSemantics: 'Greška, nije moguće učitati formu za ovu vrstu sadržaja.', editImage: 'Uredite sliku', saveLabel: 'Sačuvati', cancelLabel: 'Otkazati', resetToOriginalLabel: 'Resetirati na original', loadingImageEditor: 'Učitava se editor za sliku, molimo sačekajte...', selectFiletoUpload: 'Označite fajl za upload', or: 'ili', enterAudioUrl: 'Unesite URL za audio fajl', enterVideoUrl: 'Enter video URL', enterAudioTitle: 'Prenesite link ili izvorni URL audio fajla', enterVideoTitle: 'Prenesite YouTube link ili izvorni URL audio fajla', uploadAudioTitle: 'Upload audio fajla', uploadVideoTitle: 'Upload video fajla', addVideoDescription: 'H5P supports all external video sources formatted as mp4, webm or ogv, like Vimeo Pro, and has support for YouTube and Panopto links.', insert: 'Ubaciti', cancel: 'Otkazati', height: 'visina', width: 'širina', textField: 'polje za tekst', numberField: 'polje za broj', orderItemUp: 'Uredite elemente ka gore', orderItemDown: 'Uredite elemente ka dolje', expandAllContent: 'Expand all content', collapseAllContent: 'Collapse all content', removeItem: 'Uklonite element', hubPanelLabel: 'Označite tip sadržaja', importantInstructions: 'Važna uputstva', showImportantInstructions: 'Show instructions', hideImportantInstructions: 'Sakrijte važna uputstva', hide: 'sakriti', example: 'Primjer', createContentTabLabel: 'Napravite sadžaj', uploadTabLabel: 'Upload', uploadPlaceholder: 'Nijedan fajl nije odabran', uploadInstructionsTitle: 'Upload H5P fajla.', uploadInstructionsContent: 'Možete početi koristeći se sa primjerima na H5P.org.', uploadFileButtonLabel: 'Uploadujte fajla', uploadFileButtonChangeLabel: 'Izmjenite fajl', uploadingThrobber: 'Sada se uploaduje...', uploadSuccess: ':title was successfully uploaded!', unableToInterpretError: 'Unable to interpret response.', unableToInterpretSolution: 'Please check your error log.', h5pFileWrongExtensionTitle: 'Označeni fajl nije moguće uploadovati', h5pFileWrongExtensionContent: 'Samo fajlovi sa .h5p ekstenzijom su dozvoljeni.', h5pFileValidationFailedTitle: 'Nije moguće verificirati H5P fajl.', h5pFileValidationFailedContent: 'Budite sigurni da uploadovani H5P sadrži ispravni H5P sadržaj. H5P fajlovi koji sadrže biblioteke trebaju biti uploadovani samo preko stranice za H5P biblioteke.', h5pFileUploadServerErrorTitle: 'H5P fajl nije moguće uploadovati', h5pFileUploadServerErrorContent: 'Neočekivana greška se pojavila. Provjerite vaš server za greške više detalja.', contentTypeSectionAll: 'Sve', searchResults: 'Search Results', contentTypeSearchFieldPlaceholder: 'Pretražiti vrste sadržaja', contentTypeInstallButtonLabel: 'Instalirati', contentTypeInstallingButtonLabel: 'Instaliranje', contentTypeUseButtonLabel: 'Koristi', contentTypeDetailButtonLabel: 'Details', contentTypeUpdateButtonLabel: 'Update', contentTypeUpdatingButtonLabel: 'Updating', contentTypeGetButtonLabel: 'Dobiti', contentTypeBackButtonLabel: 'Nazad', contentTypeIconAltText: 'Sličica', contentTypeInstallSuccess: ':contentType uspješno instaliran!', contentTypeUpdateSuccess: ':contentType uspješno updejtovan!', contentTypeInstallError: ':contentType ne može biti instaliran. Kontaktirajte vašeg administratora.', contentTypeLicensePanelTitle: 'Licenca', contentTypeDemoButtonLabel: 'Demo sadržaja', numResults: ':num results', show: 'Show', recentlyUsedFirst: 'Recently Used First', popularFirst: 'Popular First', newestFirst: 'Newest First', aToZ: 'A to Z', noResultsFound: 'No results found', noResultsFoundDesc: 'There is no content type that matches your search criteria.', readMore: 'Čitajte više', readLess: 'Čitajte manje', contentTypeOwner: 'autora :owner', contentTypeUnsupportedApiVersionTitle: 'Ova vrsta sadržaja zahtjeva novu glavnu verziju', contentTypeUnsupportedApiVersionContent: 'Kontaktirajte vašeg administratora kako bi vam obezbijedio novu verziju', contentTypeUpdateAvailable: 'Update dostupan', contentTypeRestricted: 'Onemogućena vrsta sadržaja', contentTypeRestrictedDesc: 'Korištenje ove vrste sadržaja je onemogućio administrator.', contentTypeNotInstalled: 'Vrsta sadržaja nije instalirana', contentTypeNotInstalledDesc: 'Nemate potrebne dozvole da instalirate vrste sadržaja.', theContentType: 'vrsta sadržaja', currentMenuSelected: 'trenutni odabir', errorCommunicatingHubTitle: 'Nije u stanju komunicirati sa hubom.', errorCommunicatingHubContent: 'Javila se greška. Molimo pokušajte ponovo.', warningNoContentTypesInstalled: 'Nemate instaliranu nijednu vrstu sadržaja.', warningChangeBrowsingToSeeResults: 'Kliknite na Sve da dobijete listu svih vrsta sadržaja koje možete instalirati', warningUpdateAvailableTitle: 'Dostupna je nova verzija za sadržaj :contentType.', warningUpdateAvailableBody: 'Instalirajte najnoviju verziju za bolje iskustvo sadržaja.', licenseDescription: 'Neke osobine licence su naznačene ispod. Kliknite na info-sličicu iznad da pročitate tekst originalne licence.', licenseModalTitle: 'Detalji o licenci', licenseModalSubtitle: 'Označite licencu da vidite odgovarajuću upotrebu', licenseUnspecified: 'Neodređeno', licenseCanUseCommercially: 'Može se koristiti komercijalno', licenseCanModify: 'Može se mijenjati', licenseCanDistribute: 'Može se dijeliti', licenseCanSublicense: 'Može se dati podlicenca', licenseCanHoldLiable: 'Može se smatrati odgovornim', licenseCannotHoldLiable: 'Ne može se smatrati odgovornim', licenseMustIncludeCopyright: 'Mora sadržavati autorska prava', licenseMustIncludeLicense: 'Mora sadržavati licencu', licenseFetchDetailsFailed: 'Nije uspjelo dohvaćanje pojedinosti licence', imageLightboxTitle: 'Slike', imageLightBoxProgress: ':num od :total', nextImage: 'Sljedeća slika', previousImage: 'Prethodna slika', screenshots: 'Snimci ekrana', reloadButtonLabel: 'Ponovno učitavanje', videoQuality: 'Oznaka kvalitete videa', videoQualityDescription: 'Ova oznaka pomaže korisniku da zna trenutnu kvalitetu videa. Npr. 1080p, 720p, HD or Mobile', videoQualityDefaultLabel: 'Kvalitet :index', noContentTypesAvailable: 'No content types are available', noContentTypesAvailableDesc: 'Your site is having difficulties connecting to H5P.org and listing the available content types.', contentTypeCacheOutdated: 'Content type list outdated', contentTypeCacheOutdatedDesc: 'Your site is having difficulties connecting to H5P.org to check for content type updates. You may not be able to update or install new content types.', tryAgain: 'Try again', getHelp: 'Get help', untitled: 'Untitled :libraryTitle', title: 'Title', metadata: 'Metadata', addTitle: 'Add title', usedForSearchingReportsAndCopyrightInformation: 'Used for searching, reports and copyright information', metadataSharingAndLicensingInfo: 'Metadata (sharing and licensing info)', fillInTheFieldsBelow: 'Fill in the fields below', saveMetadata: 'Save metadata', addAuthor: 'Save author', confirmRemoveAuthor: 'Are you sure you would like to remove this author?', addNewChange: 'Add new change', confirmDeleteChangeLog: 'Are you sure you would like to delete this change log entry?', changelogDescription: 'Some licenses require that changes made to the original work, or derivatives are logged and displayed. You may log your changes here for licensing reasons or just to allow yourself and others to keep track of the changes made to this content.', logThisChange: 'Log this change', newChangeHasBeenLogged: 'New change has been logged', loggedChanges: 'Logged changes', noChangesHaveBeenLogged: 'No changes have been logged', errorHeader: 'An error occured', errorCalculatingMaxScore: 'Could not calculate the max score for this content. The max score is assumed to be 0. Contact your administrator if this isn’t correct.', maxScoreSemanticsMissing: 'Could not find the expected semantics in the content.', copyButton: 'Copy', copiedButton: 'Copied', pasteButton: 'Paste', pasteAndReplaceButton: 'Paste & Replace', pasteContent: 'Replace Content', confirmPasteContent: 'By doing this you will replace the current content with the content from your clipboard. The current content will be lost. Are you sure you wish to continue?', confirmPasteButtonText: 'Replace content', copyToClipboard: 'Copy H5P content to the clipboard', copiedToClipboard: 'Content is copied to the clipboard', pasteFromClipboard: 'Paste H5P content from the clipboard', pasteAndReplaceFromClipboard: 'Replace existing content with H5P Content from the clipboard', pasteNoContent: 'No H5P content on the clipboard', pasteError: 'Cannot paste from clipboard', pasteContentNotSupported: 'The content in the H5P clipboard is not supported in this context', pasteContentRestricted: 'The content in the clipboard has been restricted on this site', pasteTooOld: 'The content in the H5P clipboard is of a lower version (:clip) than what is supported in this context (:local), if possible try to have the content you want to paste upgraded, copy it again and try pasting it here.', pasteTooNew: 'The content in the H5P clipboard is of a higher version (:clip) than what is supported in this context (:local), if possible try to have this content upgraded first, and then try pasting the content here again.', ok: 'OK', avTablistLabel: 'Insert using', tabTitleBasicFileUpload: 'File Upload', tabTitleInputLinkURL: 'Link/URL', errorTooHighVersion: 'Parameters contain %used while only %supported or earlier are supported.', errorNotSupported: 'Parameters contain %used which is not supported.', errorParamsBroken: 'Parameters are broken.', libraryMissing: 'Missing required library %lib.', scriptMissing: 'Could not load upgrades script for %lib.', language: 'Language', noLanguagesSupported: 'No languages supported', changeLanguage: 'Change language to :language?', thisWillPotentially: "This will potentially reset all the text and translations. You can't undo this. The content itself will not be changed. Do you want to proceed?", notAllTextsChanged: 'Not all texts were changed, there is only partial coverage for :language.', contributeTranslations: 'If you want to complete the translation for :language you can learn about contributing translations to H5P', unknownLibrary: "Unfortunately, the selected content type '%lib' isn't installed on this system.", proceedButtonLabel: 'Proceed to save', enterFullscreenButtonLabel: 'Enter fullscreen', exitFullscreenButtonLabel: 'Exit fullscreen', a11yTitleShowLabel: 'Show label for AT', a11yTitleHideLabel: 'Hide label for AT', reuseSuccess: ':title was successfully imported from the H5P Hub.', noContentHeader: 'No Fitting Content?', noContentSuggestion: 'Create one yourself!', tutorials: 'Tutorials', contentSectionAll: 'All shared content', popularContent: 'Popular Content', allPopular: 'All Popular', newOnTheHub: 'New on the Hub', allNew: 'All New', filterBy: 'Filter by', filter: 'Filter', filters: { level: { dropdownLabel: 'Level', dialogHeader: 'Select level of education', dialogButtonLabel: 'Filter level of education', }, language: { dropdownLabel: 'Language', dialogHeader: 'Select language(s)', dialogButtonLabel: 'Filter languages', searchPlaceholder: 'Type to search for languages', }, reviewed: { dropdownLabel: 'Reviewed', dialogHeader: 'Reviewed Content', dialogButtonLabel: 'Filter', optionLabel: 'Show only reviewed content', }, contentTypes: { dropdownLabel: 'Content types', dialogHeader: 'Select Content type(s)', dialogButtonLabel: 'Filter Content Types', searchPlaceholder: 'Type to search for content types', }, disciplines: { dropdownLabel: 'Discipline', dialogHeader: 'Select Your Discipline', dialogButtonLabel: 'Filter Disciplines', searchPlaceholder: 'Type to search for disciplines', }, licenses: { dropdownLabel: 'License', dialogHeader: 'Select preferred rights of use', dialogButtonLabel: 'Filter licenses', options: { modified: 'Can be modified', commercial: 'Allows commercial use' }, }, }, clearFilters: 'Clear all filters', contentSearchFieldPlaceholder: 'Search for Content', loadingContentTitle: 'We are loading content for you...', loadingContentSubtitle: 'Please wait', by: 'By', dropdownButton: 'Open dropdown', paginationNavigation: 'Pagination navigation', page: 'Page', currentPage: 'Current page', nextPage: 'Go to next page', previousPage: 'Go to previous page', contentPreviewButtonLabel: 'Preview', contentDownloadButtonLabel: 'Get Content', reuseContentTabLabel: 'Get Shared Content', contentPublisherPanelHeader: 'Publisher Info', noContentFoundDesc: 'There is no content that matches your search criteria.', h5pType: 'H5P Type', level: 'Level', size: 'Size', failedFetchingData: 'Failed fetching data', filterErrorMessage: 'Something went wrong. Please reload the page.', in: 'in', navigateToParent: 'Navigate to parent', }; PK*\P n.n.3h5plib/v127/joubel/editor/scripts/h5p-hub-client.jsnu[!function(e){var t={};function n(r){if(t[r])return t[r].exports;var a=t[r]={i:r,l:!1,exports:{}};return e[r].call(a.exports,a,a.exports,n),a.l=!0,a.exports}n.m=e,n.c=t,n.d=function(e,t,r){n.o(e,t)||Object.defineProperty(e,t,{enumerable:!0,get:r})},n.r=function(e){"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},n.t=function(e,t){if(1&t&&(e=n(e)),8&t)return e;if(4&t&&"object"==typeof e&&e&&e.__esModule)return e;var r=Object.create(null);if(n.r(r),Object.defineProperty(r,"default",{enumerable:!0,value:e}),2&t&&"string"!=typeof e)for(var a in e)n.d(r,a,function(t){return e[t]}.bind(null,a));return r},n.n=function(e){var t=e&&e.__esModule?function(){return e.default}:function(){return e};return n.d(t,"a",t),t},n.o=function(e,t){return Object.prototype.hasOwnProperty.call(e,t)},n.p="",n(n.s=30)}([function(e,t,n){"use strict";e.exports=n(34)},function(e,t,n){e.exports=n(38)()},function(e,t){e.exports=function(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e){if(void 0===e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return e},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){function n(t){return e.exports=n=Object.setPrototypeOf?Object.getPrototypeOf:function(e){return e.__proto__||Object.getPrototypeOf(e)},e.exports.default=e.exports,e.exports.__esModule=!0,n(t)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){e.exports=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){function n(e,t){for(var n=0;n1?n-1:0),a=1;a1?n-1:0),a=1;a0&&void 0!==arguments[0]?arguments[0]:{},t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:"Async",n=D.a.createContext(void 0),r=n.Consumer,a=n.Provider;function i(e){var t=e.children;return D.a.createElement(r,null,(function(e){if(!e)throw new Error("this component should only be used within an associated component!");return t(e)}))}var o=function(t){y()(r,t);var n=k(r);function r(t){var a;S()(this,r),(a=n.call(this,t)).mounted=!1,a.counter=0,a.args=[],a.promise=X,a.abortController=new z,a.start=a.start.bind(h()(a)),a.load=a.load.bind(h()(a)),a.run=a.run.bind(h()(a)),a.cancel=a.cancel.bind(h()(a)),a.onResolve=a.onResolve.bind(h()(a)),a.onReject=a.onReject.bind(h()(a)),a.setData=a.setData.bind(h()(a)),a.setError=a.setError.bind(h()(a));var i=t.promise,o=t.promiseFn||e.promiseFn,l=t.initialValue||e.initialValue;a.state=O(O({},J({initialValue:l,promise:i,promiseFn:o})),{},{cancel:a.cancel,run:a.run,reload:function(){var e;a.load(),(e=a).run.apply(e,c()(a.args))},setData:a.setData,setError:a.setError}),a.debugLabel=t.debugLabel||e.debugLabel;var s=A.__REACT_ASYNC__.devToolsDispatcher,u=t.reducer||e.reducer,f=t.dispatcher||e.dispatcher||s,d=u?function(e,t){return u(e,t,$)}:$,p=ee((function(e,t){a.setState((function(t){return d(t,e)}),t)}));return a.dispatch=f?function(e){return f(e,p,t)}:p,a}return d()(r,[{key:"componentDidMount",value:function(){this.mounted=!0,!this.props.promise&&this.state.initialValue||this.load()}},{key:"componentDidUpdate",value:function(t){var n=this.props,r=n.watch,a=n.watchFn,i=void 0===a?e.watchFn:a,o=n.promise,l=n.promiseFn;return r!==t.watch||i&&i(O(O({},e),this.props),O(O({},e),t))?(this.counter&&this.cancel(),this.load()):o!==t.promise&&(this.counter&&this.cancel(),o)||l!==t.promiseFn&&(this.counter&&this.cancel(),l)?this.load():void 0}},{key:"componentWillUnmount",value:function(){this.cancel(),this.mounted=!1}},{key:"getMeta",value:function(e){return O({counter:this.counter,promise:this.promise,debugLabel:this.debugLabel},e)}},{key:"start",value:function(e){var t=this;return"AbortController"in A&&(this.abortController.abort(),this.abortController=new A.AbortController),this.counter++,this.promise=new Promise((function(n,r){if(t.mounted){t.dispatch({type:K.start,payload:function(){return e().then(n,r)},meta:t.getMeta()})}}))}},{key:"load",value:function(){var t=this,n=this.props.promise,r=this.props.promiseFn||e.promiseFn;if(n)this.start((function(){return n})).then(this.onResolve(this.counter)).catch(this.onReject(this.counter));else if(r){var a=O(O({},e),this.props);this.start((function(){return r(a,t.abortController)})).then(this.onResolve(this.counter)).catch(this.onReject(this.counter))}}},{key:"run",value:function(){for(var t=this,n=arguments.length,r=new Array(n),a=0;a1&&void 0!==arguments[1]?arguments[1]:R;return a.current&&(v({type:K.fulfill,payload:e,meta:M()}),t()),e}),[v,M]),E=Object(j.useCallback)((function(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:R;return a.current&&(v({type:K.reject,payload:e,error:!0,meta:M()}),t()),e}),[v,M]),C=n.onResolve,x=n.onReject,S=Object(j.useCallback)((function(e){return function(t){return e===r.current&&L(t,(function(){return C&&C(t)}))}}),[L,C]),T=Object(j.useCallback)((function(e){return function(t){return e===r.current&&E(t,(function(){return x&&x(t)}))}}),[E,x]),N=Object(j.useCallback)((function(e){return"AbortController"in A&&(u.current.abort(),u.current=new A.AbortController),r.current++,l.current=new Promise((function(t,n){if(a.current){v({type:K.start,payload:function(){return e().then(t,n)},meta:M()})}}))}),[v,M]),D=n.promise,k=n.promiseFn,I=n.initialValue,P=Object(j.useCallback)((function(){var e=I&&0===r.current;D?N((function(){return D})).then(S(r.current)).catch(T(r.current)):k&&!e&&N((function(){return k(o.current,u.current)})).then(S(r.current)).catch(T(r.current))}),[N,D,k,I,S,T]),_=n.deferFn,F=Object(j.useCallback)((function(){for(var e=arguments.length,t=new Array(e),n=0;n component instead.")};j.useEffect,j.useEffect;t.b=te}).call(this,n(17))},function(e,t){function n(t){return"function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?(e.exports=n=function(e){return typeof e},e.exports.default=e.exports,e.exports.__esModule=!0):(e.exports=n=function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},e.exports.default=e.exports,e.exports.__esModule=!0),n(t)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){var r=n(56),a=n(57),i=n(23),o=n(58);e.exports=function(e){return r(e)||a(e)||i(e)||o()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r,a=n(63),i=(r=a)&&r.__esModule?r:{default:r};t.default=i.default,e.exports=t.default},function(e,t,n){var r=n(46),a=n(47),i=n(23),o=n(48);e.exports=function(e,t){return r(e)||a(e,t)||i(e,t)||o()},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){e.exports={screenSmall:"576px"}},function(e,t,n){var r=n(52);e.exports=function(e,t){if(null==e)return{};var n,a,i=r(e,t);if(Object.getOwnPropertySymbols){var o=Object.getOwnPropertySymbols(e);for(a=0;a=0||Object.prototype.propertyIsEnumerable.call(e,n)&&(i[n]=e[n])}return i},e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){var n;n=function(){return this}();try{n=n||new Function("return this")()}catch(e){"object"==typeof window&&(n=window)}e.exports=n},function(e,t){function n(t,r){return e.exports=n=Object.setPrototypeOf||function(e,t){return e.__proto__=t,e},e.exports.default=e.exports,e.exports.__esModule=!0,n(t,r)}e.exports=n,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t){!function(e){"use strict";if(!e.fetch){var t="URLSearchParams"in e,n="Symbol"in e&&"iterator"in Symbol,r="FileReader"in e&&"Blob"in e&&function(){try{return new Blob,!0}catch(e){return!1}}(),a="FormData"in e,i="ArrayBuffer"in e;if(i)var o=["[object Int8Array]","[object Uint8Array]","[object Uint8ClampedArray]","[object Int16Array]","[object Uint16Array]","[object Int32Array]","[object Uint32Array]","[object Float32Array]","[object Float64Array]"],l=function(e){return e&&DataView.prototype.isPrototypeOf(e)},s=ArrayBuffer.isView||function(e){return e&&o.indexOf(Object.prototype.toString.call(e))>-1};h.prototype.append=function(e,t){e=f(e),t=d(t);var n=this.map[e];this.map[e]=n?n+","+t:t},h.prototype.delete=function(e){delete this.map[f(e)]},h.prototype.get=function(e){return e=f(e),this.has(e)?this.map[e]:null},h.prototype.has=function(e){return this.map.hasOwnProperty(f(e))},h.prototype.set=function(e,t){this.map[f(e)]=d(t)},h.prototype.forEach=function(e,t){for(var n in this.map)this.map.hasOwnProperty(n)&&e.call(t,this.map[n],n,this)},h.prototype.keys=function(){var e=[];return this.forEach((function(t,n){e.push(n)})),p(e)},h.prototype.values=function(){var e=[];return this.forEach((function(t){e.push(t)})),p(e)},h.prototype.entries=function(){var e=[];return this.forEach((function(t,n){e.push([n,t])})),p(e)},n&&(h.prototype[Symbol.iterator]=h.prototype.entries);var u=["DELETE","GET","HEAD","OPTIONS","POST","PUT"];w.prototype.clone=function(){return new w(this,{body:this._bodyInit})},v.call(w.prototype),v.call(L.prototype),L.prototype.clone=function(){return new L(this._bodyInit,{status:this.status,statusText:this.statusText,headers:new h(this.headers),url:this.url})},L.error=function(){var e=new L(null,{status:0,statusText:""});return e.type="error",e};var c=[301,302,303,307,308];L.redirect=function(e,t){if(-1===c.indexOf(t))throw new RangeError("Invalid status code");return new L(null,{status:t,headers:{location:e}})},e.Headers=h,e.Request=w,e.Response=L,e.fetch=function(e,t){return new Promise((function(n,a){var i=new w(e,t),o=new XMLHttpRequest;o.onload=function(){var e,t,r={status:o.status,statusText:o.statusText,headers:(e=o.getAllResponseHeaders()||"",t=new h,e.replace(/\r?\n[\t ]+/," ").split(/\r?\n/).forEach((function(e){var n=e.split(":"),r=n.shift().trim();if(r){var a=n.join(":").trim();t.append(r,a)}})),t)};r.url="responseURL"in o?o.responseURL:r.headers.get("X-Request-URL");var a="response"in o?o.response:o.responseText;n(new L(a,r))},o.onerror=function(){a(new TypeError("Network request failed"))},o.ontimeout=function(){a(new TypeError("Network request failed"))},o.open(i.method,i.url,!0),"include"===i.credentials&&(o.withCredentials=!0),"responseType"in o&&r&&(o.responseType="blob"),i.headers.forEach((function(e,t){o.setRequestHeader(t,e)})),o.send(void 0===i._bodyInit?null:i._bodyInit)}))},e.fetch.polyfill=!0}function f(e){if("string"!=typeof e&&(e=String(e)),/[^a-z0-9\-#$%&'*+.\^_`|~]/i.test(e))throw new TypeError("Invalid character in header field name");return e.toLowerCase()}function d(e){return"string"!=typeof e&&(e=String(e)),e}function p(e){var t={next:function(){var t=e.shift();return{done:void 0===t,value:t}}};return n&&(t[Symbol.iterator]=function(){return t}),t}function h(e){this.map={},e instanceof h?e.forEach((function(e,t){this.append(t,e)}),this):Array.isArray(e)?e.forEach((function(e){this.append(e[0],e[1])}),this):e&&Object.getOwnPropertyNames(e).forEach((function(t){this.append(t,e[t])}),this)}function m(e){if(e.bodyUsed)return Promise.reject(new TypeError("Already read"));e.bodyUsed=!0}function y(e){return new Promise((function(t,n){e.onload=function(){t(e.result)},e.onerror=function(){n(e.error)}}))}function g(e){var t=new FileReader,n=y(t);return t.readAsArrayBuffer(e),n}function b(e){if(e.slice)return e.slice(0);var t=new Uint8Array(e.byteLength);return t.set(new Uint8Array(e)),t.buffer}function v(){return this.bodyUsed=!1,this._initBody=function(e){if(this._bodyInit=e,e)if("string"==typeof e)this._bodyText=e;else if(r&&Blob.prototype.isPrototypeOf(e))this._bodyBlob=e;else if(a&&FormData.prototype.isPrototypeOf(e))this._bodyFormData=e;else if(t&&URLSearchParams.prototype.isPrototypeOf(e))this._bodyText=e.toString();else if(i&&r&&l(e))this._bodyArrayBuffer=b(e.buffer),this._bodyInit=new Blob([this._bodyArrayBuffer]);else{if(!i||!ArrayBuffer.prototype.isPrototypeOf(e)&&!s(e))throw new Error("unsupported BodyInit type");this._bodyArrayBuffer=b(e)}else this._bodyText="";this.headers.get("content-type")||("string"==typeof e?this.headers.set("content-type","text/plain;charset=UTF-8"):this._bodyBlob&&this._bodyBlob.type?this.headers.set("content-type",this._bodyBlob.type):t&&URLSearchParams.prototype.isPrototypeOf(e)&&this.headers.set("content-type","application/x-www-form-urlencoded;charset=UTF-8"))},r&&(this.blob=function(){var e=m(this);if(e)return e;if(this._bodyBlob)return Promise.resolve(this._bodyBlob);if(this._bodyArrayBuffer)return Promise.resolve(new Blob([this._bodyArrayBuffer]));if(this._bodyFormData)throw new Error("could not read FormData body as blob");return Promise.resolve(new Blob([this._bodyText]))},this.arrayBuffer=function(){return this._bodyArrayBuffer?m(this)||Promise.resolve(this._bodyArrayBuffer):this.blob().then(g)}),this.text=function(){var e,t,n,r=m(this);if(r)return r;if(this._bodyBlob)return e=this._bodyBlob,t=new FileReader,n=y(t),t.readAsText(e),n;if(this._bodyArrayBuffer)return Promise.resolve(function(e){for(var t=new Uint8Array(e),n=new Array(t.length),r=0;r-1?r:n),this.mode=t.mode||this.mode||null,this.referrer=null,("GET"===this.method||"HEAD"===this.method)&&a)throw new TypeError("Body not allowed for GET or HEAD requests");this._initBody(a)}function M(e){var t=new FormData;return e.trim().split("&").forEach((function(e){if(e){var n=e.split("="),r=n.shift().replace(/\+/g," "),a=n.join("=").replace(/\+/g," ");t.append(decodeURIComponent(r),decodeURIComponent(a))}})),t}function L(e,t){t||(t={}),this.type="default",this.status="status"in t?t.status:200,this.ok=this.status>=200&&this.status<300,this.statusText="statusText"in t?t.statusText:"OK",this.headers=new h(t.headers),this.url=t.url||"",this._initBody(e)}}("undefined"!=typeof self?self:this)},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.canUseDOM=void 0;var r,a=n(68);var i=((r=a)&&r.__esModule?r:{default:r}).default,o=i.canUseDOM?window.HTMLElement:{};t.canUseDOM=i.canUseDOM;t.default=o},function(e,t,n){"use strict";!function e(){if("undefined"!=typeof __REACT_DEVTOOLS_GLOBAL_HOOK__&&"function"==typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE){0;try{__REACT_DEVTOOLS_GLOBAL_HOOK__.checkDCE(e)}catch(e){console.error(e)}}}(),e.exports=n(35)},function(e,t,n){"use strict"; /* object-assign (c) Sindre Sorhus @license MIT */var r=Object.getOwnPropertySymbols,a=Object.prototype.hasOwnProperty,i=Object.prototype.propertyIsEnumerable;function o(e){if(null==e)throw new TypeError("Object.assign cannot be called with null or undefined");return Object(e)}e.exports=function(){try{if(!Object.assign)return!1;var e=new String("abc");if(e[5]="de","5"===Object.getOwnPropertyNames(e)[0])return!1;for(var t={},n=0;n<10;n++)t["_"+String.fromCharCode(n)]=n;if("0123456789"!==Object.getOwnPropertyNames(t).map((function(e){return t[e]})).join(""))return!1;var r={};return"abcdefghijklmnopqrst".split("").forEach((function(e){r[e]=e})),"abcdefghijklmnopqrst"===Object.keys(Object.assign({},r)).join("")}catch(e){return!1}}()?Object.assign:function(e,t){for(var n,l,s=o(e),u=1;ue.length)&&(t=e.length);for(var n=0,r=new Array(t);n=0)&&i(e,!n)}e.exports=t.default},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0}),t.assertNodeList=s,t.setElement=function(e){var t=e;if("string"==typeof t&&o.canUseDOM){var n=document.querySelectorAll(t);s(n,t),t="length"in n?n[0]:n}return l=t||l},t.validateElement=u,t.hide=function(e){u(e)&&(e||l).setAttribute("aria-hidden","true")},t.show=function(e){u(e)&&(e||l).removeAttribute("aria-hidden")},t.documentNotReadyOrSSRTesting=function(){l=null},t.resetForTesting=function(){l=null};var r,a=n(67),i=(r=a)&&r.__esModule?r:{default:r},o=n(20);var l=null;function s(e,t){if(!e||!e.length)throw new Error("react-modal: No elements were found for selector "+t+".")}function u(e){return!(!e&&!l)||((0,i.default)(!1,["react-modal: App element is not defined.","Please use `Modal.setAppElement(el)` or set `appElement={el}`.","This is needed so screen readers don't see main content","when modal is opened. It is not recommended, but you can opt-out","by setting `ariaHideApp={false}`."].join(" ")),!1)}},function(e,t,n){"use strict";Object.defineProperty(t,"__esModule",{value:!0});var r=new function e(){var t=this;!function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")}(this,e),this.register=function(e){-1===t.openInstances.indexOf(e)&&(t.openInstances.push(e),t.emit("register"))},this.deregister=function(e){var n=t.openInstances.indexOf(e);-1!==n&&(t.openInstances.splice(n,1),t.emit("deregister"))},this.subscribe=function(e){t.subscribers.push(e)},this.emit=function(e){t.subscribers.forEach((function(n){return n(e,t.openInstances.slice())}))},this.openInstances=[],this.subscribers=[]};t.default=r,e.exports=t.default},function(e,t,n){var r=n(4),a=n(18),i=n(53),o=n(54);function l(t){var n="function"==typeof Map?new Map:void 0;return e.exports=l=function(e){if(null===e||!i(e))return e;if("function"!=typeof e)throw new TypeError("Super expression must either be null or a function");if(void 0!==n){if(n.has(e))return n.get(e);n.set(e,t)}function t(){return o(e,arguments,r(this).constructor)}return t.prototype=Object.create(e.prototype,{constructor:{value:t,enumerable:!1,writable:!0,configurable:!0}}),a(t,e)},e.exports.default=e.exports,e.exports.__esModule=!0,l(t)}e.exports=l,e.exports.default=e.exports,e.exports.__esModule=!0},function(e,t,n){"use strict";(function(t){!function(t){var n=/^(b|B)$/,r={iec:{bits:["b","Kib","Mib","Gib","Tib","Pib","Eib","Zib","Yib"],bytes:["B","KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"]},jedec:{bits:["b","Kb","Mb","Gb","Tb","Pb","Eb","Zb","Yb"],bytes:["B","KB","MB","GB","TB","PB","EB","ZB","YB"]}},a={iec:["","kibi","mebi","gibi","tebi","pebi","exbi","zebi","yobi"],jedec:["","kilo","mega","giga","tera","peta","exa","zetta","yotta"]};function i(e){var t,i,o,l,s,u,c,f,d,p,h,m,y,g,b,v=11)for(var n=1;nD.length&&D.push(e)}function O(e,t,n){return null==e?0:function e(t,n,r,a){var l=typeof t;"undefined"!==l&&"boolean"!==l||(t=null);var s=!1;if(null===t)s=!0;else switch(l){case"string":case"number":s=!0;break;case"object":switch(t.$$typeof){case i:case o:s=!0}}if(s)return r(a,t,""===n?"."+A(t,0):n),1;if(s=0,n=""===n?".":n+":",Array.isArray(t))for(var u=0;u