Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -80,6 +80,8 @@ function PageSegmentTreeLayerPresentation({
{folderName && (
<span className="segment-explorer-filename--path">
{folderName}
{/* hidden slashes for testing snapshots */}
<small>{'/'}</small>
</span>
)}
<span className="segment-explorer-filename--name">
Expand Down Expand Up @@ -151,6 +153,9 @@ export const DEV_TOOLS_INFO_RENDER_FILES_STYLES = css`
.segment-explorer-filename--path {
margin-right: 8px;
}
.segment-explorer-filename--path small {
width: 0;
}
.segment-explorer-filename--name {
color: var(--color-gray-800);
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ describe('Segment Explorer', () => {
})
})

test.failing('remove node in the middle', () => {
test('remove node in the middle', () => {
insertSegmentNode({ pagePath: '/a/b/@sidebar/page.js', type: 'page' })
insertSegmentNode({ pagePath: '/a/b/page.js', type: 'page' })
insertSegmentNode({ pagePath: '/a/b/layout.js', type: 'layout' })
Expand Down
42 changes: 35 additions & 7 deletions packages/next/src/next-devtools/dev-overlay/segment-explorer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,11 @@ const createSegmentTreeStore = (): {
const { subscribe, getSnapshot, getServerSnapshot } = createSegmentTreeStore()

function createTrie<Value = string>({
getKey = (k) => k as unknown as string,
getCharacters = (item: Value) => [item] as string[],
compare = (a: Value | undefined, b: Value | undefined) => a === b,
}: {
getKey: (k: Value) => string
getCharacters?: (item: Value) => string[]
compare?: (a: Value | undefined, b: Value | undefined) => boolean
}): Trie<Value> {
const root: TrieNode<Value> = {
value: undefined,
Expand All @@ -72,8 +74,7 @@ function createTrie<Value = string>({

function insert(value: Value) {
let currentNode = root
const key = getKey(value)
const segments = key.split('/')
const segments = getCharacters(value)

for (const segment of segments) {
if (!currentNode.children[segment]) {
Expand All @@ -91,8 +92,31 @@ function createTrie<Value = string>({
markUpdated()
}

function remove(_: Value) {
// TODO Implement remove functionality
function remove(value: Value) {
let currentNode = root
const segments = getCharacters(value)
const stack: TrieNode<Value>[] = []
let found = true
for (const segment of segments) {
if (!currentNode.children[segment]) {
found = false
break
}
stack.push(currentNode)
currentNode = currentNode.children[segment]!
}
// If the value is not found, skip removal
if (!found || !compare(currentNode.value, value)) {
return
}
currentNode.value = undefined
for (let i = stack.length - 1; i >= 0; i--) {
const parentNode = stack[i]
const segment = segments[i]
if (Object.keys(parentNode.children[segment]!.children).length === 0) {
delete parentNode.children[segment]
}
}

markUpdated()
}
Expand All @@ -113,7 +137,11 @@ export type SegmentTrie = Trie<SegmentNode>
export type SegmentTrieNode = TrieNode<SegmentNode>

const trie: SegmentTrie = createTrie({
getKey: (item) => item.pagePath,
compare: (a, b) => {
if (!a || !b) return false
return a.pagePath === b.pagePath && a.type === b.type
},
getCharacters: (item) => item.pagePath.split('/'),
})
export const insertSegmentNode = trie.insert
export const removeSegmentNode = trie.remove
Expand Down
34 changes: 16 additions & 18 deletions test/development/app-dir/segment-explorer/segment-explorer.test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,44 +26,42 @@ describe('segment-explorer', () => {
it('should render the segment explorer for parallel routes', async () => {
const browser = await next.browser('/parallel-routes')
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
"applayout.tsx
parallel-routeslayout.tsx
parallel-routespage.tsx
@barlayout.tsx
@barpage.tsx
@foolayout.tsx
@foopage.tsx"
"app/layout.tsx
parallel-routes/layout.tsx
parallel-routes/page.tsx
@bar/layout.tsx
@bar/page.tsx
@foo/layout.tsx
@foo/page.tsx"
`)
})

it('should render the segment explorer for nested routes', async () => {
const browser = await next.browser('/blog/~/grid')
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
"applayout.tsx
(v2)layout.tsx
(team)layout.tsx
(overview)layout.tsx
gridpage.tsx"
"app/layout.tsx
(v2)/layout.tsx
(team)/layout.tsx
(overview)/layout.tsx
grid/page.tsx"
`)
})

it('should cleanup on soft navigation', async () => {
const browser = await next.browser('/soft-navigation/a')
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
"applayout.tsx
apage.tsx"
"app/layout.tsx
a/page.tsx"
`)

await browser.elementByCss('[href="/soft-navigation/b"]').click()
await retry(async () => {
expect(await browser.elementByCss('body').text()).toContain('Page B')
})

// FIXME: Should no longer contain /soft-navigation/a/page.js
expect(await getSegmentExplorerContent(browser)).toMatchInlineSnapshot(`
"applayout.tsx
apage.tsx
bpage.tsx"
"app/layout.tsx
b/page.tsx"
`)
})
})