| | |
| | |
| |
|
| | import parse from '@/frame/lib/read-frontmatter' |
| | import { allVersions } from '@/versions/lib/all-versions' |
| | import { allTools } from '@/tools/lib/all-tools' |
| | import { getDeepDataByLanguage } from '@/data-directory/lib/get-data' |
| |
|
| | interface SchemaProperty { |
| | type?: string | string[] |
| | translatable?: boolean |
| | deprecated?: boolean |
| | default?: any |
| | minimum?: number |
| | maximum?: number |
| | enum?: any[] |
| | errorMessage?: string |
| | items?: any |
| | properties?: Record<string, any> |
| | required?: string[] |
| | additionalProperties?: boolean |
| | format?: string |
| | description?: string |
| | minItems?: number |
| | maxItems?: number |
| | } |
| |
|
| | interface Schema { |
| | type: string |
| | required: string[] |
| | additionalProperties: boolean |
| | properties: Record<string, SchemaProperty> |
| | } |
| |
|
| | const layoutNames = [ |
| | 'default', |
| | 'graphql-explorer', |
| | 'product-landing', |
| | 'product-guides', |
| | 'release-notes', |
| | 'inline', |
| | 'category-landing', |
| | 'bespoke-landing', |
| | 'discovery-landing', |
| | 'journey-landing', |
| | false, |
| | ] |
| |
|
| | |
| | |
| | |
| | const guideTypes = ['overview', 'quick_start', 'tutorial', 'how_to', 'reference', 'rai'] |
| |
|
| | |
| | export const contentTypesEnum = [ |
| | 'get-started', |
| | 'concepts', |
| | 'how-tos', |
| | 'reference', |
| | 'tutorials', |
| | 'homepage', |
| | 'landing', |
| | 'rai', |
| | 'other', |
| | ] |
| |
|
| | export const schema: Schema = { |
| | type: 'object', |
| | required: ['title', 'versions'], |
| | additionalProperties: false, |
| | properties: { |
| | title: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | shortTitle: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | intro: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | product: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | permissions: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | |
| | showMiniToc: { |
| | type: 'boolean', |
| | }, |
| | |
| | miniTocMaxHeadingLevel: { |
| | deprecated: true, |
| | type: 'number', |
| | default: 2, |
| | minimum: 2, |
| | maximum: 4, |
| | }, |
| | subcategory: { |
| | type: 'boolean', |
| | }, |
| | |
| | hidden: { |
| | type: 'boolean', |
| | }, |
| | |
| | noEarlyAccessBanner: { |
| | type: 'boolean', |
| | }, |
| | |
| | |
| | earlyAccessToc: { |
| | type: 'boolean', |
| | }, |
| | layout: { |
| | type: ['string', 'boolean'], |
| | enum: layoutNames, |
| | errorMessage: 'must be the filename of an existing layout file, or `false` for no layout', |
| | }, |
| | redirect_from: { |
| | type: 'array', |
| | }, |
| | allowTitleToDifferFromFilename: { |
| | type: 'boolean', |
| | }, |
| | introLinks: { |
| | type: 'object', |
| | }, |
| | authors: { |
| | type: 'array', |
| | items: { |
| | type: 'string', |
| | }, |
| | }, |
| | examples_source: { |
| | type: 'string', |
| | }, |
| | effectiveDate: { |
| | type: 'string', |
| | }, |
| | featuredLinks: { |
| | type: 'object', |
| | properties: { |
| | gettingStarted: { |
| | type: 'array', |
| | items: { type: 'string' }, |
| | }, |
| | startHere: { |
| | type: 'array', |
| | items: { type: 'string' }, |
| | }, |
| | guideCards: { |
| | type: 'array', |
| | items: { type: 'string' }, |
| | }, |
| | popular: { |
| | type: 'array', |
| | items: { type: 'string' }, |
| | }, |
| | |
| | popularHeading: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | videos: { |
| | type: 'array', |
| | items: { |
| | type: 'object', |
| | properties: { |
| | title: { |
| | type: 'string', |
| | }, |
| | href: { |
| | type: 'string', |
| | }, |
| | }, |
| | }, |
| | }, |
| | |
| | videosHeading: { |
| | type: 'string', |
| | }, |
| | }, |
| | }, |
| | |
| | changelog: { |
| | type: 'object', |
| | properties: { |
| | label: { type: 'string' }, |
| | prefix: { type: 'string' }, |
| | }, |
| | }, |
| | audience: { |
| | type: 'array', |
| | items: { |
| | type: 'string', |
| | enum: ['builder', 'driver'], |
| | }, |
| | }, |
| | |
| | |
| | |
| | type: { |
| | type: 'string', |
| | enum: guideTypes, |
| | }, |
| | |
| | contentType: { |
| | type: 'string', |
| | enum: contentTypesEnum, |
| | }, |
| | topics: { |
| | type: 'array', |
| | }, |
| | includeGuides: { |
| | type: 'array', |
| | }, |
| | learningTracks: { |
| | type: 'array', |
| | }, |
| | |
| | journeyTracks: { |
| | type: 'array', |
| | items: { |
| | type: 'object', |
| | required: ['id', 'title', 'guides'], |
| | properties: { |
| | id: { |
| | type: 'string', |
| | description: 'Unique identifier for the journey track', |
| | }, |
| | title: { |
| | type: 'string', |
| | translatable: true, |
| | description: 'Display title for the journey track', |
| | }, |
| | description: { |
| | type: 'string', |
| | translatable: true, |
| | description: 'Optional description for the journey track', |
| | }, |
| | guides: { |
| | type: 'array', |
| | items: { |
| | type: 'string', |
| | }, |
| | description: 'Array of article paths that make up this journey track', |
| | }, |
| | }, |
| | additionalProperties: false, |
| | }, |
| | description: 'Array of journey tracks for journey landing pages', |
| | }, |
| | |
| | beta_product: { |
| | type: 'boolean', |
| | }, |
| | |
| | product_video: { |
| | type: 'string', |
| | }, |
| | |
| | product_video_transcript: { |
| | type: 'string', |
| | }, |
| | |
| | heroImage: { |
| | type: 'string', |
| | }, |
| | interactive: { |
| | type: 'boolean', |
| | }, |
| | communityRedirect: { |
| | type: 'object', |
| | properties: { |
| | name: { |
| | type: 'string', |
| | }, |
| | href: { |
| | type: 'string', |
| | }, |
| | }, |
| | }, |
| | |
| | defaultPlatform: { |
| | type: 'string', |
| | enum: ['mac', 'windows', 'linux'], |
| | }, |
| | |
| | |
| | defaultTool: { |
| | type: 'string', |
| | enum: Object.keys(allTools), |
| | }, |
| | |
| | childGroups: { |
| | type: 'array', |
| | }, |
| | |
| | children: { |
| | type: 'array', |
| | }, |
| | |
| | externalProducts: { |
| | type: 'object', |
| | required: ['electron'], |
| | properties: { |
| | electron: { |
| | type: 'object', |
| | required: ['id', 'name', 'href', 'external'], |
| | properties: { |
| | id: { type: 'string' }, |
| | name: { type: 'string' }, |
| | href: { type: 'string', format: 'url' }, |
| | external: { type: 'boolean' }, |
| | }, |
| | }, |
| | }, |
| | }, |
| | |
| | hasExperimentalAlternative: { |
| | type: 'boolean', |
| | }, |
| | |
| | |
| | 'ms.openlocfilehash': { |
| | type: 'string', |
| | }, |
| | 'ms.sourcegitcommit': { |
| | type: 'string', |
| | }, |
| | 'ms.translationtype': { |
| | type: 'string', |
| | }, |
| | 'ms.contentlocale': { |
| | type: 'string', |
| | }, |
| | 'ms.lasthandoff': { |
| | type: 'string', |
| | }, |
| | 'ms.locfileid': { |
| | type: 'string', |
| | }, |
| | autogenerated: { |
| | type: 'string', |
| | enum: ['audit-logs', 'codeql-cli', 'github-apps', 'graphql', 'rest', 'webhooks'], |
| | }, |
| | |
| | category: { |
| | type: 'array', |
| | errorMessage: `must be an array, which is written in frontmatter like: |
| | category: |
| | - Category Name`, |
| | }, |
| | complexity: { |
| | type: 'array', |
| | }, |
| | industry: { |
| | type: 'array', |
| | }, |
| | octicon: { |
| | type: 'string', |
| | }, |
| | |
| | |
| | sidebarLink: { |
| | type: 'object', |
| | required: ['text', 'href'], |
| | properties: { |
| | text: { |
| | type: 'string', |
| | translatable: true, |
| | }, |
| | href: { |
| | type: 'string', |
| | }, |
| | }, |
| | }, |
| | |
| | spotlight: { |
| | type: 'array', |
| | items: { |
| | type: 'object', |
| | required: ['article', 'image'], |
| | properties: { |
| | article: { |
| | type: 'string', |
| | description: 'Path to the article to spotlight', |
| | }, |
| | image: { |
| | type: 'string', |
| | description: 'Path to image for the spotlight card', |
| | }, |
| | }, |
| | additionalProperties: false, |
| | }, |
| | description: 'Array of articles to feature in the spotlight section', |
| | }, |
| | |
| | recommended: { |
| | type: 'array', |
| | minItems: 3, |
| | maxItems: 9, |
| | description: 'Array of articles to feature in the carousel section', |
| | }, |
| | |
| | includedCategories: { |
| | type: 'array', |
| | items: { |
| | type: 'string', |
| | }, |
| | description: 'Array of category names to include in the article grid dropdown filter', |
| | }, |
| | }, |
| | } |
| |
|
| | |
| | export const deprecatedProperties = Object.keys(schema.properties).filter((prop: string) => { |
| | return (schema.properties as Record<string, SchemaProperty>)[prop].deprecated |
| | }) |
| |
|
| | const featureVersionsProp = { |
| | feature: { |
| | type: ['string', 'array'], |
| | enum: Object.keys(getDeepDataByLanguage('features', 'en')), |
| | items: { |
| | type: 'string', |
| | }, |
| | errorMessage: |
| | 'must be the name (or names) of a feature that matches "filename" in data/features/_filename_.yml', |
| | }, |
| | } |
| |
|
| | const semverRange = { |
| | type: 'string', |
| | format: 'semver', |
| | |
| | |
| | errorMessage: 'Must be a valid SemVer range: ${0}', |
| | } |
| |
|
| | ;(schema.properties as Record<string, any>).versions = { |
| | type: ['object', 'string'], |
| | additionalProperties: false, |
| | properties: Object.values(allVersions).reduce((acc: any, versionObj) => { |
| | acc[versionObj.plan] = semverRange |
| | acc[versionObj.shortName] = semverRange |
| | return acc |
| | }, featureVersionsProp), |
| | } |
| |
|
| | export function frontmatter(markdown: string, opts: any = {}) { |
| | const defaults = { |
| | schema, |
| | } |
| |
|
| | return parse(markdown, Object.assign({}, defaults, opts)) |
| | } |
| |
|
| | |
| | frontmatter.schema = schema |
| |
|
| | export default frontmatter |
| |
|