docs: support code block titles (#22068)
Fixes https://github.com/microsoft/playwright/issues/21461
This commit is contained in:
parent
026e49b076
commit
0c4eedbabe
|
|
@ -31,7 +31,7 @@ timeouts and racy checks in their tests altogether.
|
||||||
|
|
||||||
Take a look at the following example to see how to write a test.
|
Take a look at the following example to see how to write a test.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
import { test, expect } from '@playwright/test';
|
import { test, expect } from '@playwright/test';
|
||||||
|
|
||||||
test('has title', async ({ page }) => {
|
test('has title', async ({ page }) => {
|
||||||
|
|
@ -152,7 +152,7 @@ Here is the list of the most popular async assertions. Note that there are [many
|
||||||
|
|
||||||
Playwright Test is based on the concept of [test fixtures](./test-fixtures.md) such as the [built in page fixture](./test-fixtures#built-in-fixtures), which is passed into your test. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.
|
Playwright Test is based on the concept of [test fixtures](./test-fixtures.md) such as the [built in page fixture](./test-fixtures#built-in-fixtures), which is passed into your test. Pages are isolated between tests due to the Browser Context, which is equivalent to a brand new browser profile, where every test gets a fresh environment, even when multiple tests run in a single Browser.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
test('basic test', async ({ page }) => {
|
test('basic test', async ({ page }) => {
|
||||||
...
|
...
|
||||||
```
|
```
|
||||||
|
|
@ -161,7 +161,7 @@ test('basic test', async ({ page }) => {
|
||||||
|
|
||||||
You can use various [test hooks](./api/class-test.md) such as `test.describe` to declare a group of tests and `test.beforeEach` and `test.afterEach` which are executed before/after each test. Other hooks include the `test.beforeAll` and `test.afterAll` which are executed once per worker before/after all tests.
|
You can use various [test hooks](./api/class-test.md) such as `test.describe` to declare a group of tests and `test.beforeEach` and `test.afterEach` which are executed before/after each test. Other hooks include the `test.beforeAll` and `test.afterAll` which are executed once per worker before/after all tests.
|
||||||
|
|
||||||
```js
|
```js title="tests/example.spec.ts"
|
||||||
import { test, expect } from "@playwright/test";
|
import { test, expect } from "@playwright/test";
|
||||||
|
|
||||||
test.describe("navigation", () => {
|
test.describe("navigation", () => {
|
||||||
|
|
|
||||||
|
|
@ -45,6 +45,7 @@
|
||||||
* type: 'code',
|
* type: 'code',
|
||||||
* lines: string[],
|
* lines: string[],
|
||||||
* codeLang: string,
|
* codeLang: string,
|
||||||
|
* title?: string,
|
||||||
* }} MarkdownCodeNode */
|
* }} MarkdownCodeNode */
|
||||||
|
|
||||||
/** @typedef {MarkdownBaseNode & {
|
/** @typedef {MarkdownBaseNode & {
|
||||||
|
|
@ -163,11 +164,13 @@ function buildTree(lines) {
|
||||||
// Remaining items respect indent-based nesting.
|
// Remaining items respect indent-based nesting.
|
||||||
const [, indent, content] = /** @type {string[]} */ (line.match('^([ ]*)(.*)'));
|
const [, indent, content] = /** @type {string[]} */ (line.match('^([ ]*)(.*)'));
|
||||||
if (content.startsWith('```')) {
|
if (content.startsWith('```')) {
|
||||||
|
const [codeLang, title] = parseCodeBlockMetadata(content);
|
||||||
/** @type {MarkdownNode} */
|
/** @type {MarkdownNode} */
|
||||||
const node = {
|
const node = {
|
||||||
type: 'code',
|
type: 'code',
|
||||||
lines: [],
|
lines: [],
|
||||||
codeLang: content.substring(3)
|
codeLang,
|
||||||
|
title,
|
||||||
};
|
};
|
||||||
line = lines[++i];
|
line = lines[++i];
|
||||||
while (!line.trim().startsWith('```')) {
|
while (!line.trim().startsWith('```')) {
|
||||||
|
|
@ -249,6 +252,18 @@ function buildTree(lines) {
|
||||||
return root.children;
|
return root.children;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {String} firstLine
|
||||||
|
* @returns {[string, string|undefined]}
|
||||||
|
*/
|
||||||
|
function parseCodeBlockMetadata(firstLine) {
|
||||||
|
const withoutBackticks = firstLine.substring(3);
|
||||||
|
const match = withoutBackticks.match(/ title="(.+)"$/);
|
||||||
|
if (match)
|
||||||
|
return [withoutBackticks.substring(0, match.index), match[1]];
|
||||||
|
return [withoutBackticks, undefined];
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} content
|
* @param {string} content
|
||||||
*/
|
*/
|
||||||
|
|
@ -312,7 +327,7 @@ function innerRenderMdNode(indent, node, lastNode, result, options) {
|
||||||
|
|
||||||
if (node.type === 'code') {
|
if (node.type === 'code') {
|
||||||
newLine();
|
newLine();
|
||||||
result.push(`${indent}\`\`\`${node.codeLang}`);
|
result.push(`${indent}\`\`\`${node.codeLang}${node.title ? ' title="' + node.title + '"' : ''}`);
|
||||||
for (const line of node.lines)
|
for (const line of node.lines)
|
||||||
result.push(indent + line);
|
result.push(indent + line);
|
||||||
result.push(`${indent}\`\`\``);
|
result.push(`${indent}\`\`\``);
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue