Skip to content

Commit 9b18e6a

Browse files
committed
feat: improve dd output and add edge plugin
1 parent f6e05ba commit 9b18e6a

File tree

8 files changed

+268
-95
lines changed

8 files changed

+268
-95
lines changed

.github/workflows/test.yml

+30-30
Original file line numberDiff line numberDiff line change
@@ -20,25 +20,25 @@ jobs:
2020
node-version: [20.10.0, 21.x]
2121

2222
steps:
23-
- name: Checkout code
24-
uses: actions/checkout@v3
23+
- name: Checkout code
24+
uses: actions/checkout@v3
2525

26-
- name: Setup Node.js
27-
uses: actions/setup-node@v3
28-
with:
29-
node-version: ${{ matrix.node-version }}
26+
- name: Setup Node.js
27+
uses: actions/setup-node@v3
28+
with:
29+
node-version: ${{ matrix.node-version }}
3030

31-
- name: Install pnpm
32-
if: ${{ inputs.install-pnpm }}
33-
uses: pnpm/action-setup@v2
34-
with:
35-
version: 8.6.3
31+
- name: Install pnpm
32+
if: ${{ inputs.install-pnpm }}
33+
uses: pnpm/action-setup@v2
34+
with:
35+
version: 8.6.3
3636

37-
- name: Install dependencies
38-
run: npm install
37+
- name: Install dependencies
38+
run: npm install
3939

40-
- name: Run tests
41-
run: npm test
40+
- name: Run tests
41+
run: npm test
4242

4343
test_windows:
4444
if: ${{ !inputs.disable-windows }}
@@ -48,22 +48,22 @@ jobs:
4848
node-version: [20.10.0, 21.x]
4949

5050
steps:
51-
- name: Checkout code
52-
uses: actions/checkout@v3
51+
- name: Checkout code
52+
uses: actions/checkout@v3
5353

54-
- name: Setup Node.js
55-
uses: actions/setup-node@v3
56-
with:
57-
node-version: ${{ matrix.node-version }}
54+
- name: Setup Node.js
55+
uses: actions/setup-node@v3
56+
with:
57+
node-version: ${{ matrix.node-version }}
5858

59-
- name: Install pnpm
60-
if: ${{ inputs.install-pnpm }}
61-
uses: pnpm/action-setup@v2
62-
with:
63-
version: 8.6.3
59+
- name: Install pnpm
60+
if: ${{ inputs.install-pnpm }}
61+
uses: pnpm/action-setup@v2
62+
with:
63+
version: 8.6.3
6464

65-
- name: Install dependencies
66-
run: npm install
65+
- name: Install dependencies
66+
run: npm install
6767

68-
- name: Run tests
69-
run: npm test
68+
- name: Run tests
69+
run: npm test

index.ts

+5
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,11 @@ export const errors: typeof encryptionErrors &
3838
* Youch terminal
3939
*/
4040
export async function prettyPrintError(error: any) {
41+
if (error && typeof error === 'object' && error.code === 'E_DUMP_DIE_EXCEPTION') {
42+
console.error(error)
43+
return
44+
}
45+
4146
// @ts-expect-error
4247
const { default: youchTerminal } = await import('youch-terminal')
4348
const { default: Youch } = await import('youch')

modules/dumper/dumper.ts

+106-9
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
* file that was distributed with this source code.
88
*/
99

10+
import { styleText } from 'node:util'
1011
import { dump as consoleDump } from '@poppinss/dumper/console'
1112
import type { HTMLDumpConfig } from '@poppinss/dumper/html/types'
1213
import type { ConsoleDumpConfig } from '@poppinss/dumper/console/types'
@@ -43,12 +44,16 @@ const DUMP_TITLE_STYLES = `
4344
border-top-right-radius: 0;
4445
}`
4546

47+
const IDE = process.env.ADONIS_IDE ?? process.env.EDITOR ?? ''
48+
4649
/**
47-
* Dumper exposes the API to dump or die/dump values via your
50+
* Dumper exposes the API to dump or die/dump values in your
4851
* AdonisJS application. An singleton instance of the Dumper
4952
* is shared as a service and may use it follows.
5053
*
5154
* ```ts
55+
* const dumper = container.make('dumper')
56+
*
5257
* dumper.configureHtmlOutput({
5358
* // parser + html formatter config
5459
* })
@@ -62,20 +67,62 @@ const DUMP_TITLE_STYLES = `
6267
*
6368
* // Returns style and script tags that must be
6469
* // injeted to the head of the HTML document
70+
*
6571
* const head = dumper.getHeadElements()
6672
* ```
6773
*/
6874
export class Dumper {
6975
#app: Application<any>
76+
77+
/**
78+
* Configuration for the HTML formatter
79+
*/
7080
#htmlConfig: HTMLDumpConfig = {}
81+
82+
/**
83+
* Configuration for the Console formatter
84+
*/
7185
#consoleConfig: ConsoleDumpConfig = {
7286
collapse: ['DateTime', 'Date'],
7387
}
7488

89+
/**
90+
* A collections of known editors to create URLs to open
91+
* them
92+
*/
93+
#editors: Record<string, string> = {
94+
textmate: 'txmt://open?url=file://%f&line=%l',
95+
macvim: 'mvim://open?url=file://%f&line=%l',
96+
emacs: 'emacs://open?url=file://%f&line=%l',
97+
sublime: 'subl://open?url=file://%f&line=%l',
98+
phpstorm: 'phpstorm://open?file=%f&line=%l',
99+
atom: 'atom://core/open/file?filename=%f&line=%l',
100+
vscode: 'vscode://file/%f:%l',
101+
}
102+
75103
constructor(app: Application<any>) {
76104
this.#app = app
77105
}
78106

