Skip to content

Instantly share code, notes, and snippets.

@theoknock
Last active November 15, 2025 02:48
Show Gist options
  • Select an option

  • Save theoknock/2db057ccda11434b8ac376e427b8ed3a to your computer and use it in GitHub Desktop.

Select an option

Save theoknock/2db057ccda11434b8ac376e427b8ed3a to your computer and use it in GitHub Desktop.
Lists all DOM elements from page loaded with WebKit.
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")")
// }
// }
// }
@theoknock
Copy link
Author

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

@theoknock
Copy link
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 ==============
> 

@theoknock
Copy link
Author

@theoknock
Copy link
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