chore: update changelog, bump versions and refine tests
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "mcp-extension",
|
||||
"version": "0.0.48",
|
||||
"version": "0.0.49",
|
||||
"description": "Playwright MCP Browser Extension",
|
||||
"private": true,
|
||||
"repository": {
|
||||
|
||||
@@ -1,5 +1,19 @@
|
||||
# Changelog
|
||||
|
||||
## 0.0.9
|
||||
|
||||
### Patch Changes
|
||||
|
||||
- Added `tabs` permission to extension manifest to fix `chrome.tabs` access issues
|
||||
- Implemented `toggleExtensionForActiveTab` global helper in extension background script
|
||||
- Automated extension loading and toggling in MCP tests using `chromium.launchPersistentContext`
|
||||
- Added comprehensive tests for extension lifecycle:
|
||||
- Toggling extension on new and existing pages
|
||||
- Verifying direct CDP connection to relay
|
||||
- Handling Playwright connection before extension attachment
|
||||
- Fixed `getCdpUrl` utility usage in tests
|
||||
- Updated tests to use unique URLs for better debugging
|
||||
|
||||
## 0.0.8
|
||||
|
||||
### Patch Changes
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "playwriter",
|
||||
"description": "",
|
||||
"version": "0.0.8",
|
||||
"version": "0.0.9",
|
||||
"type": "module",
|
||||
"main": "dist/index.js",
|
||||
"types": "dist/index.d.ts",
|
||||
|
||||
+24
-29
@@ -2,15 +2,27 @@ import { createMCPClient } from './mcp-client.js'
|
||||
import { describe, it, expect, beforeAll, afterAll } from 'vitest'
|
||||
import { exec } from 'node:child_process'
|
||||
import { promisify } from 'node:util'
|
||||
import { chromium } from 'playwright-core'
|
||||
import { chromium, BrowserContext } from 'playwright-core'
|
||||
import path from 'node:path'
|
||||
import fs from 'node:fs'
|
||||
import os from 'node:os'
|
||||
import { getCdpUrl } from './utils.js'
|
||||
|
||||
import { spawn } from 'node:child_process'
|
||||
|
||||
|
||||
const execAsync = promisify(exec)
|
||||
|
||||
async function getExtensionServiceWorker(context: BrowserContext) {
|
||||
let serviceWorker = context.serviceWorkers().find(sw => sw.url().startsWith('chrome-extension://'))
|
||||
if (!serviceWorker) {
|
||||
serviceWorker = await context.waitForEvent('serviceworker', {
|
||||
predicate: (sw) => sw.url().startsWith('chrome-extension://')
|
||||
})
|
||||
}
|
||||
return serviceWorker
|
||||
}
|
||||
|
||||
function js(strings: TemplateStringsArray, ...values: any[]): string {
|
||||
return strings.reduce(
|
||||
(result, str, i) => result + str + (values[i] || ''),
|
||||
@@ -52,7 +64,7 @@ describe('MCP Server Tests', () => {
|
||||
cwd: process.cwd(),
|
||||
stdio: 'inherit'
|
||||
})
|
||||
|
||||
|
||||
// Wait for port 19988 to be ready
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
let retries = 0
|
||||
@@ -73,7 +85,7 @@ describe('MCP Server Tests', () => {
|
||||
}
|
||||
}, 1000)
|
||||
})
|
||||
|
||||
|
||||
const result = await createMCPClient()
|
||||
client = result.client
|
||||
cleanup = result.cleanup
|
||||
@@ -98,7 +110,7 @@ describe('MCP Server Tests', () => {
|
||||
// Create a page to attach to
|
||||
const page = await browserContext.newPage()
|
||||
await page.goto('about:blank')
|
||||
|
||||
|
||||
// Connect the tab
|
||||
await serviceWorker.evaluate(async () => {
|
||||
// @ts-ignore
|
||||
@@ -115,7 +127,7 @@ describe('MCP Server Tests', () => {
|
||||
relayServerProcess.kill()
|
||||
}
|
||||
await killProcessOnPort(19988)
|
||||
|
||||
|
||||
if (userDataDir) {
|
||||
try {
|
||||
fs.rmSync(userDataDir, { recursive: true, force: true })
|
||||
@@ -264,21 +276,15 @@ describe('MCP Server Tests', () => {
|
||||
if (!browserContext) throw new Error('Browser not initialized')
|
||||
|
||||
// Find the correct service worker by URL
|
||||
const extensionPath = path.resolve('../extension/dist')
|
||||
let serviceWorker = browserContext.serviceWorkers().find(sw => sw.url().startsWith('chrome-extension://'))
|
||||
|
||||
if (!serviceWorker) {
|
||||
serviceWorker = await browserContext.waitForEvent('serviceworker', {
|
||||
predicate: (sw) => sw.url().startsWith('chrome-extension://')
|
||||
})
|
||||
}
|
||||
const serviceWorker = await getExtensionServiceWorker(browserContext)
|
||||
|
||||
// 1. Create a new page
|
||||
const page = await browserContext.newPage()
|
||||
const testUrl = 'https://example.com/'
|
||||
const testUrl = 'https://example.com/toggling'
|
||||
await page.goto(testUrl)
|
||||
|
||||
await page.bringToFront()
|
||||
|
||||
|
||||
// 2. Enable extension on this new tab
|
||||
// Since it's a new page, extension is not connected yet
|
||||
const result = await serviceWorker.evaluate(async () => {
|
||||
@@ -288,8 +294,7 @@ describe('MCP Server Tests', () => {
|
||||
expect(result.isConnected).toBe(true)
|
||||
|
||||
// 3. Verify we can connect via direct CDP and see the page
|
||||
const randomId = Math.random().toString(36).substring(7)
|
||||
const cdpUrl = `ws://localhost:19988/cdp/${randomId}`
|
||||
const cdpUrl = getCdpUrl()
|
||||
let directBrowser = await chromium.connectOverCDP(cdpUrl)
|
||||
let contexts = directBrowser.contexts()
|
||||
let pages = contexts[0].pages()
|
||||
@@ -310,23 +315,15 @@ describe('MCP Server Tests', () => {
|
||||
|
||||
// 5. Try to connect/use the page.
|
||||
// connecting to relay will succeed, but listing pages should NOT show our page
|
||||
// OR if we try to send command to the previous targetId (via session), it should fail
|
||||
|
||||
// Connect to relay again
|
||||
directBrowser = await chromium.connectOverCDP(cdpUrl)
|
||||
contexts = directBrowser.contexts()
|
||||
pages = contexts[0].pages() // this calls Target.getTargets internally via contexts() or pages()?
|
||||
// Actually contexts() just returns what it knows.
|
||||
// If relay sent detachedFromTarget, the page should be gone from the context.
|
||||
pages = contexts[0].pages()
|
||||
|
||||
foundPage = pages.find(p => p.url() === testUrl)
|
||||
expect(foundPage).toBeUndefined()
|
||||
|
||||
// Also try to send a command to the old target ID if possible?
|
||||
// Hard to do with high-level Playwright API on the browser object.
|
||||
// We can try to use a raw CDPSession on the browser target if we knew how to route it.
|
||||
// But checking it's gone is good enough for "connection disabled".
|
||||
|
||||
await directBrowser.close()
|
||||
|
||||
// 6. Re-enable extension
|
||||
@@ -337,9 +334,6 @@ describe('MCP Server Tests', () => {
|
||||
expect(resultEnabled.isConnected).toBe(true)
|
||||
|
||||
// 7. Verify page is back
|
||||
// Note: targetId might have changed! Fetch it again just in case, or rely on relay to update routing.
|
||||
// But relay routing is based on `sessionId`. New session ID generated on attach.
|
||||
// The URL path param `targetId` is just a label.
|
||||
|
||||
directBrowser = await chromium.connectOverCDP(cdpUrl)
|
||||
// Wait a bit for targets to populate
|
||||
@@ -359,6 +353,7 @@ describe('MCP Server Tests', () => {
|
||||
await directBrowser.close()
|
||||
await page.close()
|
||||
})
|
||||
|
||||
})
|
||||
function tryJsonParse(str: string) {
|
||||
try {
|
||||
|
||||
@@ -383,7 +383,7 @@ server.tool(
|
||||
responseText += 'Code executed successfully (no output)'
|
||||
}
|
||||
|
||||
const MAX_LENGTH = 1000
|
||||
const MAX_LENGTH = 5000
|
||||
let finalText = responseText.trim()
|
||||
if (finalText.length > MAX_LENGTH) {
|
||||
finalText = finalText.slice(0, MAX_LENGTH) + `\n\n[Truncated to ${MAX_LENGTH} characters. Better manage your logs or paginate them to read the full logs]`
|
||||
|
||||
@@ -1,318 +1,23 @@
|
||||
Return value:
|
||||
- table [ref=e3]:
|
||||
- rowgroup [ref=e4]:
|
||||
- row "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit xmorse (70) | logout" [ref=e5]:
|
||||
- cell "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit xmorse (70) | logout" [ref=e6]:
|
||||
- row "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e5]:
|
||||
- cell "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e6]:
|
||||
- table [ref=e7]:
|
||||
- rowgroup [ref=e8]:
|
||||
- row "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit xmorse (70) | logout" [ref=e9]:
|
||||
- row "Hacker Newsnew | past | comments | ask | show | jobs | submit login" [ref=e9]:
|
||||
- cell [ref=e10]:
|
||||
- link [ref=e11] [cursor=pointer]:
|
||||
- /url: https://news.ycombinator.com
|
||||
- img [ref=e12]
|
||||
- cell "Hacker Newsnew | threads | past | comments | ask | show | jobs | submit" [ref=e13]:
|
||||
- cell "Hacker Newsnew | past | comments | ask | show | jobs | submit" [ref=e13]:
|
||||
- generic [ref=e14]:
|
||||
- link "Hacker News" [ref=e16] [cursor=pointer]:
|
||||
- /url: news
|
||||
- link "new" [ref=e17] [cursor=pointer]:
|
||||
- /url: newest
|
||||
- text: "|"
|
||||
- link "threads" [ref=e18] [cursor=pointer]:
|
||||
- /url: threads?id=xmorse
|
||||
- text: "|"
|
||||
- link "past" [ref=e19] [cursor=pointer]:
|
||||
- /url: front
|
||||
- text: "|"
|
||||
- link "comments" [ref=e20] [cursor=pointer]:
|
||||
- /url: newcomments
|
||||
- text: "|"
|
||||
- link "ask" [ref=e21] [cursor=pointer]:
|
||||
- /url: ask
|
||||
- text: "|"
|
||||
- link "show" [ref=e22] [cursor=pointer]:
|
||||
- /url: show
|
||||
- text: "|"
|
||||
- link "jobs" [ref=e23] [cursor=pointer]:
|
||||
- /url: jobs
|
||||
- text: "|"
|
||||
- link "submit" [ref=e24] [cursor=pointer]:
|
||||
- /url: submit
|
||||
- cell "xmorse (70) | logout" [ref=e25]:
|
||||
- generic [ref=e26]:
|
||||
- link "xmorse" [ref=e27] [cursor=pointer]:
|
||||
- /url: user?id=xmorse
|
||||
- text: (70) |
|
||||
- link "logout" [ref=e28] [cursor=pointer]:
|
||||
- /url: logout?auth=227f860372905c327e92615af914e1e41ec43fff&goto=item%3Fid%3D1
|
||||
- row [ref=e29]
|
||||
- row [ref=e30]:
|
||||
- cell [ref=e31]:
|
||||
- table [ref=e32]:
|
||||
- rowgroup [ref=e33]:
|
||||
- row "upvote Y Combinator (ycombinator.com)" [ref=e34]:
|
||||
- cell [ref=e35]
|
||||
- cell "upvote" [ref=e36]:
|
||||
- link "upvote" [ref=e38] [cursor=pointer]:
|
||||
- /url: vote?id=1&how=up&auth=e52b391ec392eb381ace51126fd80e19d48c1d7b&goto=item%3Fid%3D1
|
||||
- generic "upvote" [ref=e39]
|
||||
- cell "Y Combinator (ycombinator.com)" [ref=e40]:
|
||||
- generic [ref=e41]:
|
||||
- link "Y Combinator" [ref=e42] [cursor=pointer]:
|
||||
- /url: http://ycombinator.com
|
||||
- generic [ref=e43]:
|
||||
- text: (
|
||||
- link "ycombinator.com" [ref=e44] [cursor=pointer]:
|
||||
- /url: from?site=ycombinator.com
|
||||
- text: )
|
||||
- row "57 points by pg on Oct 9, 2006 | hide | past | favorite | 16 comments" [ref=e45]:
|
||||
- cell [ref=e46]
|
||||
- cell "57 points by pg on Oct 9, 2006 | hide | past | favorite | 16 comments" [ref=e47]:
|
||||
- generic [ref=e48]:
|
||||
- text: 57 points by
|
||||
- link "pg" [ref=e49] [cursor=pointer]:
|
||||
- /url: user?id=pg
|
||||
- generic "2006-10-09T18:21:51 1160418111" [ref=e50]:
|
||||
- link "on Oct 9, 2006" [ref=e51] [cursor=pointer]:
|
||||
- /url: item?id=1
|
||||
- text: "|"
|
||||
- link "hide" [ref=e52] [cursor=pointer]:
|
||||
- /url: hide?id=1&auth=e52b391ec392eb381ace51126fd80e19d48c1d7b&goto=item%3Fid%3D1
|
||||
- text: "|"
|
||||
- link "past" [ref=e53] [cursor=pointer]:
|
||||
- /url: https://hn.algolia.com/?query=Y%20Combinator&type=story&dateRange=all&sort=byDate&storyText=false&prefix&page=0
|
||||
- text: "|"
|
||||
- link "favorite" [ref=e54] [cursor=pointer]:
|
||||
- /url: fave?id=1&auth=e52b391ec392eb381ace51126fd80e19d48c1d7b
|
||||
- text: "|"
|
||||
- link "16 comments" [ref=e55] [cursor=pointer]:
|
||||
- /url: item?id=1
|
||||
- row [ref=e56]:
|
||||
- cell [ref=e57]
|
||||
- cell [ref=e58]
|
||||
- table [ref=e59]:
|
||||
- rowgroup [ref=e60]:
|
||||
- row "upvote sama on Oct 9, 2006 | [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e61]:
|
||||
- cell "upvote sama on Oct 9, 2006 | [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e62]:
|
||||
- table [ref=e63]:
|
||||
- rowgroup [ref=e64]:
|
||||
- row "upvote sama on Oct 9, 2006 | [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e65]:
|
||||
- cell [ref=e66]:
|
||||
- img
|
||||
- cell "upvote" [ref=e67]:
|
||||
- link "upvote" [ref=e69] [cursor=pointer]:
|
||||
- /url: vote?id=15&how=up&auth=709295bd69cc8638fcf14a7b807bb0efabd69a2d&goto=item%3Fid%3D1#15
|
||||
- generic "upvote" [ref=e70]
|
||||
- cell "sama on Oct 9, 2006 | [–] \"the rising star of venture capital\" -unknown VC eating lunch on SHR" [ref=e71]:
|
||||
- generic [ref=e73]:
|
||||
- link "sama" [ref=e74] [cursor=pointer]:
|
||||
- /url: user?id=sama
|
||||
- generic "2006-10-09T19:51:01 1160423461" [ref=e75]:
|
||||
- link "on Oct 9, 2006" [ref=e76] [cursor=pointer]:
|
||||
- /url: item?id=15
|
||||
- generic [ref=e77]:
|
||||
- text: "|"
|
||||
- link [ref=e78] [cursor=pointer]:
|
||||
- /url: "#487171"
|
||||
- text: next
|
||||
- link "[–]" [ref=e79] [cursor=pointer]:
|
||||
- /url: javascript:void(0)
|
||||
- generic [ref=e80]:
|
||||
- generic [ref=e81]: "\"the rising star of venture capital\" -unknown VC eating lunch on SHR"
|
||||
- generic:
|
||||
- paragraph
|
||||
- row "upvote pg on Oct 9, 2006 | | [–] Is there anywhere to eat on Sandhill Road?" [ref=e82]:
|
||||
- cell "upvote pg on Oct 9, 2006 | | [–] Is there anywhere to eat on Sandhill Road?" [ref=e83]:
|
||||
- table [ref=e84]:
|
||||
- rowgroup [ref=e85]:
|
||||
- row "upvote pg on Oct 9, 2006 | | [–] Is there anywhere to eat on Sandhill Road?" [ref=e86]:
|
||||
- cell [ref=e87]:
|
||||
- img [ref=e88]
|
||||
- cell "upvote" [ref=e89]:
|
||||
- link "upvote" [ref=e91] [cursor=pointer]:
|
||||
- /url: vote?id=17&how=up&auth=3c24b126f8f812f8c3a24a0b9143eac42ca15476&goto=item%3Fid%3D1#17
|
||||
- generic "upvote" [ref=e92]
|
||||
- cell "pg on Oct 9, 2006 | | [–] Is there anywhere to eat on Sandhill Road?" [ref=e93]:
|
||||
- generic [ref=e95]:
|
||||
- link "pg" [ref=e96] [cursor=pointer]:
|
||||
- /url: user?id=pg
|
||||
- generic "2006-10-09T19:52:45 1160423565" [ref=e97]:
|
||||
- link "on Oct 9, 2006" [ref=e98] [cursor=pointer]:
|
||||
- /url: item?id=17
|
||||
- generic [ref=e99]:
|
||||
- text: "|"
|
||||
- link [ref=e100] [cursor=pointer]:
|
||||
- /url: "#15"
|
||||
- text: parent
|
||||
- text: "|"
|
||||
- link [ref=e101] [cursor=pointer]:
|
||||
- /url: "#487171"
|
||||
- text: next
|
||||
- link "[–]" [ref=e102] [cursor=pointer]:
|
||||
- /url: javascript:void(0)
|
||||
- generic [ref=e103]:
|
||||
- generic [ref=e104]: Is there anywhere to eat on Sandhill Road?
|
||||
- generic:
|
||||
- paragraph
|
||||
- row "upvote dmon on Feb 25, 2007 | | | [–] sure" [ref=e105]:
|
||||
- cell "upvote dmon on Feb 25, 2007 | | | [–] sure" [ref=e106]:
|
||||
- table [ref=e107]:
|
||||
- rowgroup [ref=e108]:
|
||||
- row "upvote dmon on Feb 25, 2007 | | | [–] sure" [ref=e109]:
|
||||
- cell [ref=e110]:
|
||||
- img [ref=e111]
|
||||
- cell "upvote" [ref=e112]:
|
||||
- link "upvote" [ref=e114] [cursor=pointer]:
|
||||
- /url: vote?id=1079&how=up&auth=851f0b1e178c46300e9d2218764827726415a50d&goto=item%3Fid%3D1#1079
|
||||
- generic "upvote" [ref=e115]
|
||||
- cell "dmon on Feb 25, 2007 | | | [–] sure" [ref=e116]:
|
||||
- generic [ref=e118]:
|
||||
- link "dmon" [ref=e119] [cursor=pointer]:
|
||||
- /url: user?id=dmon
|
||||
- generic "2007-02-25T22:18:23 1172441903" [ref=e120]:
|
||||
- link "on Feb 25, 2007" [ref=e121] [cursor=pointer]:
|
||||
- /url: item?id=1079
|
||||
- generic [ref=e122]:
|
||||
- text: "|"
|
||||
- link [ref=e123] [cursor=pointer]:
|
||||
- /url: "#15"
|
||||
- text: root
|
||||
- text: "|"
|
||||
- link [ref=e124] [cursor=pointer]:
|
||||
- /url: "#17"
|
||||
- text: parent
|
||||
- text: "|"
|
||||
- link [ref=e125] [cursor=pointer]:
|
||||
- /url: "#487171"
|
||||
- text: next
|
||||
- link "[–]" [ref=e126] [cursor=pointer]:
|
||||
- /url: javascript:void(0)
|
||||
- generic [ref=e127]:
|
||||
- generic [ref=e128]: sure
|
||||
- generic:
|
||||
- paragraph
|
||||
- row "jacquesm on Feb 19, 2009 [dead] | | [–] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e129]:
|
||||
- cell "jacquesm on Feb 19, 2009 [dead] | | [–] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e130]:
|
||||
- table [ref=e131]:
|
||||
- rowgroup [ref=e132]:
|
||||
- row "jacquesm on Feb 19, 2009 [dead] | | [–] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e133]:
|
||||
- cell [ref=e134]:
|
||||
- img
|
||||
- cell [ref=e135]:
|
||||
- img [ref=e137]
|
||||
- cell "jacquesm on Feb 19, 2009 [dead] | | [–] So, just to see how hard it is to make the longest span between article and comment :) Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together. Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment." [ref=e138]:
|
||||
- generic [ref=e140]:
|
||||
- link "jacquesm" [ref=e141] [cursor=pointer]:
|
||||
- /url: user?id=jacquesm
|
||||
- generic "2009-02-19T12:21:23 1235046083" [ref=e142]:
|
||||
- link "on Feb 19, 2009" [ref=e143] [cursor=pointer]:
|
||||
- /url: item?id=487171
|
||||
- text: "[dead]"
|
||||
- generic [ref=e144]:
|
||||
- text: "|"
|
||||
- link [ref=e145] [cursor=pointer]:
|
||||
- /url: "#15"
|
||||
- text: prev
|
||||
- text: "|"
|
||||
- link [ref=e146] [cursor=pointer]:
|
||||
- /url: "#234509"
|
||||
- text: next
|
||||
- link "[–]" [ref=e147] [cursor=pointer]:
|
||||
- /url: javascript:void(0)
|
||||
- generic [ref=e148]:
|
||||
- generic [ref=e149]:
|
||||
- text: So, just to see how hard it is to make the longest span between article and comment :)
|
||||
- paragraph [ref=e150]: Congratulations on your second birthday YC, and thanks to Paul Graham for writing this forum. I had a really good look at the good a few days ago and I was quite impressed with how elegant the whole thing is put together.
|
||||
- paragraph [ref=e151]: Lisp would not be my language of choice for a website like this, and yet, after seeing how concise it was I'm tempted to play around with lisp in a web environment.
|
||||
- generic:
|
||||
- paragraph
|
||||
- row "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e152]:
|
||||
- cell "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e153]:
|
||||
- table [ref=e154]:
|
||||
- rowgroup [ref=e155]:
|
||||
- row "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e156]:
|
||||
- cell [ref=e157]:
|
||||
- img
|
||||
- cell "kleevr on July 2, 2008 [dead] | | [11 more]" [ref=e158]:
|
||||
- generic [ref=e160]:
|
||||
- link "kleevr" [ref=e161] [cursor=pointer]:
|
||||
- /url: user?id=kleevr
|
||||
- generic "2008-07-02T20:29:48 1215030588" [ref=e162]:
|
||||
- link "on July 2, 2008" [ref=e163] [cursor=pointer]:
|
||||
- /url: item?id=234509
|
||||
- text: "[dead]"
|
||||
- generic [ref=e164]:
|
||||
- text: "|"
|
||||
- link [ref=e165] [cursor=pointer]:
|
||||
- /url: "#487171"
|
||||
- text: prev
|
||||
- text: "|"
|
||||
- link [ref=e166] [cursor=pointer]:
|
||||
- /url: "#82729"
|
||||
- text: next
|
||||
- link "[11 more]" [ref=e167] [cursor=pointer]:
|
||||
- /url: javascript:void(0)
|
||||
- row "vice on Nov 22, 2007 [dead] | [–] I'm nX 1 too ;)" [ref=e168]:
|
||||
- cell "vice on Nov 22, 2007 [dead] | [–] I'm nX 1 too ;)" [ref=e169]:
|
||||
- table [ref=e170]:
|
||||
- rowgroup [ref=e171]:
|
||||
- row "vice on Nov 22, 2007 [dead] | [–] I'm nX 1 too ;)" [ref=e172]:
|
||||
- cell [ref=e173]:
|
||||
- img
|
||||
- cell [ref=e174]:
|
||||
- img [ref=e176]
|
||||
- cell "vice on Nov 22, 2007 [dead] | [–] I'm nX 1 too ;)" [ref=e177]:
|
||||
- generic [ref=e179]:
|
||||
- link "vice" [ref=e180] [cursor=pointer]:
|
||||
- /url: user?id=vice
|
||||
- generic "2007-11-22T12:50:54 1195735854" [ref=e181]:
|
||||
- link "on Nov 22, 2007" [ref=e182] [cursor=pointer]:
|
||||
- /url: item?id=82729
|
||||
- text: "[dead]"
|
||||
- generic [ref=e183]:
|
||||
- text: "|"
|
||||
- link [ref=e184] [cursor=pointer]:
|
||||
- /url: "#234509"
|
||||
- text: prev
|
||||
- link "[–]" [ref=e185] [cursor=pointer]:
|
||||
- /url: javascript:void(0)
|
||||
- generic [ref=e186]:
|
||||
- generic [ref=e187]:
|
||||
- text: I'm nX 1 too
|
||||
- paragraph [ref=e188]: ;)
|
||||
- generic:
|
||||
- paragraph
|
||||
- row "Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact Search:" [ref=e189]:
|
||||
- cell "Guidelines | FAQ | Lists | API | Security | Legal | Apply to YC | Contact Search:" [ref=e190]:
|
||||
- img
|
||||
- table [ref=e191]:
|
||||
- rowgroup [ref=e192]:
|
||||
- row [ref=e193]:
|
||||
- cell [ref=e194]
|
||||
- generic [ref=e195]:
|
||||
- generic [ref=e196]:
|
||||
- link "Guidelines" [ref=e197] [cursor=pointer]:
|
||||
- /url: newsguidelines.html
|
||||
- text: "|"
|
||||
- link "FAQ" [ref=e198] [cursor=pointer]:
|
||||
- /url: newsfaq.html
|
||||
- text: "|"
|
||||
- link "Lists" [ref=e199] [cursor=pointer]:
|
||||
- /url: lists
|
||||
- text: "|"
|
||||
- link "API" [ref=e200] [cursor=pointer]:
|
||||
- /url: https://github.com/HackerNews/API
|
||||
- text: "|"
|
||||
- link "Security" [ref=e201] [cursor=pointer]:
|
||||
- /url: security.html
|
||||
- text: "|"
|
||||
- link "Legal" [ref=e202] [cursor=pointer]:
|
||||
- /url: https://www.ycombinator.com/legal/
|
||||
- text: "|"
|
||||
- link "Apply to YC" [ref=e203] [cursor=pointer]:
|
||||
- /url: https://www.ycombinator.com/apply/
|
||||
- text: "|"
|
||||
- link "Contact" [ref=e204] [cursor=pointer]:
|
||||
- /url: mailto:hn@ycombinator.com
|
||||
- generic [ref=e205]:
|
||||
- text: "Search:"
|
||||
- textbox [ref=e206]
|
||||
- link "past" [ref=e18] [cursor=pointer]:
|
||||
|
||||
|
||||
[Truncated to 1000 characters. Better manage your logs or paginate them to read the full logs]
|
||||
@@ -24,320 +24,6 @@ Return value:
|
||||
- /url: /colors
|
||||
- generic [ref=e16]:
|
||||
- button "Search documentation... ⌘ K" [ref=e18]:
|
||||
- generic [ref=e19]: Search documentation...
|
||||
- generic [ref=e21]:
|
||||
- generic: ⌘
|
||||
- generic: K
|
||||
- link "99.8k" [ref=e22] [cursor=pointer]:
|
||||
- /url: https://github.com/shadcn-ui/ui
|
||||
- img
|
||||
- generic [ref=e23]: 99.8k
|
||||
- button "Toggle layout" [ref=e24]:
|
||||
- generic [ref=e25]: Toggle layout
|
||||
- img
|
||||
- button "Toggle theme" [ref=e26]:
|
||||
- img
|
||||
- generic [ref=e27]: Toggle theme
|
||||
- main [ref=e28]:
|
||||
- generic [ref=e29]:
|
||||
- generic [ref=e32]:
|
||||
- 'link "New New Components: Field, Input Group, Item and more" [ref=e33] [cursor=pointer]':
|
||||
- /url: /docs/changelog
|
||||
- generic "New" [ref=e34]
|
||||
- text: "New Components: Field, Input Group, Item and more"
|
||||
- img
|
||||
- heading "The Foundation for your Design System" [level=1] [ref=e35]
|
||||
- paragraph [ref=e36]: A set of beautifully designed components that you can customize, extend, and build on. Start here then make it your own. Open Source. Open Code.
|
||||
- generic [ref=e37]:
|
||||
- link "Get Started" [ref=e38] [cursor=pointer]:
|
||||
- /url: /docs/installation
|
||||
- link "View Components" [ref=e39] [cursor=pointer]:
|
||||
- /url: /docs/components
|
||||
- generic [ref=e41]:
|
||||
- generic [ref=e46]:
|
||||
- link "Examples" [ref=e47] [cursor=pointer]:
|
||||
- /url: /
|
||||
- link "Dashboard" [ref=e48] [cursor=pointer]:
|
||||
- /url: /examples/dashboard
|
||||
- link "Tasks" [ref=e49] [cursor=pointer]:
|
||||
- /url: /examples/tasks
|
||||
- link "Playground" [ref=e50] [cursor=pointer]:
|
||||
- /url: /examples/playground
|
||||
- link "Authentication" [ref=e51] [cursor=pointer]:
|
||||
- /url: /examples/authentication
|
||||
- generic [ref=e52]:
|
||||
- generic [ref=e53]: Theme
|
||||
- combobox "Theme" [ref=e54]:
|
||||
- generic [ref=e55]: "Theme:"
|
||||
- generic: Neutral
|
||||
- img
|
||||
- button "Copy Code" [ref=e56]:
|
||||
- img
|
||||
- generic [ref=e57]: Copy Code
|
||||
- generic [ref=e61]:
|
||||
- generic [ref=e65]:
|
||||
- group "Payment Method" [ref=e66]:
|
||||
- generic [ref=e67]: Payment Method
|
||||
- paragraph [ref=e68]: All transactions are secure and encrypted
|
||||
- generic [ref=e69]:
|
||||
- group [ref=e70]:
|
||||
- generic [ref=e71]: Name on Card
|
||||
- textbox "Name on Card" [ref=e72]:
|
||||
- /placeholder: John Doe
|
||||
- generic [ref=e73]:
|
||||
- group [ref=e74]:
|
||||
- generic [ref=e75]: Card Number
|
||||
- textbox "Card Number" [ref=e76]:
|
||||
- /placeholder: 1234 5678 9012 3456
|
||||
- paragraph [ref=e77]: Enter your 16-digit number.
|
||||
- group [ref=e78]:
|
||||
- generic [ref=e79]: CVV
|
||||
- textbox "CVV" [ref=e80]:
|
||||
- /placeholder: "123"
|
||||
- generic [ref=e81]:
|
||||
- group [ref=e82]:
|
||||
- generic [ref=e83]: Month
|
||||
- combobox "Month" [ref=e84]:
|
||||
- generic: MM
|
||||
- img
|
||||
- combobox [ref=e85]
|
||||
- group [ref=e86]:
|
||||
- generic [ref=e87]: Year
|
||||
- combobox "Year" [ref=e88]:
|
||||
- generic: YYYY
|
||||
- img
|
||||
- combobox [ref=e89]
|
||||
- group "Billing Address" [ref=e91]:
|
||||
- generic [ref=e92]: Billing Address
|
||||
- paragraph [ref=e93]: The billing address associated with your payment method
|
||||
- group [ref=e95]:
|
||||
- checkbox "Same as shipping address" [checked] [ref=e96]:
|
||||
- generic:
|
||||
- img
|
||||
- checkbox [checked]
|
||||
- generic [ref=e97]: Same as shipping address
|
||||
- group [ref=e99]:
|
||||
- group [ref=e101]:
|
||||
- generic [ref=e102]: Comments
|
||||
- textbox "Comments" [ref=e103]:
|
||||
- /placeholder: Add any additional comments
|
||||
- group [ref=e104]:
|
||||
- button "Submit" [ref=e105]
|
||||
- button "Cancel" [ref=e106]
|
||||
- generic [ref=e107]:
|
||||
- generic [ref=e108]:
|
||||
- generic [ref=e109]:
|
||||
- generic [ref=e111]:
|
||||
- img "@shadcn" [ref=e113]
|
||||
- img "@maxleiter" [ref=e115]
|
||||
- img "@evilrabbit" [ref=e117]
|
||||
- generic [ref=e118]: No Team Members
|
||||
- generic [ref=e119]: Invite your team to collaborate on this project.
|
||||
- button "Invite Members" [ref=e121]:
|
||||
- img
|
||||
- text: Invite Members
|
||||
- generic [ref=e122]:
|
||||
- generic [ref=e123]:
|
||||
- status "Loading"
|
||||
- text: Syncing
|
||||
- generic [ref=e124]:
|
||||
- status "Loading"
|
||||
- text: Updating
|
||||
- generic [ref=e125]:
|
||||
- status "Loading"
|
||||
- text: Loading
|
||||
- group [ref=e126]:
|
||||
- group [ref=e127]:
|
||||
- button "Add" [ref=e128]:
|
||||
- img
|
||||
- group [ref=e129]:
|
||||
- group [ref=e130]:
|
||||
- textbox "Send a message..." [ref=e131]
|
||||
- group [ref=e132]:
|
||||
- button "Voice Mode" [ref=e133]:
|
||||
- img
|
||||
- group [ref=e135]:
|
||||
- generic [ref=e136]: Price Range
|
||||
- paragraph [ref=e137]: Set your budget range ($200 - 800).
|
||||
- generic "Price Range" [ref=e138]:
|
||||
- slider "Minimum" [ref=e142]
|
||||
- slider "Maximum" [ref=e144]
|
||||
- generic [ref=e145]:
|
||||
- group [ref=e146]:
|
||||
- textbox "Search..." [ref=e147]
|
||||
- group [ref=e148]:
|
||||
- img [ref=e149]
|
||||
- group [ref=e152]: 12 results
|
||||
- group [ref=e153]:
|
||||
- textbox "example.com" [ref=e154]
|
||||
- group [ref=e155]:
|
||||
- generic [ref=e156]: https://
|
||||
- group [ref=e157]:
|
||||
- button "Info" [ref=e158]:
|
||||
- img
|
||||
- group [ref=e159]:
|
||||
- textbox "Ask, Search or Chat..." [ref=e160]
|
||||
- group [ref=e161]:
|
||||
- button "Add" [ref=e162]:
|
||||
- img
|
||||
- button "Auto" [ref=e163]
|
||||
- generic [ref=e164]: 52% used
|
||||
- button "Send" [ref=e165]:
|
||||
- img
|
||||
- generic [ref=e166]: Send
|
||||
- group [ref=e167]:
|
||||
- textbox "@shadcn" [ref=e168]
|
||||
- group [ref=e169]:
|
||||
- img [ref=e171]
|
||||
- generic [ref=e173]:
|
||||
- generic [ref=e174]:
|
||||
- generic [ref=e175]: Input Secure
|
||||
- group [ref=e176]:
|
||||
- textbox "Input Secure" [ref=e177]
|
||||
- group [ref=e178]:
|
||||
- button "Info" [ref=e179]:
|
||||
- img
|
||||
- group [ref=e180]: https://
|
||||
- group [ref=e181]:
|
||||
- button "Favorite" [ref=e182]:
|
||||
- img
|
||||
- generic [ref=e183]:
|
||||
- generic [ref=e184]:
|
||||
- generic [ref=e185]:
|
||||
- generic [ref=e186]: Two-factor authentication
|
||||
- paragraph [ref=e187]: Verify via email or phone number.
|
||||
- button "Enable" [ref=e189]
|
||||
- link "Your profile has been verified." [ref=e190] [cursor=pointer]:
|
||||
- /url: "#"
|
||||
- generic [ref=e191]:
|
||||
- img
|
||||
- generic [ref=e193]: Your profile has been verified.
|
||||
- img [ref=e195]
|
||||
- generic [ref=e198]: Appearance Settings
|
||||
- group [ref=e199]:
|
||||
- generic [ref=e200]:
|
||||
- group "Compute Environment" [ref=e201]:
|
||||
- generic [ref=e202]: Compute Environment
|
||||
- paragraph [ref=e203]: Select the compute environment for your cluster.
|
||||
- radiogroup [ref=e204]:
|
||||
- group [ref=e206]:
|
||||
- generic [ref=e207]:
|
||||
- generic [ref=e208]: Kubernetes
|
||||
- paragraph [ref=e209]: Run GPU workloads on a K8s configured cluster. This is the default.
|
||||
- radio "Kubernetes" [checked] [ref=e210]:
|
||||
- img [ref=e211]
|
||||
- group [ref=e214]:
|
||||
- generic [ref=e215]:
|
||||
- generic [ref=e216]: Virtual Machine
|
||||
- paragraph [ref=e217]: Access a VM configured cluster to run workloads. (Coming soon)
|
||||
- radio "Virtual Machine" [ref=e218]
|
||||
- group [ref=e220]:
|
||||
- generic [ref=e221]:
|
||||
- generic [ref=e222]: Number of GPUs
|
||||
- paragraph [ref=e223]: You can add more later.
|
||||
- group [ref=e224]:
|
||||
- textbox "Number of GPUs" [ref=e225]: "8"
|
||||
- button "Decrement" [ref=e226]:
|
||||
- img
|
||||
- button "Increment" [ref=e227]:
|
||||
- img
|
||||
- group [ref=e229]:
|
||||
- generic [ref=e230]:
|
||||
- generic [ref=e231]: Wallpaper Tinting
|
||||
- paragraph [ref=e232]: Allow the wallpaper to be tinted.
|
||||
- switch "Wallpaper Tinting" [checked] [ref=e233]
|
||||
- generic [ref=e234]:
|
||||
- group [ref=e236]:
|
||||
- generic [ref=e237]: Prompt
|
||||
- group [ref=e238]:
|
||||
- textbox "Prompt" [ref=e239]:
|
||||
- /placeholder: Ask, search, or make anything...
|
||||
- group [ref=e240]:
|
||||
- button "Add context" [ref=e241]:
|
||||
- img
|
||||
- text: Add context
|
||||
- group [ref=e243]:
|
||||
- button "Attach file" [ref=e244]:
|
||||
- img
|
||||
- button "Auto" [ref=e245]
|
||||
- button "All Sources" [ref=e246]:
|
||||
- img
|
||||
- text: All Sources
|
||||
- button "Send" [ref=e247]:
|
||||
- img
|
||||
- group [ref=e248]:
|
||||
- group [ref=e249]:
|
||||
- button "Go Back" [ref=e250]:
|
||||
- img
|
||||
- group [ref=e251]:
|
||||
- button "Archive" [ref=e252]
|
||||
- button "Report" [ref=e253]
|
||||
- group [ref=e254]:
|
||||
- button "Snooze" [ref=e255]
|
||||
- button "More Options" [ref=e256]:
|
||||
- img
|
||||
- group [ref=e258]:
|
||||
- checkbox "I agree to the terms and conditions" [checked] [ref=e259]:
|
||||
- generic:
|
||||
- img
|
||||
- generic [ref=e260]: I agree to the terms and conditions
|
||||
- generic [ref=e261]:
|
||||
- group [ref=e262]:
|
||||
- group [ref=e263]:
|
||||
- button "1" [ref=e264]
|
||||
- button "2" [ref=e265]
|
||||
- button "3" [ref=e266]
|
||||
- group [ref=e267]:
|
||||
- button "Previous" [ref=e268]:
|
||||
- img
|
||||
- button "Next" [ref=e269]:
|
||||
- img
|
||||
- group [ref=e270]:
|
||||
- button "Copilot" [ref=e271]:
|
||||
- img
|
||||
- text: Copilot
|
||||
- button "Open Popover" [ref=e272]:
|
||||
- img
|
||||
- group "How did you hear about us?" [ref=e277]:
|
||||
- generic [ref=e278]: How did you hear about us?
|
||||
- paragraph [ref=e279]: Select the option that best describes how you heard about us.
|
||||
- generic [ref=e280]:
|
||||
- group [ref=e282]:
|
||||
- checkbox "Social Media" [checked] [ref=e283]:
|
||||
- generic:
|
||||
- img
|
||||
- checkbox [checked]
|
||||
- generic [ref=e284]: Social Media
|
||||
- group [ref=e286]:
|
||||
- checkbox "Search Engine" [ref=e287]
|
||||
- checkbox
|
||||
- generic [ref=e288]: Search Engine
|
||||
- group [ref=e290]:
|
||||
- checkbox "Referral" [ref=e291]
|
||||
- checkbox
|
||||
- generic [ref=e292]: Referral
|
||||
- group [ref=e294]:
|
||||
- checkbox "Other" [ref=e295]
|
||||
- checkbox
|
||||
- generic [ref=e296]: Other
|
||||
- generic [ref=e297]:
|
||||
- generic [ref=e298]:
|
||||
- generic [ref=e299]:
|
||||
- status "Loading"
|
||||
- generic [ref=e300]: Processing your request
|
||||
- generic [ref=e301]: Please wait while we process your request. Do not refresh the page.
|
||||
- button "Cancel" [ref=e303]
|
||||
- contentinfo [ref=e304]:
|
||||
- generic [ref=e307]:
|
||||
- text: Built by
|
||||
- link "shadcn" [ref=e308] [cursor=pointer]:
|
||||
- /url: https://twitter.com/shadcn
|
||||
- text: at
|
||||
- link "Vercel" [ref=e309] [cursor=pointer]:
|
||||
- /url: https://vercel.com/new?utm_source=shadcn_site&utm_medium=web&utm_campaign=docs_cta_deploy_now_callout
|
||||
- text: . The source code is available on
|
||||
- link "GitHub" [ref=e310] [cursor=pointer]:
|
||||
- /url: https://github.com/shadcn-ui/ui
|
||||
- text: .
|
||||
- region "Notifications alt+T"
|
||||
- alert [ref=e311]
|
||||
- generic [re
|
||||
|
||||
[Truncated to 1000 characters. Better manage your logs or paginate them to read the full logs]
|
||||
Reference in New Issue
Block a user