ÿØÿà 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-Ї Ç home/smkb8269/public_html/lms.smk-almanshuriyah.sch.id/.grunt/components.js000064400000034743152266406710022645 0ustar00// 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 . /** * Helper functions for working with Moodle component names, directories, and sources. * * @copyright 2019 Andrew Nicols * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ "use strict"; /* eslint-env node */ /** @var {Object} A list of subsystems in Moodle */ const componentData = {}; /** * Load details of all moodle modules. * * @returns {object} */ const fetchComponentData = () => { const fs = require('fs'); const path = require('path'); const glob = require('glob'); const gruntFilePath = process.cwd(); if (!Object.entries(componentData).length) { componentData.subsystems = {}; componentData.pathList = []; componentData.components = {}; componentData.standardComponents = {}; // Fetch the component definiitions from the distributed JSON file. const components = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/components.json`)); const pluginData = JSON.parse(fs.readFileSync(`${gruntFilePath}/lib/plugins.json`)); componentData.pluginTypes = components.plugintypes; const standardPlugins = Object.entries(pluginData.standard).map( ([pluginType, pluginNames]) => { return pluginNames.map(pluginName => `${pluginType}_${pluginName}`); } ).reduce((acc, val) => acc.concat(val), []); // Build the list of moodle subsystems. componentData.subsystems.lib = 'core'; componentData.pathList.push(process.cwd() + path.sep + 'lib'); for (const [component, thisPath] of Object.entries(components.subsystems)) { if (thisPath) { // Prefix "core_" to the front of the subsystems. componentData.subsystems[thisPath] = `core_${component}`; componentData.pathList.push(process.cwd() + path.sep + thisPath); } } // The list of components includes the list of subsystems. componentData.components = {...componentData.subsystems}; const subpluginAdder = (subpluginType, subpluginTypePath) => { glob.sync(`${subpluginTypePath}/*/version.php`).forEach(versionPath => { const componentPath = fs.realpathSync(path.dirname(versionPath)); const componentName = path.basename(componentPath); const frankenstyleName = `${subpluginType}_${componentName}`; componentData.components[`${subpluginTypePath}/${componentName}`] = frankenstyleName; componentData.pathList.push(componentPath); }); }; // Go through each of the plugintypes. Object.entries(components.plugintypes).forEach(([pluginType, pluginTypePath]) => { // We don't allow any code in this place..? glob.sync(`${pluginTypePath}/*/version.php`).forEach(versionPath => { const componentPath = fs.realpathSync(path.dirname(versionPath)); const componentName = path.basename(componentPath); const frankenstyleName = `${pluginType}_${componentName}`; componentData.components[`${pluginTypePath}/${componentName}`] = frankenstyleName; componentData.pathList.push(componentPath); // Look for any subplugins. const subPluginConfigurationFile = `${componentPath}/db/subplugins.json`; if (fs.existsSync(subPluginConfigurationFile)) { const subpluginList = JSON.parse(fs.readFileSync(fs.realpathSync(subPluginConfigurationFile))); if (subpluginList.subplugintypes) { Object.entries(subpluginList.subplugintypes).forEach(([subpluginType, subpluginTypePath]) => { subpluginAdder( subpluginType, `${pluginTypePath}/${componentName}/${subpluginTypePath}` ); }); } else if (subpluginList.plugintypes) { Object.entries(subpluginList.plugintypes).forEach(([subpluginType, subpluginTypePath]) => { subpluginAdder(subpluginType, subpluginTypePath); }); } } }); }); // Create a list of the standard subsystem and plugins. componentData.standardComponents = Object.fromEntries( Object.entries(componentData.components).filter(([, name]) => { if (name === 'core' || name.startsWith('core_')) { return true; } return standardPlugins.indexOf(name) !== -1; }) ); componentData.componentMapping = Object.fromEntries( Object.entries(componentData.components).map(([path, name]) => [name, path]) ); } return componentData; }; /** * Get the list of component paths. * * @param {string} relativeTo * @returns {array} */ const getComponentPaths = (relativeTo = '') => fetchComponentData().pathList.map(componentPath => { return componentPath.replace(relativeTo, ''); }); /** * Get the list of paths to build AMD sources. * * @returns {Array} */ const getAmdSrcGlobList = () => { const globList = []; fetchComponentData().pathList.forEach(componentPath => { globList.push(`${componentPath}/amd/src/*.js`); globList.push(`${componentPath}/amd/src/**/*.js`); }); return globList; }; /** * Get the list of paths to build YUI sources. * * @param {String} relativeTo * @returns {Array} */ const getYuiSrcGlobList = relativeTo => { const globList = []; fetchComponentData().pathList.forEach(componentPath => { const relativeComponentPath = componentPath.replace(relativeTo, ''); globList.push(`${relativeComponentPath}/yui/src/**/*.js`); }); return globList; }; /** * Get the list of paths to thirdpartylibs.xml. * * @param {String} relativeTo * @returns {Array} */ const getThirdPartyLibsList = relativeTo => { const fs = require('fs'); const path = require('path'); return fetchComponentData().pathList .map(componentPath => path.relative(relativeTo, componentPath) + '/thirdpartylibs.xml') .map(componentPath => componentPath.replace(/\\/g, '/')) .filter(path => fs.existsSync(path)) .sort(); }; /** * Get the list of thirdparty library paths. * * @returns {array} */ const getThirdPartyPaths = () => { const DOMParser = require('@xmldom/xmldom').DOMParser; const fs = require('fs'); const path = require('path'); const xpath = require('xpath'); const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./')); const libs = ['node_modules/', 'vendor/']; const addLibToList = lib => { if (!lib.match('\\*') && fs.statSync(lib).isDirectory()) { // Ensure trailing slash on dirs. lib = lib.replace(/\/?$/, '/'); } // Look for duplicate paths before adding to array. if (libs.indexOf(lib) === -1) { libs.push(lib); } }; thirdpartyfiles.forEach(function(file) { const dirname = path.dirname(file); const xmlContent = fs.readFileSync(file, 'utf8'); const doc = new DOMParser().parseFromString(xmlContent); const nodes = xpath.select("/libraries/library/location/text()", doc); nodes.forEach(function(node) { let lib = path.posix.join(dirname, node.toString()); addLibToList(lib); }); }); return libs; }; /** * Find the name of the component matching the specified path. * * @param {String} path * @returns {String|null} Name of matching component. */ const getComponentFromPath = path => { const componentList = fetchComponentData().components; if (componentList.hasOwnProperty(path)) { return componentList[path]; } return null; }; /** * Check whether the supplied path, relative to the Gruntfile.js, is in a known component. * * @param {String} checkPath The path to check. This can be with either Windows, or Linux directory separators. * @returns {String|null} */ const getOwningComponentDirectory = checkPath => { const path = require('path'); // Fetch all components into a reverse sorted array. // This ensures that components which are within the directory of another component match first. const pathList = Object.keys(fetchComponentData().components).sort().reverse(); for (const componentPath of pathList) { // If the componentPath is the directory being checked, it will be empty. // If the componentPath is a parent of the directory being checked, the relative directory will not start with .. if (!path.relative(componentPath, checkPath).startsWith('..')) { return componentPath; } } return null; }; /** * Get the latest tag in a remote GitHub repository. * * @param {string} url The remote repository. * @returns {Array} */ const getRepositoryTags = async(url) => { const gtr = require('git-tags-remote'); try { const tags = await gtr.get(url); if (tags !== undefined) { return tags; } } catch (error) { return []; } return []; }; /** * Get the list of thirdparty libraries that could be upgraded. * * @returns {Array} */ const getThirdPartyLibsUpgradable = async() => { const libraries = getThirdPartyLibsData().filter((library) => !!library.repository); const upgradableLibraries = []; const versionCompare = (a, b) => { if (a === b) { return 0; } const aParts = a.split('.'); const bParts = b.split('.'); for (let i = 0; i < Math.min(aParts.length, bParts.length); i++) { const aPart = parseInt(aParts[i], 10); const bPart = parseInt(bParts[i], 10); if (aPart > bPart) { // 1.1.0 > 1.0.9 return 1; } else if (aPart < bPart) { // 1.0.9 < 1.1.0 return -1; } else { // Same version. continue; } } if (aParts.length > bParts.length) { // 1.0.1 > 1.0 return 1; } // 1.0 < 1.0.1 return -1; }; for (let library of libraries) { upgradableLibraries.push( getRepositoryTags(library.repository).then((tagMap) => { library.version = library.version.replace(/^v/, ''); const currentVersion = library.version.replace(/moodle-/, ''); const currentMajorVersion = library.version.split('.')[0]; const tags = [...tagMap] .map((tagData) => tagData[0]) .filter((tag) => !tag.match(/(alpha|beta|rc)/)) .map((tag) => tag.replace(/^v/, '')) .sort((a, b) => versionCompare(b, a)); if (!tags.length) { library.warning = "Unable to find any comparable tags."; return library; } library.latestVersion = tags[0]; tags.some((tag) => { if (!tag) { return false; } // See if the version part matches. const majorVersion = tag.split('.')[0]; if (majorVersion === currentMajorVersion) { library.latestSameMajorVersion = tag; return true; } return false; }); if (versionCompare(currentVersion, library.latestVersion) > 0) { // Moodle somehow has a newer version than the latest version. library.warning = `Newer version found: ${currentVersion} > ${library.latestVersion} for ${library.name}`; return library; } if (library.version !== library.latestVersion) { // Delete version and add it again at the end of the array. That way, current and new will stay closer. delete library.version; library.version = currentVersion; return library; } return null; }) ); } return (await Promise.all(upgradableLibraries)).filter((library) => !!library); }; /** * Get the list of thirdparty libraries. * * @returns {Array} */ const getThirdPartyLibsData = () => { const DOMParser = require('@xmldom/xmldom').DOMParser; const fs = require('fs'); const xpath = require('xpath'); const path = require('path'); const libraryList = []; const libraryFields = [ 'location', 'name', 'version', 'repository', ]; const thirdpartyfiles = getThirdPartyLibsList(fs.realpathSync('./')); thirdpartyfiles.forEach(function(libraryPath) { const xmlContent = fs.readFileSync(libraryPath, 'utf8'); const doc = new DOMParser().parseFromString(xmlContent); const libraries = xpath.select("/libraries/library", doc); for (const library of libraries) { const libraryData = []; for (const field of libraryFields) { libraryData[field] = xpath.select(`${field}/text()`, library)?.toString(); } libraryData.location = path.join(path.dirname(libraryPath), libraryData.location); libraryList.push(libraryData); } }); return libraryList.sort((a, b) => a.location.localeCompare(b.location)); }; module.exports = { fetchComponentData, getAmdSrcGlobList, getComponentFromPath, getComponentPaths, getOwningComponentDirectory, getYuiSrcGlobList, getThirdPartyLibsList, getThirdPartyPaths, getThirdPartyLibsUpgradable, };