Last active
November 15, 2025 02:48
-
-
Save theoknock/2db057ccda11434b8ac376e427b8ed3a to your computer and use it in GitHub Desktop.
Lists all DOM elements from page loaded with WebKit.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| import SwiftUI | |
| import WebKit | |
| import Combine | |
| import Observation | |
| @Observable class MyWebViewModel { | |
| var webPage = WebPage() | |
| func load(url: URL) async { | |
| webPage.load(URLRequest(url: url)) | |
| } | |
| func restrictToVertical(webPage: WebPage) async { | |
| // Wait until the page has finished loading | |
| while webPage.isLoading { | |
| try? await Task.sleep(nanoseconds: 100_000_000) // 0.1 s | |
| } | |
| let js = """ | |
| const style = document.createElement('style'); | |
| style.textContent = ` | |
| html, body { | |
| overflow-x: hidden !important; | |
| overscroll-behavior-x: none; | |
| } | |
| * { | |
| max-width: 100vw !important; | |
| box-sizing: border-box; | |
| } | |
| `; | |
| document.head.appendChild(style); | |
| """ | |
| do { | |
| _ = try await webPage.callJavaScript(js) | |
| } catch { | |
| print("Failed to inject vertical-only CSS:", error) | |
| } | |
| } | |
| func list(webPage: WebPage) async { | |
| // Wait until the page has finished loading | |
| while webPage.isLoading { | |
| try? await Task.sleep(nanoseconds: 100_000_000) // 0.1 seconds | |
| } | |
| // After the page has finished loading, list DOM elements | |
| let js = """ | |
| const all = document.getElementsByTagName('*'); | |
| const elements = []; | |
| for (let i = 0; i < all.length; i++) { | |
| const el = all[i]; | |
| const tagName = el.tagName; | |
| const id = el.id || ''; | |
| const className = el.className || ''; | |
| const text = (el.textContent || '').trim().slice(0, 80); | |
| elements.push(tagName + "|" + id + "|" + className + "|" + text); | |
| } | |
| return elements; | |
| """ | |
| do { | |
| if let elements = try await webPage.callJavaScript(js) as? [String] { | |
| print("\n================ DOM ELEMENTS ================") | |
| print("Total elements: \(elements.count)") | |
| for (index, line) in elements.enumerated() { | |
| let parts = line.components(separatedBy: "|") | |
| let tagName = parts.count > 0 ? parts[0] : "" | |
| let elementId = parts.count > 1 ? parts[1] : "" | |
| let className = parts.count > 2 ? parts[2] : "" | |
| let textPreview = parts.count > 3 ? parts[3] : "" | |
| print("\n[\(index)] <\(tagName)>") | |
| if !elementId.isEmpty { | |
| print(" id: \(elementId)") | |
| } | |
| if !className.isEmpty { | |
| print(" class: \(className)") | |
| } | |
| if !textPreview.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { | |
| print(" text: \"\(textPreview)\"") | |
| } | |
| } | |
| print("\n============== END DOM ELEMENTS ==============\n") | |
| } else { | |
| let result = try await webPage.callJavaScript(js) | |
| print("DOM script returned unexpected result:", result as Any) | |
| } | |
| } catch { | |
| print("JavaScript error:", error.localizedDescription) | |
| } | |
| } | |
| } | |
| struct ContentView: View { | |
| @State private var viewModel = MyWebViewModel() | |
| var body: some View { | |
| NavigationView { | |
| WebView(viewModel.webPage) | |
| .clipShape(RoundedRectangle(cornerRadius: 20)) | |
| .padding() | |
| .task { | |
| await viewModel.load(url: URL(string: "https://chatgpt.com")!) | |
| await viewModel.restrictToVertical(webPage: viewModel.webPage) | |
| await viewModel.list(webPage: viewModel.webPage) | |
| } | |
| } | |
| .ignoresSafeArea() | |
| } | |
| } | |
| #Preview { | |
| ContentView() | |
| .preferredColorScheme(.dark) | |
| } | |
| // struct WebView: UIViewRepresentable { | |
| // let url: URL | |
| // | |
| // func makeCoordinator() -> Coordinator { | |
| // Coordinator(self) | |
| // } | |
| // | |
| // func makeUIView(context: Context) -> WKWebView { | |
| // // Configure WKWebView with navigation delegate | |
| // let configuration = WKWebViewConfiguration() | |
| // configuration.websiteDataStore = .default() | |
| // | |
| // // Enable JavaScript | |
| // configuration.preferences.javaScriptEnabled = true | |
| // | |
| // // Create WebView | |
| // let webView = WKWebView(frame: .zero, configuration: configuration) | |
| // webView.navigationDelegate = context.coordinator | |
| // | |
| // // Load the URL | |
| // let request = URLRequest(url: url) | |
| // webView.load(request) | |
| // | |
| // return webView | |
| // } | |
| // | |
| // func updateUIView(_ webView: WKWebView, context: Context) { | |
| // // No updates needed for this simple implementation | |
| // } | |
| // | |
| // class Coordinator: NSObject, WKNavigationDelegate { | |
| // var parent: WebView | |
| // | |
| // init(_ parent: WebView) { | |
| // self.parent = parent | |
| // } | |
| // | |
| // // Called when the page finishes loading | |
| // func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { | |
| // print("✅ Page finished loading: \(webView.url?.absoluteString ?? "unknown")") | |
| // | |
| // // JavaScript to get all DOM elements | |
| // let jsScript = """ | |
| // (function() { | |
| // // Get all elements on the page | |
| // const allElements = document.getElementsByTagName('*'); | |
| // const elementInfo = []; | |
| // | |
| // // Collect information about each element | |
| // for (let i = 0; i < allElements.length; i++) { | |
| // const elem = allElements[i]; | |
| // const info = { | |
| // tagName: elem.tagName, | |
| // id: elem.id || 'none', | |
| // className: elem.className || 'none', | |
| // textContent: elem.textContent ? elem.textContent.substring(0, 50) : 'none', | |
| // elementIndex: i | |
| // }; | |
| // elementInfo.push(info); | |
| // } | |
| // | |
| // return { | |
| // totalElements: allElements.length, | |
| // elements: elementInfo | |
| // }; | |
| // })(); | |
| // """ | |
| // | |
| // // Execute the JavaScript | |
| // webView.evaluateJavaScript(jsScript) { (result, error) in | |
| // if let error = error { | |
| // print("❌ JavaScript Error: \(error.localizedDescription)") | |
| // return | |
| // } | |
| // | |
| // if let resultDict = result as? [String: Any], | |
| // let totalElements = resultDict["totalElements"] as? Int, | |
| // let elements = resultDict["elements"] as? [[String: Any]] { | |
| // | |
| // print("\n" + String(repeating: "=", count: 80)) | |
| // print("📊 DOM ELEMENTS ANALYSIS") | |
| // print(String(repeating: "=", count: 80)) | |
| // print("Total DOM Elements Found: \(totalElements)") | |
| // print(String(repeating: "-", count: 80)) | |
| // | |
| // // Print each element's information | |
| // for (index, element) in elements.enumerated() { | |
| // let tagName = element["tagName"] as? String ?? "unknown" | |
| // let elementId = element["id"] as? String ?? "none" | |
| // let className = element["className"] as? String ?? "none" | |
| // let textPreview = element["textContent"] as? String ?? "none" | |
| // | |
| // print("\n🏷️ Element #\(index + 1):") | |
| // print(" Tag: <\(tagName)>") | |
| // | |
| // if elementId != "none" { | |
| // print(" ID: #\(elementId)") | |
| // } | |
| // | |
| // if className != "none" && !className.isEmpty { | |
| // print(" Classes: .\(className.replacingOccurrences(of: " ", with: ", ."))") | |
| // } | |
| // | |
| // if textPreview != "none" && !textPreview.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty { | |
| // let trimmedText = textPreview | |
| // .trimmingCharacters(in: .whitespacesAndNewlines) | |
| // .replacingOccurrences(of: "\n", with: " ") | |
| // if trimmedText.count > 0 { | |
| // print(" Text: \"\(trimmedText)...\"") | |
| // } | |
| // } | |
| // } | |
| // | |
| // print("\n" + String(repeating: "=", count: 80)) | |
| // print("✅ DOM Analysis Complete!") | |
| // print(String(repeating: "=", count: 80) + "\n") | |
| // | |
| // // Also print a summary of tag types | |
| // self.printTagSummary(elements: elements) | |
| // } | |
| // } | |
| // } | |
| // | |
| // // Print a summary of tag types found | |
| // func printTagSummary(elements: [[String: Any]]) { | |
| // var tagCounts: [String: Int] = [:] | |
| // | |
| // for element in elements { | |
| // if let tagName = element["tagName"] as? String { | |
| // tagCounts[tagName] = (tagCounts[tagName] ?? 0) + 1 | |
| // } | |
| // } | |
| // | |
| // print("\n📈 TAG SUMMARY:") | |
| // print(String(repeating: "-", count: 40)) | |
| // | |
| // // Sort by count (descending) and print | |
| // let sortedTags = tagCounts.sorted { $0.value > $1.value } | |
| // for (tag, count) in sortedTags.prefix(20) { // Show top 20 most common tags | |
| // print(" \(tag): \(count) elements") | |
| // } | |
| // | |
| // if sortedTags.count > 20 { | |
| // print(" ... and \(sortedTags.count - 20) more tag types") | |
| // } | |
| // | |
| // print(String(repeating: "-", count: 40) + "\n") | |
| // } | |
| // | |
| // // Handle navigation errors | |
| // func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) { | |
| // print("❌ Navigation failed: \(error.localizedDescription)") | |
| // } | |
| // | |
| // // Handle provisional navigation failures | |
| // func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) { | |
| // print("❌ Provisional navigation failed: \(error.localizedDescription)") | |
| // } | |
| // | |
| // // Log when navigation starts | |
| // func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { | |
| // print("🔄 Starting to load: \(webView.url?.absoluteString ?? "unknown")") | |
| // } | |
| // } | |
| // } |
Author
Author
Sample runtime console output
> >
> ================ DOM ELEMENTS ================
> Total elements: 433
>
> [0] <HTML>
> class: dark
> text: "ChatGPT{"@context":"https://schema.org","@graph":[{"@type":"Organization","name""
>
> [1] <HEAD>
> text: "ChatGPT{"@context":"https://schema.org","@graph":[{"@type":"Organization","name""
>
> [2] <META>
>
> [3] <META>
>
> [4] <TITLE>
> text: "ChatGPT"
>
> [5] <META>
>
> [6] <META>
>
> [7] <LINK>
>
> [8] <LINK>
>
> [9] <LINK>
>
> [10] <META>
>
> [11] <META>
>
> [12] <META>
>
> [13] <META>
>
> [14] <META>
>
> [15] <LINK>
>
> [16] <LINK>
>
> [17] <LINK>
>
> [18] <LINK>
>
> [19] <META>
>
> [20] <META>
>
> [21] <META>
>
> [22] <META>
>
> [23] <META>
>
> [24] <LINK>
>
> [25] <LINK>
>
> [26] <LINK>
>
> [27] <LINK>
>
> [28] <LINK>
>
> [29] <LINK>
>
> [30] <LINK>
>
> [31] <LINK>
>
> [32] <LINK>
>
> [33] <LINK>
>
> [34] <LINK>
>
> [35] <LINK>
>
> [36] <LINK>
>
> [37] <LINK>
>
> [38] <LINK>
>
> [39] <LINK>
>
> [40] <LINK>
>
> [41] <LINK>
>
> [42] <LINK>
>
> [43] <LINK>
>
> [44] <LINK>
>
> [45] <LINK>
>
> [46] <LINK>
>
> [47] <LINK>
>
> [48] <LINK>
>
> [49] <LINK>
>
> [50] <LINK>
>
> [51] <LINK>
>
> [52] <LINK>
>
> [53] <LINK>
>
> [54] <LINK>
>
> [55] <LINK>
>
> [56] <LINK>
>
> [57] <LINK>
>
> [58] <LINK>
>
> [59] <LINK>
>
> [60] <LINK>
>
> [61] <LINK>
>
> [62] <LINK>
>
> [63] <LINK>
>
> [64] <LINK>
>
> [65] <LINK>
>
> [66] <LINK>
>
> [67] <LINK>
>
> [68] <LINK>
>
> [69] <LINK>
>
> [70] <LINK>
>
> [71] <LINK>
>
> [72] <LINK>
>
> [73] <LINK>
>
> [74] <LINK>
>
> [75] <LINK>
>
> [76] <LINK>
>
> [77] <LINK>
>
> [78] <LINK>
>
> [79] <LINK>
>
> [80] <LINK>
>
> [81] <LINK>
>
> [82] <LINK>
>
> [83] <LINK>
>
> [84] <LINK>
>
> [85] <LINK>
>
> [86] <LINK>
>
> [87] <LINK>
>
> [88] <LINK>
>
> [89] <LINK>
>
> [90] <LINK>
>
> [91] <LINK>
>
> [92] <LINK>
>
> [93] <LINK>
>
> [94] <LINK>
>
> [95] <LINK>
>
> [96] <LINK>
>
> [97] <LINK>
>
> [98] <LINK>
>
> [99] <LINK>
>
> [100] <LINK>
>
> [101] <LINK>
>
> [102] <LINK>
>
> [103] <LINK>
>
> [104] <LINK>
>
> [105] <LINK>
>
> [106] <LINK>
>
> [107] <LINK>
>
> [108] <LINK>
>
> [109] <LINK>
>
> [110] <LINK>
>
> [111] <LINK>
>
> [112] <LINK>
>
> [113] <LINK>
>
> [114] <LINK>
>
> [115] <LINK>
>
> [116] <LINK>
>
> [117] <LINK>
>
> [118] <LINK>
>
> [119] <LINK>
>
> [120] <LINK>
>
> [121] <LINK>
>
> [122] <LINK>
>
> [123] <LINK>
>
> [124] <LINK>
>
> [125] <LINK>
>
> [126] <LINK>
>
> [127] <LINK>
>
> [128] <LINK>
>
> [129] <SCRIPT>
> id: organization-ld
> text: "{"@context":"https://schema.org","@graph":[{"@type":"Organization","name":"ChatG"
>
> [130] <SCRIPT>
> id: website-ld
> text: "{"@context":"https://schema.org","@type":"WebSite","url":"https://chatgpt.com/","
>
> [131] <SCRIPT>
> id: webpage-ld
> text: "{"@context":"https://schema.org","@type":"WebPage","url":"https://chatgpt.com/","
>
> [132] <LINK>
>
> [133] <LINK>
>
> [134] <SCRIPT>
> text: "!function initScrollTimelineInline(){try{if(CSS.supports("animation-timeline: --"
>
> [135] <LINK>
>
> [136] <LINK>
>
> [137] <LINK>
>
> [138] <LINK>
>
> [139] <LINK>
>
> [140] <LINK>
>
> [141] <LINK>
>
> [142] <LINK>
>
> [143] <LINK>
>
> [144] <LINK>
>
> [145] <LINK>
>
> [146] <LINK>
>
> [147] <LINK>
>
> [148] <LINK>
>
> [149] <LINK>
>
> [150] <LINK>
>
> [151] <LINK>
>
> [152] <LINK>
>
> [153] <LINK>
>
> [154] <LINK>
>
> [155] <LINK>
>
> [156] <LINK>
>
> [157] <LINK>
>
> [158] <LINK>
>
> [159] <LINK>
>
> [160] <LINK>
>
> [161] <LINK>
>
> [162] <LINK>
>
> [163] <LINK>
>
> [164] <LINK>
>
> [165] <LINK>
>
> [166] <LINK>
>
> [167] <LINK>
>
> [168] <LINK>
>
> [169] <LINK>
>
> [170] <LINK>
>
> [171] <LINK>
>
> [172] <LINK>
>
> [173] <LINK>
>
> [174] <LINK>
>
> [175] <LINK>
>
> [176] <LINK>
>
> [177] <LINK>
>
> [178] <LINK>
>
> [179] <LINK>
>
> [180] <LINK>
>
> [181] <LINK>
>
> [182] <LINK>
>
> [183] <LINK>
>
> [184] <LINK>
>
> [185] <LINK>
>
> [186] <LINK>
>
> [187] <LINK>
>
> [188] <LINK>
>
> [189] <LINK>
>
> [190] <LINK>
>
> [191] <LINK>
>
> [192] <LINK>
>
> [193] <LINK>
>
> [194] <LINK>
>
> [195] <LINK>
>
> [196] <LINK>
>
> [197] <LINK>
>
> [198] <LINK>
>
> [199] <LINK>
>
> [200] <LINK>
>
> [201] <LINK>
>
> [202] <LINK>
>
> [203] <LINK>
>
> [204] <LINK>
>
> [205] <LINK>
>
> [206] <LINK>
>
> [207] <LINK>
>
> [208] <LINK>
>
> [209] <LINK>
>
> [210] <LINK>
>
> [211] <LINK>
>
> [212] <LINK>
>
> [213] <LINK>
>
> [214] <LINK>
>
> [215] <LINK>
>
> [216] <LINK>
>
> [217] <LINK>
>
> [218] <LINK>
>
> [219] <LINK>
>
> [220] <LINK>
>
> [221] <LINK>
>
> [222] <LINK>
>
> [223] <LINK>
>
> [224] <LINK>
>
> [225] <LINK>
>
> [226] <LINK>
>
> [227] <LINK>
>
> [228] <LINK>
>
> [229] <LINK>
>
> [230] <LINK>
>
> [231] <LINK>
>
> [232] <LINK>
>
> [233] <LINK>
>
> [234] <LINK>
>
> [235] <LINK>
>
> [236] <LINK>
>
> [237] <LINK>
>
> [238] <LINK>
>
> [239] <LINK>
>
> [240] <LINK>
>
> [241] <LINK>
>
> [242] <LINK>
>
> [243] <LINK>
>
> [244] <LINK>
>
> [245] <LINK>
>
> [246] <LINK>
>
> [247] <LINK>
>
> [248] <LINK>
>
> [249] <LINK>
>
> [250] <LINK>
>
> [251] <LINK>
>
> [252] <LINK>
>
> [253] <LINK>
>
> [254] <LINK>
>
> [255] <LINK>
>
> [256] <LINK>
>
> [257] <LINK>
>
> [258] <LINK>
>
> [259] <LINK>
>
> [260] <LINK>
>
> [261] <STYLE>
> text: "html, body {
> overflow-x: hidden !important;
> overscroll-behavior-x: none;"
>
> [262] <BODY>
> text: "!function(){try{var d=document.documentElement,c=d.classList;c.remove('light','d"
>
> [263] <SCRIPT>
> text: "!function(){try{var d=document.documentElement,c=d.classList;c.remove('light','d"
>
> [264] <SCRIPT>
> text: "!function(){try{const t=localStorage.getItem("oai/apps/chatTheme");document.docu"
>
> [265] <SPAN>
> class: hidden
>
> [266] <A>
> class: bg-token-main-surface-primary fixed start-1/2 top-1 z-50 mx-auto w-fit -translate-x-1/2 translate-y-[-100lvh] rounded-full px-3 py-2 focus-visible:translate-y-0 print:hidden
> text: "Skip to content"
>
> [267] <DIV>
> class: flex h-full w-full flex-col
> text: "ChatGPTLog inChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThi"
>
> [268] <DIV>
> class: relative flex h-full w-full flex-1 transition-colors z-0
> text: "ChatGPTLog inChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThi"
>
> [269] <DIV>
> class: relative flex h-full w-full flex-row
> text: "ChatGPTLog inChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThi"
>
> [270] <DIV>
> class: relative flex h-full max-w-full min-w-0 flex-1 flex-col
> text: "ChatGPTLog inChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThi"
>
> [271] <DIV>
> class: draggable h-header-height bg-token-bg-primary sticky top-0 z-10 flex items-center border-transparent px-2 md:hidden print:hidden [box-shadow:var(--sharp-edge-top-shadow-placeholder)]
> text: "ChatGPTLog in"
>
> [272] <DIV>
> class: no-draggable flex items-center justify-center
>
> [273] <SPAN>
> class: flex
>
> [274] <A>
> class: text-token-text-primary no-draggable hover:bg-token-surface-hover keyboard-focused:bg-token-surface-hover touch:h-10 touch:w-10 flex h-9 w-9 items-center justify-center rounded-lg focus:outline-none disabled:opacity-50
>
> [275] <svg>
> class: [object SVGAnimatedString]
>
> [276] <path>
> class: [object SVGAnimatedString]
>
> [277] <DIV>
> class: no-draggable flex-1
> text: "ChatGPT"
>
> [278] <DIV>
> class: flex items-center
> text: "ChatGPT"
>
> [279] <BUTTON>
> id: radix-_R_19j6hhp8jacm_
> class: group flex cursor-pointer justify-center items-center gap-1 rounded-lg min-h-9 touch:min-h-10 px-2.5 text-lg hover:bg-token-surface-hover focus-visible:bg-token-surface-hover font-normal whitespace-nowrap focus-visible:outline-none
> text: "ChatGPT"
>
> [280] <DIV>
> text: "ChatGPT"
>
> [281] <svg>
> class: [object SVGAnimatedString]
>
> [282] <path>
> class: [object SVGAnimatedString]
>
> [283] <DIV>
> class: no-draggable flex items-center justify-center
> text: "Log in"
>
> [284] <DIV>
> class: flex items-center
> text: "Log in"
>
> [285] <BUTTON>
> class: btn relative btn-primary
> text: "Log in"
>
> [286] <DIV>
> class: flex items-center justify-center
> text: "Log in"
>
> [287] <BUTTON>
> id: radix-_R_1dj6hhp8jacm_
> class: group user-select-none ps-2 focus:outline-0
>
> [288] <DIV>
> class: group-hover:bg-token-interactive-bg-secondary-selected touch:h-10 touch:w-10 group-keyboard-focused:focus-ring flex h-9 w-9 items-center justify-center rounded-full
>
> [289] <svg>
> class: [object SVGAnimatedString]
>
> [290] <path>
> class: [object SVGAnimatedString]
>
> [291] <path>
> class: [object SVGAnimatedString]
>
> [292] <MAIN>
> id: main
> class: transition-width relative h-full w-full flex-1 overflow-auto -translate-y-[calc(env(safe-area-inset-bottom,0px)/2)] pt-[calc(env(safe-area-inset-bottom,0px)/2)]
> text: "ChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThis chat won't "
>
> [293] <DIV>
> id: thread
> class: group/thread @container/thread h-full w-full
> text: "ChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThis chat won't "
>
> [294] <DIV>
> class: composer-parent flex flex-col focus-visible:outline-0 overflow-hidden h-full
> text: "ChatGPTLog inSign up for freeWhat can I help with?Temporary ChatThis chat won't "
>
> [295] <HEADER>
> id: page-header
> class: draggable no-draggable-children top-0 p-2 touch:p-2.5 flex items-center justify-between z-20 h-header-height pointer-events-none select-none [view-transition-name:var(--vt-page-header)] *:pointer-events-auto motion-safe:transition max-md:hidden absolute start-0 end-0 thread-xl:absolute thread-xl:start-0 thread-xl:end-0 thread-xl:shadow-none! thread-xl:bg-transparent bg-transparent [box-shadow:var(--sharp-edge-top-shadow-placeholder)]
> text: "ChatGPTLog inSign up for free"
>
> [296] <DIV>
> class: pointer-events-none absolute start-0 flex flex-col items-center gap-2 lg:start-1/2 ltr:-translate-x-1/2 rtl:translate-x-1/2
>
> [297] <DIV>
> class: flex items-center
> text: "ChatGPT"
>
> [298] <A>
> class: hover:bg-token-bg-tertiary group touch:h-10 flex aspect-square h-9 items-center justify-center rounded-[10px]
>
> [299] <DIV>
>
> [300] <svg>
> class: [object SVGAnimatedString]
>
> [301] <path>
> class: [object SVGAnimatedString]
>
> [302] <svg>
> class: [object SVGAnimatedString]
>
> [303] <path>
> class: [object SVGAnimatedString]
>
> [304] <BUTTON>
> id: radix-_r_b_
> class: group flex cursor-pointer justify-center items-center gap-1 rounded-lg min-h-9 touch:min-h-10 px-2.5 text-lg hover:bg-token-surface-hover focus-visible:bg-token-surface-hover font-normal whitespace-nowrap focus-visible:outline-none
> text: "ChatGPT"
>
> [305] <DIV>
> text: "ChatGPT"
>
> [306] <svg>
> class: [object SVGAnimatedString]
>
> [307] <path>
> class: [object SVGAnimatedString]
>
> [308] <DIV>
> class: block lg:hidden
>
> [309] <DIV>
> class: flex items-center justify-center gap-3
> text: "Log inSign up for free"
>
> [310] <DIV>
> class: flex-shrink-0
>
> [311] <DIV>
> class: flex items-center gap-2
> text: "Log inSign up for free"
>
> [312] <DIV>
> id: conversation-header-actions
> class: flex items-center
> text: "Log inSign up for free"
>
> [313] <DIV>
> class: flex items-center
> text: "Log inSign up for free"
>
> [314] <DIV>
> class: flex items-center justify-center gap-2
> text: "Log inSign up for free"
>
> [315] <BUTTON>
> class: btn relative btn-primary
> text: "Log in"
>
> [316] <DIV>
> class: flex items-center justify-center
> text: "Log in"
>
> [317] <BUTTON>
> class: btn relative btn-secondary screen-arch:hidden md:screen-arch:flex
> text: "Sign up for free"
>
> [318] <DIV>
> class: flex items-center justify-center
> text: "Sign up for free"
>
> [319] <BUTTON>
> id: radix-_r_d_
> class: group user-select-none ps-2 focus:outline-0
>
> [320] <DIV>
> class: group-hover:bg-token-interactive-bg-secondary-selected touch:h-10 touch:w-10 group-keyboard-focused:focus-ring flex h-9 w-9 items-center justify-center rounded-full
>
> [321] <svg>
> class: [object SVGAnimatedString]
>
> [322] <path>
> class: [object SVGAnimatedString]
>
> [323] <path>
> class: [object SVGAnimatedString]
>
> [324] <DIV>
> class: relative basis-auto flex-col shrink flex flex-col justify-end max-sm:grow max-sm:justify-center sm:min-h-[42svh]
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [325] <DIV>
> class: flex justify-center
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [326] <DIV>
> class: mb-7 hidden text-center sm:block
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [327] <DIV>
> class: relative inline-flex justify-center text-center text-2xl leading-9 font-semibold
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [328] <DIV>
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [329] <DIV>
> class: grid-cols-1 items-center justify-end
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [330] <H1>
> class: text-page-header inline-flex min-h-10.5 items-baseline whitespace-pre-wrap
> text: "What can I help with?"
>
> [331] <DIV>
> class: px-1 text-pretty whitespace-pre-wrap
> text: "What can I help with?"
>
> [332] <DIV>
> class: bottom-0 hidden
> text: "Temporary ChatThis chat won't appear in history or be used to train our models. "
>
> [333] <DIV>
> class: flex flex-col items-center gap-3
> text: "Temporary ChatThis chat won't appear in history or be used to train our models. "
>
> [334] <H1>
> class: text-[28px] leading-[34px] font-normal tracking-[0.38px]
> text: "Temporary Chat"
>
> [335] <INPUT>
> id: temporary-chat-checkbox
> class: sr-only
>
> [336] <DIV>
> class: text-token-text-secondary dark:text-token-text-tertiary max-w-[24rem] text-center text-base leading-[24px] font-normal tracking-[-0.32px] text-balance
> text: "This chat won't appear in history or be used to train our models. For safety pur"
>
> [337] <DIV>
> class: text-token-text-primary mt-[var(--screen-optical-compact-offset-amount)] [display:var(--display-hidden-until-loaded,flex)] w-full shrink flex-col items-center justify-center px-4 transition-opacity sm:hidden h-full opacity-100
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [338] <DIV>
> class: relative inline-flex justify-center text-center text-2xl leading-9 font-semibold
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [339] <DIV>
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [340] <DIV>
> class: grid-cols-1 items-center justify-end
> text: "What can I help with?Temporary ChatThis chat won't appear in history or be used "
>
> [341] <H1>
> class: text-page-header inline-flex min-h-10.5 items-baseline whitespace-pre-wrap
> text: "What can I help with?"
>
> [342] <DIV>
> class: px-1 text-pretty whitespace-pre-wrap
> text: "What can I help with?"
>
> [343] <DIV>
> class: bottom-0 hidden
> text: "Temporary ChatThis chat won't appear in history or be used to train our models. "
>
> [344] <DIV>
> class: flex flex-col items-center gap-3
> text: "Temporary ChatThis chat won't appear in history or be used to train our models. "
>
> [345] <H1>
> class: text-[28px] leading-[34px] font-normal tracking-[0.38px]
> text: "Temporary Chat"
>
> [346] <INPUT>
> id: temporary-chat-checkbox
> class: sr-only
>
> [347] <DIV>
> class: text-token-text-secondary dark:text-token-text-tertiary max-w-[24rem] text-center text-base leading-[24px] font-normal tracking-[-0.32px] text-balance
> text: "This chat won't appear in history or be used to train our models. For safety pur"
>
> [348] <DIV>
>
> [349] <DIV>
> id: thread-bottom-container
> class: group/thread-bottom-container relative isolate z-10 w-full basis-auto has-data-has-thread-error:pt-2 has-data-has-thread-error:[box-shadow:var(--sharp-edge-bottom-shadow)] md:border-transparent md:pt-0 dark:border-white/20 md:dark:border-transparent print:hidden min-h-0 sm:grow flex flex-col
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [350] <DIV>
> class: [display:var(--display-hidden-until-loaded,block)] md:absolute md:start-0 md:bottom-8 md:w-full
>
> [351] <DIV>
> class: text-base mx-auto [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)
>
> [352] <DIV>
> class: [--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1
>
> [353] <DIV>
> class: block flex-1 z-20
>
> [354] <DIV>
> id: thread-bottom
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [355] <DIV>
> class: text-base mx-auto [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [356] <DIV>
> class: [--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [357] <DIV>
> class: flex justify-center empty:hidden
>
> [358] <DIV>
> class: pointer-events-auto relative z-1 flex h-[var(--composer-container-height,100%)] max-w-full flex-[var(--composer-container-flex,1)] flex-col
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [359] <BUTTON>
> class: invisible absolute self-center
>
> [360] <FORM>
> class: group/composer w-full
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [361] <DIV>
> class: hidden
>
> [362] <INPUT>
>
> [363] <DIV>
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [364] <DIV>
> class: bg-token-bg-primary cursor-text overflow-clip bg-clip-padding p-2.5 contain-inline-size dark:bg-[#303030] grid grid-cols-[auto_1fr_auto] [grid-template-areas:'header_header_header'_'leading_primary_trailing'_'._footer_.'] group-data-expanded/composer:[grid-template-areas:'header_header_header'_'primary_primary_primary'_'leading_footer_trailing'] shadow-short
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [365] <DIV>
> class: -my-2.5 flex min-h-14 items-center overflow-x-hidden px-1.5 [grid-area:primary] group-data-expanded/composer:mb-0 group-data-expanded/composer:px-2.5
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [366] <DIV>
> class: _prosemirror-parent_1dsxi_2 text-token-text-primary max-h-[max(30svh,5rem)] max-h-52 flex-1 overflow-auto [scrollbar-width:thin] default-browser vertical-scroll-fade-mask
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [367] <TEXTAREA>
> class: _fallbackTextarea_1dsxi_2
>
> [368] <SCRIPT>
> text: "window.__oai_logHTML?window.__oai_logHTML():window.__oai_SSR_HTML=window.__oai_S"
>
> [369] <DIV>
> id: prompt-textarea
> class: ProseMirror
>
> [370] <P>
> class: placeholder
>
> [371] <BR>
> class: ProseMirror-trailingBreak
>
> [372] <DIV>
> class: -m-1 max-w-full overflow-x-auto p-1 [grid-area:footer] [scrollbar-width:none] group-not-data-expanded/composer:-mb-12
> text: "AttachSearchStudy"
>
> [373] <DIV>
> class: flex min-w-fit items-center gap-1.5 ps-0 pe-1.5
> text: "AttachSearchStudy"
>
> [374] <DIV>
> text: "Attach"
>
> [375] <DIV>
> class: relative
> text: "Attach"
>
> [376] <SPAN>
> class: flex
> text: "Attach"
>
> [377] <DIV>
> id: radix-_R_1ctl7a9b2kl6hhp8jacm_
> class: flex
> text: "Attach"
>
> [378] <BUTTON>
> class: flex items-center justify-center h-9 rounded-full border border-token-border-default text-token-text-secondary min-w-8 w-auto p-2 text-[13px] font-semibold radix-state-open:bg-black/10 hover:bg-token-main-surface-secondary
> text: "Attach"
>
> [379] <svg>
> class: [object SVGAnimatedString]
>
> [380] <path>
> class: [object SVGAnimatedString]
>
> [381] <SPAN>
> class: ps-1 pe-1 whitespace-nowrap [[data-collapse-labels]_&]:sr-only
> text: "Attach"
>
> [382] <DIV>
> text: "Search"
>
> [383] <DIV>
> text: "Search"
>
> [384] <SPAN>
> class: inline-block
> text: "Search"
>
> [385] <DIV>
> class: radix-state-open:bg-black/10 inline-flex h-9 rounded-full border text-[13px] font-medium text-token-text-secondary border-token-border-default hover:bg-token-main-surface-secondary focus-visible:outline-black dark:focus-visible:outline-white
> text: "Search"
>
> [386] <BUTTON>
> class: flex h-full min-w-8 items-center justify-center p-2
> text: "Search"
>
> [387] <svg>
> class: [object SVGAnimatedString]
>
> [388] <path>
> class: [object SVGAnimatedString]
>
> [389] <SPAN>
> text: "Search"
>
> [390] <DIV>
> class: ps-1 pe-1 font-semibold whitespace-nowrap [[data-collapse-labels]_&]:sr-only
> text: "Search"
>
> [391] <DIV>
> class: radix-state-open:bg-black/10 inline-flex h-9 rounded-full border text-[13px] font-medium text-token-text-secondary border-token-border-default hover:bg-token-main-surface-secondary focus-visible:outline-black dark:focus-visible:outline-white
> text: "Study"
>
> [392] <BUTTON>
> class: flex h-full min-w-8 items-center justify-center p-2
> text: "Study"
>
> [393] <svg>
> class: [object SVGAnimatedString]
>
> [394] <path>
> class: [object SVGAnimatedString]
>
> [395] <SPAN>
> text: "Study"
>
> [396] <DIV>
> class: ps-1 pe-1 font-semibold whitespace-nowrap [[data-collapse-labels]_&]:sr-only
> text: "Study"
>
> [397] <DIV>
> class: flex items-center gap-2 [grid-area:trailing]
>
> [398] <DIV>
> class: ms-auto flex items-center gap-1.5
>
> [399] <SPAN>
>
> [400] <BUTTON>
> id: composer-submit-button
> class: composer-submit-btn composer-submit-button-color h-9 w-9
>
> [401] <svg>
> class: [object SVGAnimatedString]
>
> [402] <path>
> class: [object SVGAnimatedString]
>
> [403] <INPUT>
> id: upload-photos
> class: sr-only
>
> [404] <INPUT>
> id: upload-camera
> class: sr-only
>
> [405] <DIV>
>
> [406] <DIV>
> class: text-base mx-auto [--thread-content-margin:--spacing(4)] thread-sm:[--thread-content-margin:--spacing(6)] thread-lg:[--thread-content-margin:--spacing(16)] px-(--thread-content-margin)
>
> [407] <DIV>
> class: [--thread-content-max-width:40rem] thread-lg:[--thread-content-max-width:48rem] mx-auto max-w-(--thread-content-max-width) flex-1
>
> [408] <DIV>
> class: max-w-full max-sm:hidden min-h-[108px] h-[70px]
>
> [409] <DIV>
> class: text-token-text-secondary relative mt-auto flex min-h-8 w-full items-center justify-center p-2 text-center text-xs [view-transition-name:var(--vt-disclaimer)] md:px-[60px]
> text: "By messaging ChatGPT, an AI chatbot, you agree to our Terms and have read our Pr"
>
> [410] <SPAN>
> class: pointer-events-auto text-sm leading-none
> text: "By messaging ChatGPT, an AI chatbot, you agree to our Terms and have read our Pr"
>
> [411] <A>
> class: text-token-text-primary decoration-token-text-primary underline
> text: "Terms"
>
> [412] <A>
> class: text-token-text-primary decoration-token-text-primary underline
> text: "Privacy Policy"
>
> [413] <DIV>
> id: live-region-assertive
> class: sr-only
>
> [414] <DIV>
> id: live-region-polite
> class: sr-only
>
> [415] <AUDIO>
> class: fixed start-0 bottom-0 hidden h-0 w-0
>
> [416] <SCRIPT>
> text: "window.__reactRouterContext = {"basename":"/","future":{"v8_middleware":false,"u"
>
> [417] <SCRIPT>
> text: "import "https://cdn.oaistatic.com/assets/manifest-8cb4da05.js";
> import * as rout"
>
> [418] <SCRIPT>
> text: "window.__reactRouterContext.streamController.enqueue("[{\"_1\":2,\"_4458\":-5,\""
>
> [419] <SCRIPT>
> text: "window.__reactRouterContext.streamController.enqueue("P4447:[{\"_4461\":14,\"_44"
>
> [420] <SCRIPT>
> text: "window.__reactRouterContext.streamController.close();"
>
> [421] <SCRIPT>
> id: _R_
> text: "requestAnimationFrame(function(){$RT=performance.now()});"
>
> [422] <SCRIPT>
> text: "$RB=[];$RV=function(a){$RT=performance.now();for(var b=0;b<a.length;b+=2){var c="
>
> [423] <SCRIPT>
> text: "$RC("B:3","S:3")"
>
> [424] <SCRIPT>
> text: "$RC("B:4","S:4")"
>
> [425] <SCRIPT>
> text: "window.ReactQueryError ??= class ReactQueryError extends Error {};
> null==Promise"
>
> [426] <SCRIPT>
> text: "$RC("B:1","S:1")"
>
> [427] <SCRIPT>
> text: "window.__REACT_QUERY_CACHE__["[\"promptStarters\",8,null]"].resolve(({items:[{id"
>
> [428] <SCRIPT>
> text: "window.__REACT_QUERY_CACHE__["[\"models\",\"{\\\"IIM\\\":false,\\\"isGizmo\\\":f"
>
> [429] <SCRIPT>
> text: "$RC("B:0","S:0")"
>
> [430] <SCRIPT>
> text: "(function(){function c(){var b=a.contentDocument"
>
> [431] <IFRAME>
>
> [432] <SCRIPT>
> id: pioneer-script-ouia2h4
>
> ============== END DOM ELEMENTS ==============
>
Author
Author
ScreenRecording_11-14-2025.21-47-36_1.mp4
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment

ScreenRecording_11-14-2025.19-24-19_1.MP4