.on(`all`, (event, path) => { if (event === `change` || event === `add`) { // Copy it over local version. // Don't copy over the Gatsby bin file as that breaks the NPM symlink. if (_.includes(path, `dist/gatsby-cli.js`)) { return } const newPath = syspath.join( `./node_modules/${p}`, syspath.relative(prefix, path) ) copyPath(path, newPath, quiet) // If this is from "cache-dir" also copy it into the site's .cache if (_.includes(path, `cache-dir`)) { const newCachePath = syspath.join( `.cache/`, syspath.relative(syspath.join(prefix, `cache-dir`), path) ) copyPath(path, newCachePath, quiet) } if (scanOnce) { debouncedQuit() } } })
exports.createPageDependency = ({ path, nodeId, connection }) => { const state = store.getState() // Check that the dependencies aren't already recorded so we // can avoid creating lots of very noisy actions. let nodeDependencyExists = false let connectionDependencyExists = false if (!nodeId) { nodeDependencyExists = true } if ( nodeId && _.includes(state.componentDataDependencies.nodes[nodeId], path) ) { nodeDependencyExists = true } if (!connection) { connectionDependencyExists = true } if ( connection && _.includes(state.componentDataDependencies.connections, connection) ) { connectionDependencyExists = true } if (nodeDependencyExists && connectionDependencyExists) { return } // It's new, let's dispatch it const action = actions.createPageDependency({ path, nodeId, connection }) store.dispatch(action) }
(obj, next, key, po, pn, stack) => { if (obj === INVALID_VALUE) return obj // TODO: if you want to support infering Union types this should be handled // differently. Maybe merge all like types into examples for each type? // e.g. union: [1, { foo: true }, ['brown']] -> Union Int|Object|List if (!isSameType(obj, next)) return INVALID_VALUE if (!_.isArray(obj || next)) { // Prefer floats over ints as they're more specific. if (obj && _.isNumber(obj) && !_.isInteger(obj)) return obj if (obj === null) return next if (next === null) return obj return undefined } let array = [].concat(obj, next).filter(isDefined) if (!array.length) return null if (!areAllSameType(array)) return INVALID_VALUE // Linked node arrays don't get reduced further as we // want to preserve all the linked node types. if (_.includes(key, `___NODE`)) { return array } // primitive values don't get merged further, just take the first item if (!_.isObject(array[0])) return array.slice(0, 1) let merged = extractFieldExamples(array) return isDefined(merged) ? [merged] : null }
_.each(clonedArgs.filter, function (v, k) { // Ignore connection and sorting args. if (_.includes([`skip`, `limit`, `sort`], k)) return; siftArgs.push(siftifyArgs({ [k]: v })); extractFieldsToSift(``, k, {}, fieldsToSift, v); });
_.each(exampleValue, (value, key) => { // Remove fields common to the top-level of all nodes. We add these // elsewhere so don't need to infer their type. if (isRoot && EXCLUDE_KEYS[key]) return // Several checks to see if a field is pointing to custom type // before we try automatic inference. const nextSelector = selector ? `${selector}.${key}` : key const fieldSelector = `${nodes[0].internal.type}.${nextSelector}` let fieldName = key let inferredField // First check for manual field => type mappings in the site's // gatsby-config.js if (mapping && _.includes(Object.keys(mapping), fieldSelector)) { inferredField = inferFromMapping(value, mapping, fieldSelector, types) // Second if the field has a suffix of ___node. We use then the value // (a node id) to find the node and use that node's type as the field } else if (_.includes(key, `___NODE`)) { ;[fieldName] = key.split(`___`) inferredField = inferFromFieldName(value, nextSelector, types) // Third if the field is pointing to a file (from another file). } else if ( nodes[0].internal.type !== `File` && shouldInferFile(nodes, nextSelector, value) ) { inferredField = inferFromUri(key, types) } // Finally our automatic inference of field value type. if (!inferredField) { inferredField = inferGraphQLType({ nodes, types, exampleValue: value, selector: selector ? `${selector}.${key}` : key, }) } if (!inferredField) return // Replace unsupported values inferredFields[createKey(fieldName)] = inferredField })
Array.from(store.getState().pages.values()).forEach(page => { if ( !_.includes(statefulPlugins, page.pluginCreatorId) && page.updatedAt < timestamp ) { deleteComponentsDependencies([page.path]) deletePage(page) } })
var codeSplits = highlightedCode.split(`\n`).map(function (split, i) { if (_.includes(lineNumbersHighlight, i + 1)) { return { highlighted: true, code: `<span class="gatsby-highlight-code-line">${split}\n</span>` }; } else { return { code: split }; } });
const codeSplits = highlightedCode.split(`\n`).map((split, i) => { if (_.includes(lineNumbersHighlight, i + 1)) { return { highlighted: true, code: `<span class="gatsby-highlight-code-line">${split}\n</span>`, } } else { return { code: split } } })
const blogPosts = _.filter(result.data.allMarkdownRemark.edges, edge => { const slug = _.get(edge, `node.fields.slug`) const draft = _.get(edge, `node.frontmatter.draft`) if (!slug) return undefined if (_.includes(slug, `/blog/`) && !draft) { return edge } return undefined })
const useGlobalGatsby = function() { // Never use global install *except* for new and help commands if (!_.includes([`new`, `--help`], process.argv[2])) { report.panic( `A local install of Gatsby was not found. \n` + `You should save Gatsby as a site dependency e.g. npm install --save gatsby` ) } require(`./bin/cli`) }
visit(ast, `image`, node => { if ( node.title === `Permalink to this headline` || node.title === 'Permalink to this definition' ) { toRemove.push(node); } else { if (_.includes(node.title, `Permalink`)) { console.log(node); } } });
const readingPosts = _.filter(allMarkdownPages, edge => { const slug = _.get(edge, `node.fields.slug`) if (!slug) { return false } if (_.includes(slug, `/reading/`)) { return true } return false })
visited.set(entrypoint, requires.reduce((acc, dep) => { debug(`found ${dep}`); if (dep.startsWith(`.`)) { debug(`${dep} is relative, descending`); const next = walk(path.resolve(path.dirname(entrypoint), dep)); acc = new Set([...acc, ...next]); } else if (!builtins.includes(dep)) { debug(`found dependency ${dep}`); acc.add(requireToPackage(dep)); } return acc; }, new Set()));
result.data.allMarkdownRemark.edges.forEach(edge => { const slug = _.get(edge, `node.fields.slug`) if (!slug) return if (!_.includes(slug, `/blog/`)) { createPage({ path: `${edge.node.fields.slug}`, // required component: slash( edge.node.fields.package ? localPackageTemplate : docsTemplate ), context: { slug: edge.node.fields.slug, }, }) } })
_.each(exampleValue, (value, key) => { // Remove fields for traversing through nodes as we want to control // setting traversing up not try to automatically infer them. if (isRoot && EXCLUDE_KEYS[key]) return // Input arguments on linked fields aren't currently supported if (_.includes(key, `___NODE`)) return let field = inferGraphQLInputFields({ nodes, value, prefix: `${prefix}${_.upperFirst(key)}`, }) if (field == null) return inferredFields[createKey(key)] = field })
const depsToVersions = _.curry((rootPkg, deps) => deps.reduce((acc, dep) => { if (builtins.includes(dep)) { return acc; } acc[dep] = rootPkg.dependencies[dep] || rootPkg.devDependencies[dep] || rootPkg.optionalDependencies[dep]; if (!acc[dep]) { try { acc[dep] = require(`./packages/node_modules/${dep}/package.json`).version; } catch (err) { // eslint-disable-next-line no-console console.warn(err); throw new Error(`Failed to determine version for ${dep}, Is it missing from package.json?`); } } return acc; }, {}));
allPackages.forEach(edge => { if (_.includes(localPackagesArr, edge.node.title)) { createPage({ path: edge.node.slug, component: slash(localPackageTemplate), context: { slug: edge.node.slug, id: edge.node.id, layout: `plugins`, }, }) } else { createPage({ path: edge.node.slug, component: slash(remotePackageTemplate), context: { slug: edge.node.slug, id: edge.node.id, layout: `plugins`, }, }) } })
async function onCreateNode({ node, getNode, actions, loadNodeContent }) { const { createNode, createParentChildLink } = actions const fileExtsToProcess = [`js`, `jsx`, `ts`, `tsx`] // This only processes javascript and typescript files. if (!_.includes(fileExtsToProcess, node.extension)) { return } const code = await loadNodeContent(node) const options = { sourceType: `module`, allowImportExportEverywhere: true, plugins: [ `jsx`, `doExpressions`, `objectRestSpread`, [ `decorators`, { decoratorsBeforeExport: true, }, ], `classProperties`, `exportExtensions`, `asyncGenerators`, `functionBind`, `functionSent`, `dynamicImport`, `flow`, ], } let exportsData, frontmatter, error try { const ast = babylon.parse(code, options) const parseData = function parseData(node) { let value if (node.type === `TemplateLiteral`) { // Experimental basic support for template literals: // Extract and join any text content; ignore interpolations value = node.quasis.map(quasi => quasi.value.cooked).join(``) } else if (node.type === `ObjectExpression`) { value = {} node.properties.forEach(elem => { value[elem.key.name] = parseData(elem.value) }) } else if (node.type === `ArrayExpression`) { value = node.elements.map(elem => parseData(elem)) } else { value = node.value } return value } frontmatter = {} error = false traverse(ast, { AssignmentExpression: function AssignmentExpression(astPath) { if ( astPath.node.left.type === `MemberExpression` && astPath.node.left.property.name === `frontmatter` ) { astPath.node.right.properties.forEach(node => { frontmatter[node.key.name] = parseData(node.value) }) } }, ExportNamedDeclaration: function ExportNamedDeclaration(astPath) { const { declaration } = astPath.node if (declaration && declaration.type === `VariableDeclaration`) { const dataVariableDeclarator = _.find( declaration.declarations, d => d.id.name === `frontmatter` ) if (dataVariableDeclarator && dataVariableDeclarator.init) { dataVariableDeclarator.init.properties.forEach(node => { frontmatter[node.key.name] = parseData(node.value) }) } } }, }) } catch (e) { // stick the error on the query so the user can // react to an error as they see fit error = { err: true, code: e.code, message: e.message, stack: e.stack, } } finally { // only create node if frontmatter is not empty if (!_.isEmpty(frontmatter)) { exportsData = { ...frontmatter, error: error, } const objStr = JSON.stringify(node) const contentDigest = crypto .createHash(`md5`) .update(objStr) .digest(`hex`) const nodeData = { id: `${node.id} >>> JavascriptFrontmatter`, children: [], parent: node.id, node: { ...node }, internal: { contentDigest, type: `JavascriptFrontmatter`, }, } nodeData.frontmatter = { ...exportsData } if (node.internal.type === `File`) { nodeData.fileAbsolutePath = node.absolutePath } createNode(nodeData) createParentChildLink({ parent: node, child: nodeData }) } } }
actions.createNodeField = ( { node, name, value, fieldName, fieldValue }: CreateNodeInput, plugin: Plugin, actionOptions?: ActionOptions ) => { if (fieldName) { console.warn( `Calling "createNodeField" with "fieldName" is deprecated. Use "name" instead` ) if (!name) { name = fieldName } } if (fieldValue) { console.warn( `Calling "createNodeField" with "fieldValue" is deprecated. Use "value" instead` ) if (!value) { value = fieldValue } } // Ensure required fields are set. if (!node.internal.fieldOwners) { node.internal.fieldOwners = {} } if (!node.fields) { node.fields = {} } /** * Normalized name of the field that will be used in schema */ const schemaFieldName = _.includes(name, `___NODE`) ? name.split(`___`)[0] : name // Check that this field isn't owned by another plugin. const fieldOwner = node.internal.fieldOwners[schemaFieldName] if (fieldOwner && fieldOwner !== plugin.name) { throw new Error( stripIndent` A plugin tried to update a node field that it doesn't own: Node id: ${node.id} Plugin: ${plugin.name} name: ${name} value: ${value} ` ) } // Update node node.fields[name] = value node.internal.fieldOwners[schemaFieldName] = plugin.name return { type: `ADD_FIELD_TO_NODE`, plugin, ...actionOptions, payload: node, } }
groups[val] = _.filter(connectionNodes, n => _.includes(_.get(n, fieldName), val)
const filterOptionals = (key) => OPTIONAL.includes(key)
_.each(resolvedExample, (value, key) => { // Remove fields common to the top-level of all nodes. We add these // elsewhere so don't need to infer their type. if (value === INVALID_VALUE || (isRoot && EXCLUDE_KEYS[key])) return // Several checks to see if a field is pointing to custom type // before we try automatic inference. const nextSelector = selector ? `${selector}.${key}` : key const fieldSelector = `${rootTypeName}.${nextSelector}` let fieldName = key let inferredField // First check for manual field => type mappings in the site's // gatsby-config.js if (mapping && _.includes(Object.keys(mapping), fieldSelector)) { inferredField = inferFromMapping(value, mapping, fieldSelector, types) // Second if the field has a suffix of ___node. We use then the value // (a node id) to find the node and use that node's type as the field } else if (key.includes(`___NODE`)) { ;[fieldName] = key.split(`___`) inferredField = inferFromFieldName(value, nextSelector, types) lazyFields.add(typeName, fieldName) } // Replace unsupported values const sanitizedFieldName = createKey(fieldName) // If a pluging has already provided a type for this, don't infer it. if (ignoreFields && ignoreFields.includes(sanitizedFieldName)) { return } // Finally our automatic inference of field value type. if (!inferredField) { inferredField = inferGraphQLType({ nodes, types, exampleValue: value, selector: nextSelector, }) } if (!inferredField) return // If sanitized field name is different from original field name // add resolve passthrough to reach value using original field name if (sanitizedFieldName !== fieldName) { const { resolve: fieldResolve, ...inferredFieldWithoutResolve } = inferredField // Using copy if field as we sometimes have predefined frozen // field definitions and we can't mutate them. inferredField = inferredFieldWithoutResolve if (fieldResolve) { // If field has resolver, call it with adjusted resolveInfo // that points to original field name inferredField.resolve = (source, args, context, resolveInfo) => fieldResolve(source, args, context, { ...resolveInfo, fieldName: fieldName, }) } else { inferredField.resolve = source => source[fieldName] } } inferredFields[sanitizedFieldName] = inferredField })
.pages.filter(p => !_.includes(statefulPlugins, p.pluginCreatorId))
.filter(n => _.includes(newOrUpdatedEntries, n.id))
.on(`add`, path => { if (!_.includes(files, path)) { _createPage(path, pagesDirectory, createPage) files.push(path) } })
module.exports = type => { const enumValues = buildFieldEnumValues({ nodes: type.nodes, typeName: type.name, }) const { connectionType: groupConnection } = connectionDefinitions({ name: _.camelCase(`${type.name} groupConnection`), nodeType: type.nodeObjectType, connectionFields: () => { return { field: { type: GraphQLString }, fieldValue: { type: GraphQLString }, totalCount: { type: GraphQLInt }, } }, }) return { totalCount: { type: GraphQLInt, }, distinct: { type: new GraphQLList(GraphQLString), args: { field: { type: new GraphQLEnumType({ name: _.camelCase(`${type.name} distinct enum`), values: enumValues, }), }, }, resolve(connection, args) { let fieldName = args.field if (_.includes(args.field, `___`)) { fieldName = args.field.replace(/___/g, `.`) } const fields = connection.edges.map(edge => _.get(edge.node, fieldName)) return _.sortBy(_.filter(_.uniq(_.flatten(fields)), _.identity)) }, }, group: { type: new GraphQLList(groupConnection), args: { ...connectionArgs, field: { type: new GraphQLEnumType({ name: _.camelCase(`${type.name} group enum`), values: enumValues, }), }, }, resolve(connection, args) { const fieldName = args.field.replace(/___/g, `.`) const connectionNodes = connection.edges.map(edge => edge.node) let groups = {} // Do a custom grouping for arrays (w/ a group per array value) // Find the first node with this field and check if it's an array. if (_.isArray(_.get(_.find(connectionNodes, fieldName), fieldName))) { const values = _.uniq( _.reduce( connectionNodes, (vals, n) => { if (_.has(n, fieldName)) { return vals.concat(_.get(n, fieldName)) } else { return vals } }, [] ) ) values.forEach(val => { groups[val] = _.filter(connectionNodes, n => _.includes(_.get(n, fieldName), val) ) }) } else { groups = _.groupBy(connectionNodes, fieldName) } const groupConnections = [] // Do default sort by fieldValue const sortedFieldValues = _.sortBy(_.keys(groups)) _.each(sortedFieldValues, fieldValue => { const groupNodes = groups[fieldValue] const groupConn = connectionFromArray(groupNodes, args) groupConn.totalCount = groupNodes.length groupConn.field = fieldName groupConn.fieldValue = fieldValue groupConnections.push(groupConn) }) return groupConnections }, }, } }
.filter(u => _.includes(usersToAlert, u.id))
const isImage = image => _.includes( [`image/jpeg`, `image/jpg`, `image/png`, `image/webp`, `image/gif`], _.get(image, `file.contentType`) )
exports.onCreateNode = ({ node, actions, getNode, reporter }) => { const { createNodeField } = actions let slug if (node.internal.type === `File`) { const parsedFilePath = parseFilepath(node.relativePath) if (node.sourceInstanceName === `docs`) { if (parsedFilePath.name !== `index` && parsedFilePath.dir !== ``) { slug = `/${parsedFilePath.dir}/${parsedFilePath.name}/` } else if (parsedFilePath.dir === ``) { slug = `/${parsedFilePath.name}/` } else { slug = `/${parsedFilePath.dir}/` } } if (slug) { createNodeField({ node, name: `slug`, value: slug }) } } else if ( node.internal.type === `MarkdownRemark` && getNode(node.parent).internal.type === `File` ) { const fileNode = getNode(node.parent) const parsedFilePath = parseFilepath(fileNode.relativePath) // Add slugs for docs pages if (fileNode.sourceInstanceName === `docs`) { if (parsedFilePath.name !== `index` && parsedFilePath.dir !== ``) { slug = `/${parsedFilePath.dir}/${parsedFilePath.name}/` } else if (parsedFilePath.dir === ``) { slug = `/${parsedFilePath.name}/` } else { slug = `/${parsedFilePath.dir}/` } // Set released status and `published at` for blog posts. if (_.includes(parsedFilePath.dir, `blog`)) { let released = false const date = _.get(node, `frontmatter.date`) if (date) { released = moment.utc().isSameOrAfter(moment.utc(date)) } createNodeField({ node, name: `released`, value: released }) const canonicalLink = _.get(node, `frontmatter.canonicalLink`) const publishedAt = _.get(node, `frontmatter.publishedAt`) createNodeField({ node, name: `publishedAt`, value: canonicalLink ? publishedAt || url.parse(canonicalLink).hostname : null, }) } } // Add slugs for package READMEs. if ( fileNode.sourceInstanceName === `packages` && parsedFilePath.name === `README` ) { slug = `/packages/${parsedFilePath.dir}/` createNodeField({ node, name: `title`, value: parsedFilePath.dir, }) createNodeField({ node, name: `package`, value: true }) } if (slug) { createNodeField({ node, name: `anchor`, value: slugToAnchor(slug) }) createNodeField({ node, name: `slug`, value: slug }) } } else if (node.internal.type === `AuthorYaml`) { slug = `/contributors/${slugify(node.id, { lower: true, })}/` createNodeField({ node, name: `slug`, value: slug }) } else if (node.internal.type === `SitesYaml` && node.main_url) { const parsed = url.parse(node.main_url) const cleaned = parsed.hostname + parsed.pathname slug = `/showcase/${slugify(cleaned)}` createNodeField({ node, name: `slug`, value: slug }) // determine if screenshot is available const screenshotNode = node.children .map(childID => getNode(childID)) .find(node => node.internal.type === `Screenshot`) createNodeField({ node, name: `hasScreenshot`, value: !!screenshotNode }) } else if (node.internal.type === `StartersYaml` && node.repo) { // To develop on the starter showcase, you'll need a GitHub // personal access token. Check the `www` README for details. // Default fields are to avoid graphql errors. const { owner, name: repoStub } = parseGHUrl(node.repo) const defaultFields = { slug: `/${owner}/${repoStub}/`, stub: repoStub, name: ``, description: ``, stars: 0, lastUpdated: ``, owner: ``, githubFullName: ``, gatsbyMajorVersion: [[`no data`, `0`]], allDependencies: [[`no data`, `0`]], gatsbyDependencies: [[`no data`, `0`]], miscDependencies: [[`no data`, `0`]], } if (!process.env.GITHUB_API_TOKEN) { return createNodeField({ node, name: `starterShowcase`, value: { ...defaultFields, }, }) } else { return Promise.all([ getpkgjson(node.repo), githubApiClient.request(` query { repository(owner:"${owner}", name:"${repoStub}") { name stargazers { totalCount } createdAt pushedAt owner { login } nameWithOwner } } `), ]) .then(results => { const [pkgjson, githubData] = results const { stargazers: { totalCount: stars }, pushedAt: lastUpdated, owner: { login: owner }, name, nameWithOwner: githubFullName, } = githubData.repository const { dependencies = [], devDependencies = [] } = pkgjson const allDependencies = Object.entries(dependencies).concat( Object.entries(devDependencies) ) const gatsbyMajorVersion = allDependencies .filter(([key, _]) => key === `gatsby`) .map(version => { let [gatsby, versionNum] = version if (versionNum === `latest` || versionNum === `next`) { return [gatsby, `2`] } return [gatsby, versionNum.replace(/\D/g, ``).charAt(0)] }) // If a new field is added here, make sure a corresponding // change is made to "defaultFields" to not break DX const starterShowcaseFields = { slug: `/${owner}/${repoStub}/`, stub: repoStub, name, description: pkgjson.description, stars, lastUpdated, owner, githubFullName, gatsbyMajorVersion, allDependencies, gatsbyDependencies: allDependencies .filter( ([key, _]) => ![`gatsby-cli`, `gatsby-link`].includes(key) // remove stuff everyone has ) .filter(([key, _]) => key.includes(`gatsby`)), miscDependencies: allDependencies.filter( ([key, _]) => !key.includes(`gatsby`) ), } createNodeField({ node, name: `starterShowcase`, value: starterShowcaseFields, }) }) .catch(err => { reporter.panicOnBuild( `Error getting repo data for starter "${repoStub}":\n ${err.message}` ) }) } } else if (node.internal.type === `CreatorsYaml`) { // Creator pages const validTypes = { individual: `people`, agency: `agencies`, company: `companies`, } if (!validTypes[node.type]) { throw new Error( `Creators must have a type of “individual”, “agency”, or “company”, but invalid type “${ node.type }” was provided for ${node.name}.` ) } slug = `/creators/${validTypes[node.type]}/${slugify(node.name, { lower: true, })}` createNodeField({ node, name: `slug`, value: slug }) } // end Creator pages return null }
chokidar.watch(pagesGlob).on(`add`, function (path) { if (!_.includes(files, path)) { _createPage(path, pagesDirectory, createPage); files.push(path); } }).on(`unlink`, function (path) {