it('should memoize with external cache', () => { const cache: Cache<string, string> = { get: (key: string) => key, set: (key: string, value: string) => {}, has: (key: string) => true }; const fn: string => string = _ => _.trim(); const memoizedFn1: string => string = memoize( fn, { cache, serializer: () => '' } ); })
import memoize from 'fast-memoize'; import {getPlaylistLessons} from '../playlists'; import {isLessonTranslated} from '../lessonFrontmatter'; /** * Returns whether or not all lessons in the playlist is translated to the given language. * @param {string} course E.g. 'scratch' * @param {string} playlist E.g. 'playlist1' * @param {string} language E.g. 'nb' * @returns {boolean} */ export const areAllLessonsInPlaylistTranslated = memoize( (course, playlist, language) => { const lessons = getPlaylistLessons(course, playlist); const lessonTranslatedReducer = (result, lesson) => result && isLessonTranslated(course, lesson, language); return lessons.reduce(lessonTranslatedReducer, true); } );
it('should memoize', () => { const fn: string => string = _ => _.trim(); const memoizedFn1: string => string = memoize(fn) // $ExpectError const memoizedFn2: number => number = memoize(fn) })
* } * lessons: ['scratchLesson1', 'scratchLesson2'], * }, * ... * }, * python: { * ... * } * } */ const getData = memoize( () => { const playlists = {}; for (const key of playlistContext.keys()) { const [/* ignore */, course, playlist] = key.match(/^[.][/]([^/]+)[/]playlists[/]([^.]+)[.]yml$/); const {sortindex = 0, title = {}, lessons = []} = playlistContext(key); assignDeep(playlists, [course, playlist], {sortindex, title, lessons}); } return playlists; } ); /** * Return all playlists for a course. The playlists are sorted. * @param {string} course E.g. 'scratch' * @return {string[]} An array with the (file)name of all the playlists (without extension), * e.g. ['playlist1', 'playlist2'] */ export const getPlaylistsForCourse = memoize( (course) => { const coursePlaylists = getData()[course] || {};
return [r, g, b, 1] } function parseRgbColor (color) { color = color.match(/\d+\.?\d*/g) var r = Number(color[0]) var g = Number(color[1]) var b = Number(color[2]) var a = Number(color[3]) return [r, g, b, a] } function parseColor (color) { var result if (color[0] === '#') { result = parseHexColor(color) } else if (color[0] === 'r') { result = parseRgbColor(color) } else { throwError(`Wrong color format: ${color}`) } return result } export var parse = memoize(parseColor)
* ... * } */ const getData = memoize( () => { const lessons = {}; for (const key of lessonFrontmatterContext.keys()) { const [/* ignore */, course, lesson, file] = key.match(/^[.][/]([^/]+)[/]([^/]+)[/]([^.]+)[.]md$/); if (isLesson(course, lesson)) { const { language, title = '', author = '', translator = '', external = '' } = lessonFrontmatterContext(key); if (!title) { console.warn('WARNING: The lesson', key, 'did not specify title.'); } if (language) { const isReadmeKey = file.startsWith('README') ? 1 : 0; const path = `/${course}/${lesson}/${file}`; const lessonData = {title, author, translator, external, path, key}; assignDeep(lessons, [course, lesson, language, isReadmeKey], lessonData); } else { console.warn('WARNING: The lesson', key, 'did not specify language, so lesson will not be used.'); } } else { console.warn(`WARNING: The lesson ${course}/${lesson}/${file} did not have a lesson.yml file, skipping...`); } } return lessons; } ); /** * Convert file (given course and lesson) to language and isReadme.
let io; let extensionManager; // Check for updates fetch('http://registry.npmjs.org/nodecg/latest').then(res => { return res.json(); // Download the body as JSON }).then(body => { if (semver.gt(body.version, pjson.version) >= 1) { log.warn('An update is available for NodeCG: %s (current: %s)', JSON.parse(body).version, pjson.version); } }).catch(/* istanbul ignore next */() => { // Discard errors. }); const renderTemplate = memoize((content, options) => { return template(content)(options); }); module.exports = new EventEmitter(); module.exports.start = function () { log.info('Starting NodeCG %s (Running on Node.js %s)', pjson.version, process.version); // (Re)create Express app, HTTP(S) & Socket.IO servers app = express(); if (global.sentryEnabled) { app.use(Raven.requestHandler()); app.use(Raven.errorHandler()); }
* }, * python: { * ... * }, * ... * } */ const getData = memoize( () => { const courses = {}; for (const key of courseFrontmatterContext.keys()) { const [/* ignore */, course, file] = key.match(/^[.][/]([^/]+)[/](index[^.]*)[.]md$/); const {title = '', external = '', language} = courseFrontmatterContext(key); if (getAvailableLanguages().includes(language)) { const path = `/${course}/${file}`; const data = {title, external, path, key}; assignDeep(courses, [course, language], data); } else { console.warn(`The course info ${key} did not have a valid language (${language})`); } } return courses; } ); /** * Get the frontmatter of a course for a given language * @param {string} course E.g. 'scratch' * @param {string} language E.g. 'nb' * @return {object} E.g. {title: 'Scratch', key: './scratch/index.md'} */
while (node) { if (node.tagName) { top = top + node.offsetTop; left = left + node.offsetLeft; node = node.offsetParent; } else { node = node.parentNode; } if (node === ancestor) { node = null; } } return [left, top]; }; /* * Get prefixed or un-prefixed name of "transform" property * in this browser. */ export const getTransformPropertyName = memoize(function () { const prefixes = ['', 'webkit', 'moz', 'ms']; for (let i = 0, ilen = prefixes.length; i < ilen; i++) { const prefix = prefixes[i]; const propertyName = prefix + (prefix ? 'T' : 't') + 'ransform'; if (typeof body.style[propertyName] !== 'undefined') { return propertyName; } } });