1
0
mirror of https://github.com/ianstormtaylor/slate.git synced 2025-08-28 01:19:52 +02:00

Compare only decorations offsets in MemoizedText. Code highlighting example improvements. (#5271)

* add basePath prop to Range inside slate-react custom types, calculate absolute ranges on passing them into TextComponent

* code highlighting example improvements, minor markdown preview refactoring

* changeset added

* Revert "add basePath prop to Range inside slate-react custom types, calculate absolute ranges on passing them into TextComponent"

This reverts commit afa085c289bc67ce3d27dd33b1f074ab8153efe8.

* add basePath prop to Point inside slate-react custom types, resolve relative ranges on passing them to TextComponent

* Update changeset

* linter fixes

* remove redundant checks inside renderElement function

* custom types fixes for Range and Point in examples

* wrap intervals and ranges extractors in useMemo hook for running them only if editor.children is changed

* revert basePath changes, compare only offsets for MemoizedText decorations

* use an element as a key in decorations ranges map instead of id

* simplify code highlighting implementation, make code block nested

* fix code-highlighting example, add toolbar code block button

* remove redundant code

* fix code highlighting playwright integration test
This commit is contained in:
Sergei Dedkov
2023-02-10 00:53:21 +06:00
committed by GitHub
parent 7d1e60b88f
commit 9635b992a0
11 changed files with 782 additions and 272 deletions

View File

@@ -1,57 +1,122 @@
import { test, expect } from '@playwright/test'
import { test, expect, Page } from '@playwright/test'
test.describe('code highlighting', () => {
const slateEditor = '[data-slate-node="element"]'
const leafNode = 'span[data-slate-leaf="true"]'
test.beforeEach(async ({ page }) => {
page.goto('http://localhost:3000/examples/code-highlighting')
})
test('highlights HTML tags', async ({ page }) => {
const outer = page
.locator(slateEditor)
.locator('span')
.nth(0)
.locator(leafNode)
.nth(0)
await expect(await outer.textContent()).toContain('<h1>')
await expect(outer).toHaveCSS('color', 'rgb(153, 0, 85)')
})
for (const testCase of getTestCases()) {
const { language, content, highlights } = testCase
test('highlights javascript syntax', async ({ page }) => {
const JSCode = 'const slateVar = 30;'
await page.locator('select').selectOption('JavaScript') // Select the 'JavaScript' option
await expect(await page.locator('select').inputValue()).toBe('js') // Confirm value to avoid race condition
test(`code highlighting ${language}`, async ({ page }) => {
await setText(page, content, language)
await page.locator(slateEditor).click() // focus on the editor
const isMac = await page.evaluate(() => {
return /Mac|iPhone|iPod|iPad/i.test(navigator.platform)
const tokens = await page
.locator('[data-slate-editor] [data-slate-string]')
.all()
for (const [index, token] of tokens.entries()) {
const highlight = highlights[index]
const textContent = await token.textContent()
await expect(textContent).toEqual(highlight[0])
await expect(token).toHaveCSS('color', highlight[1])
}
})
if (isMac) {
await page.keyboard.press('Meta+A')
} else {
await page.keyboard.press('Control+A')
}
await page.keyboard.type(JSCode) // Type JavaScript code
await page.keyboard.press('Enter')
expect(
await page
.locator(slateEditor)
.locator('span')
.nth(0)
.locator(leafNode)
.nth(0)
.textContent()
).toContain('const')
await expect(
page
.locator(slateEditor)
.locator('span')
.nth(0)
.locator(leafNode)
.nth(0)
).toHaveCSS('color', 'rgb(0, 119, 170)')
})
}
})
// it also tests if select and code block button works the right way
async function setText(page: Page, text: string, language: string) {
await page.locator('[data-slate-editor]').fill('') // clear editor
await page.getByTestId('code-block-button').click() // convert first and the only one paragraph to code block
await page.getByTestId('language-select').selectOption({ value: language }) // select the language option
await page.keyboard.type(text) // type text
}
function getTestCases() {
const testCases: {
language: string
content: string
highlights: [string, string][]
}[] = [
{
language: 'css',
content: `body {
background-color: lightblue;
}`,
highlights: [
['body', 'rgb(102, 153, 0)'],
[' ', 'rgb(0, 0, 0)'],
['{', 'rgb(153, 153, 153)'],
[' ', 'rgb(0, 0, 0)'],
['background-color', 'rgb(153, 0, 85)'],
[':', 'rgb(153, 153, 153)'],
[' lightblue', 'rgb(0, 0, 0)'],
[';', 'rgb(153, 153, 153)'],
['}', 'rgb(153, 153, 153)'],
],
},
{
language: 'html',
content: `<body>
<h1 class="title">Testing html</h1>
</body>`,
highlights: [
['<', 'rgb(153, 0, 85)'],
['body', 'rgb(153, 0, 85)'],
['>', 'rgb(153, 0, 85)'],
[' ', 'rgb(0, 0, 0)'],
['<', 'rgb(153, 0, 85)'],
['h1', 'rgb(153, 0, 85)'],
[' ', 'rgb(153, 0, 85)'],
['class', 'rgb(102, 153, 0)'],
['=', 'rgb(0, 119, 170)'],
['"', 'rgb(0, 119, 170)'],
['title', 'rgb(0, 119, 170)'],
['"', 'rgb(0, 119, 170)'],
['>', 'rgb(153, 0, 85)'],
['Testing html', 'rgb(0, 0, 0)'],
['</', 'rgb(153, 0, 85)'],
['h1', 'rgb(153, 0, 85)'],
['>', 'rgb(153, 0, 85)'],
['</', 'rgb(153, 0, 85)'],
['body', 'rgb(153, 0, 85)'],
['>', 'rgb(153, 0, 85)'],
],
},
{
language: 'jsx',
content: `<Title title="title" renderIcon={() => <Icon />} />`,
highlights: [
['<', 'rgb(153, 0, 85)'],
['Title', 'rgb(221, 74, 104)'],
[' ', 'rgb(153, 0, 85)'],
['title', 'rgb(102, 153, 0)'],
['=', 'rgb(0, 119, 170)'],
['"', 'rgb(0, 119, 170)'],
['title', 'rgb(0, 119, 170)'],
['"', 'rgb(0, 119, 170)'],
[' ', 'rgb(153, 0, 85)'],
['renderIcon', 'rgb(102, 153, 0)'],
['=', 'rgb(153, 0, 85)'],
['{', 'rgb(153, 0, 85)'],
['(', 'rgb(153, 0, 85)'],
[')', 'rgb(153, 0, 85)'],
[' ', 'rgb(153, 0, 85)'],
['=>', 'rgb(154, 110, 58)'],
[' ', 'rgb(153, 0, 85)'],
['<', 'rgb(153, 0, 85)'],
['Icon', 'rgb(221, 74, 104)'],
[' ', 'rgb(153, 0, 85)'],
['/>', 'rgb(153, 0, 85)'],
['}', 'rgb(153, 0, 85)'],
[' ', 'rgb(153, 0, 85)'],
['/>', 'rgb(153, 0, 85)'],
],
},
]
return testCases
}