| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * Copyright (c) Microsoft Corporation. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * 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. | 
					
						
							|  |  |  |  */ | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  | 
 | 
					
						
							|  |  |  | /** @typedef {'Types'|'ReleaseNotesMd'} OutputType */ | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  | // @ts-check
 | 
					
						
							|  |  |  | const toKebabCase = require('lodash/kebabCase.js') | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  | const Documentation = require('./documentation'); | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  | function createMarkdownLink(languagePath, member, text) { | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  |   const className = toKebabCase(member.clazz.name); | 
					
						
							|  |  |  |   const memberName = toKebabCase(member.name); | 
					
						
							|  |  |  |   let hash = null; | 
					
						
							|  |  |  |   if (member.kind === 'property' || member.kind === 'method') | 
					
						
							|  |  |  |     hash = `${className}-${memberName}`.toLowerCase(); | 
					
						
							|  |  |  |   else if (member.kind === 'event') | 
					
						
							|  |  |  |     hash = `${className}-event-${memberName}`.toLowerCase(); | 
					
						
							|  |  |  |   return `[${text}](https://playwright.dev${languagePath}/docs/api/class-${member.clazz.name.toLowerCase()}#${hash})`; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {string} languagePath | 
					
						
							|  |  |  |  * @param {Documentation.Class} clazz | 
					
						
							|  |  |  |  * @returns {string} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function createClassMarkdownLink(languagePath, clazz) { | 
					
						
							|  |  |  |   return `[${clazz.name}](https://playwright.dev${languagePath}/docs/api/class-${clazz.name.toLowerCase()})`; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  | /** | 
					
						
							|  |  |  |  * @param {string} language  | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  |  * @param {OutputType} outputType | 
					
						
							|  |  |  |  * @returns {Documentation.Renderer} | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  | function docsLinkRendererForLanguage(language, outputType) { | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  |   const languagePath = languageToRelativeDocsPath(language); | 
					
						
							|  |  |  |   return ({ clazz, member, param, option }) => { | 
					
						
							|  |  |  |     if (param) | 
					
						
							|  |  |  |       return `\`${param}\``; | 
					
						
							|  |  |  |     if (option) | 
					
						
							|  |  |  |       return `\`${option}\``; | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  |     if (clazz) { | 
					
						
							|  |  |  |       if (outputType === 'Types') | 
					
						
							|  |  |  |         return `{@link ${clazz.name}}`; | 
					
						
							|  |  |  |       if (outputType === 'ReleaseNotesMd') | 
					
						
							|  |  |  |         return createClassMarkdownLink(languagePath, clazz); | 
					
						
							|  |  |  |       throw new Error(`Unexpected output type ${outputType}`); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  |     if (!member || !member.clazz) | 
					
						
							|  |  |  |       throw new Error('Internal error'); | 
					
						
							|  |  |  |     const className = member.clazz.varName === 'playwrightAssertions' ? '' : member.clazz.varName + '.'; | 
					
						
							| 
									
										
										
										
											2024-05-06 16:00:24 -07:00
										 |  |  |     if (member.kind === 'method') { | 
					
						
							|  |  |  |       const args = outputType === 'ReleaseNotesMd' ? '' : renderJSSignature(member.argsArray); | 
					
						
							|  |  |  |       return createMarkdownLink(languagePath, member, `${formatClassName(className, language)}${member.alias}(${args})`); | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  |     if (member.kind === 'event') | 
					
						
							|  |  |  |       return createMarkdownLink(languagePath, member, `${className}on('${member.alias.toLowerCase()}')`); | 
					
						
							|  |  |  |     if (member.kind === 'property') | 
					
						
							|  |  |  |       return createMarkdownLink(languagePath, member, `${className}${member.alias}`); | 
					
						
							|  |  |  |     throw new Error('Unknown member kind ' + member.kind); | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function languageToRelativeDocsPath(language) { | 
					
						
							|  |  |  |   if (language === 'js') | 
					
						
							|  |  |  |     return ''; | 
					
						
							|  |  |  |   if (language === 'csharp') | 
					
						
							|  |  |  |     return '/dotnet'; | 
					
						
							|  |  |  |   if (language === 'python') | 
					
						
							|  |  |  |     return '/python'; | 
					
						
							|  |  |  |   if (language === 'java') | 
					
						
							|  |  |  |     return '/java'; | 
					
						
							|  |  |  |   throw new Error('Unexpected language ' + language); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function formatClassName(className, language) { | 
					
						
							|  |  |  |   if (!className.endsWith('Assertions.')) | 
					
						
							|  |  |  |     return className; | 
					
						
							|  |  |  |   className = className.substring(0, className.length - 1) | 
					
						
							|  |  |  |   if (language === 'js') | 
					
						
							|  |  |  |     return `expect(${assertionArgument(className)}).`; | 
					
						
							|  |  |  |   else if (language === 'csharp') | 
					
						
							|  |  |  |     return `Expect(${assertionArgument(className)}).`; | 
					
						
							|  |  |  |   else if (language === 'python') | 
					
						
							|  |  |  |     return `expect(${assertionArgument(className)}).`; | 
					
						
							|  |  |  |   else if (language === 'java') | 
					
						
							|  |  |  |     return `assertThat(${assertionArgument(className)}).`; | 
					
						
							|  |  |  |   throw new Error('Unexpected language ' + language); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | function assertionArgument(className) { | 
					
						
							|  |  |  |   switch (className.toLowerCase()) { | 
					
						
							|  |  |  |     case 'locatorassertions': return 'locator'; | 
					
						
							|  |  |  |     case 'pageassertions': return 'page'; | 
					
						
							|  |  |  |     case 'genericassertions': return 'value'; | 
					
						
							|  |  |  |     case 'snapshotassertions': return 'value'; | 
					
						
							|  |  |  |     case 'apiresponseassertions': return 'response'; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   throw new Error(`Unexpected assertion class: ${className}`); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							| 
									
										
										
										
											2024-04-10 10:05:54 -07:00
										 |  |  |  * @param {Documentation.Member[]} args | 
					
						
							| 
									
										
										
										
											2023-10-16 11:23:22 +02:00
										 |  |  |  */ | 
					
						
							|  |  |  | function renderJSSignature(args) { | 
					
						
							|  |  |  |   const tokens = []; | 
					
						
							|  |  |  |   let hasOptional = false; | 
					
						
							|  |  |  |   for (const arg of args) { | 
					
						
							|  |  |  |     const name = arg.alias; | 
					
						
							|  |  |  |     const optional = !arg.required; | 
					
						
							|  |  |  |     if (tokens.length) { | 
					
						
							|  |  |  |       if (optional && !hasOptional) | 
					
						
							|  |  |  |         tokens.push(`[, ${name}`); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         tokens.push(`, ${name}`); | 
					
						
							|  |  |  |     } else { | 
					
						
							|  |  |  |       if (optional && !hasOptional) | 
					
						
							|  |  |  |         tokens.push(`[${name}`); | 
					
						
							|  |  |  |       else | 
					
						
							|  |  |  |         tokens.push(`${name}`); | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  |     hasOptional = hasOptional || optional; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   if (hasOptional) | 
					
						
							|  |  |  |     tokens.push(']'); | 
					
						
							|  |  |  |   return tokens.join(''); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /** | 
					
						
							|  |  |  |  * @param {string} content | 
					
						
							|  |  |  |  * @param {string} languagePath | 
					
						
							|  |  |  |  * @param {string} relativePath | 
					
						
							|  |  |  |  * @returns {string} | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | function renderPlaywrightDevLinks(content, languagePath, relativePath) { | 
					
						
							|  |  |  |   return content.replace(/\[([^\]]+)\]\((\.[^\)]+)\)/g, (match, p1, p2) => { | 
					
						
							|  |  |  |     return `[${p1}](${new URL(p2.replace('.md', ''), `https://playwright.dev${languagePath}/docs${relativePath}/`).toString()})`; | 
					
						
							|  |  |  |   }); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | module.exports = { | 
					
						
							|  |  |  |   docsLinkRendererForLanguage, | 
					
						
							|  |  |  |   renderPlaywrightDevLinks, | 
					
						
							|  |  |  |   languageToRelativeDocsPath, | 
					
						
							|  |  |  | } |