107+
/**
108+
* Returns the link to open the file using dd inside one
109+
* of the known code editors
110+
*/
111+
#getEditorLink(source?: {
112+
location: string
113+
line: number
114+
}): { href: string; text: string } | undefined {
115+
const editorURL = this.#editors[IDE] || IDE
116+
if (!editorURL || !source) {
117+
return
118+
}
119+
120+
return {
121+
href: editorURL.replace('%f', source.location).replace('%l', String(source.line)),
122+
text: `${this.#app.relativePath(source.location)}:${source.line}`,
123+
}
124+
}
125+
79126
/**
80127
* Configure the HTML formatter output
81128
*/
@@ -98,7 +145,7 @@ export class Dumper {
98145
*/
99146
getHeadElements(cspNonce?: string): string {
100147
return (
101-
'<style id="dumper-styles">' +
148+
`<style id="dumper-styles">` +
102149
createStyleSheet() +
103150
DUMP_TITLE_STYLES +
104151
'</style>' +
@@ -111,28 +158,78 @@ export class Dumper {
111158
/**
112159
* Dump value to HTML ouput
113160
*/
114-
dumpToHtml(value: unknown, cspNonce?: string) {
115-
return dump(value, { cspNonce, ...this.#htmlConfig })
161+
dumpToHtml(
162+
value: unknown,
163+
options: {
164+
cspNonce?: string
165+
title?: string
166+
source?: {
167+
location: string
168+
line: number
169+
}
170+
} = {}
171+
) {
172+
const link = this.#getEditorLink(options.source) ?? null
173+
const title = options.title || 'DUMP'
174+
175+
return (
176+
'<div class="adonisjs-dump-header">' +
177+
`<span class="adonisjs-dump-header-title">${title}</span>` +
178+
(link ? `<a href="${link.href}" class="adonisjs-dump-header-source">${link.text}</a>` : '') +
179+
'</div>' +
180+
dump(value, { cspNonce: options.cspNonce, ...this.#htmlConfig })
181+
)
116182
}
117183

118184
/**
119185
* Dump value to ANSI output
120186
*/
121-
dumpToAnsi(value: unknown) {
122-
return consoleDump(value, this.#consoleConfig)
187+
dumpToAnsi(
188+
value: unknown,
189+
options: {
190+
title?: string
191+
source?: {
192+
location: string
193+
line: number
194+
}
195+
} = {}
196+
) {
197+
const columns = process.stdout.columns
198+
199+
/**
200+
* Link to the source file
201+
*/
202+
const link = `${this.#getEditorLink(options.source)?.text ?? ''} `
203+
204+
/**
205+
* Dump title
206+
*/
207+
const title = ` ${options.title || 'DUMP'}`
208+
209+
/**
210+
* Whitespace between the title and the link to align them
211+
* on each side of x axis
212+
*/
213+
const whiteSpace = new Array(columns - link.length - title.length - 4).join(' ')
214+
215+
/**
216+
* Styled heading with background color and bold text
217+
*/
218+
const heading = styleText('bgRed', styleText('bold', `${title}${whiteSpace}${link}`))
219+
220+
return `${heading}\n${consoleDump(value, this.#consoleConfig)}`
123221
}
124222

125223
/**
126224
* Dump values and die. The formatter will be picked
127225
* based upon where your app is running.
128226
*
129-
* - In CLI commands, the ANSI output will be printed
130-
* to the console.
131227
* - During an HTTP request, the HTML output will be
132228
* sent to the server.
229+
* - Otherwise the value will be logged in the console
133230
*/
134231
dd(value: unknown, traceSourceIndex: number = 1) {
135-
const error = new E_DUMP_DIE_EXCEPTION(value, this, this.#app)
232+
const error = new E_DUMP_DIE_EXCEPTION(value, this)
136233
error.setTraceSourceIndex(traceSourceIndex)
137234
throw error
138235
}

0 commit comments

Comments
 (0)