blob: 80eea559f437f596ff92de329250c6f962483760 (
plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
|
#!/usr/bin/env tclsh
package require tclgumbo
package require Tk
# TODO: General notes enclose the script into functions, this is ugly right now.
# TODO: Scripts now expects all secondary files to be already present. It should request them from protocol daemon
# instead.
# TODO: Actually, both browse and this script are now unaware of each other. This should be priority for now.
text .t -yscrollcommand {.s set} -relief flat -font {Times 12} -wrap word -border 4
scrollbar .s -command {.t yview}
pack .s -side right -fill y
pack .t -side left -fill both -expand 1
set w .t
$w tag config title -elide true
$w tag config href -elide true
$w tag config a -foreground blue -underline 1
$w tag config strong -font {Times 12 bold}
$w tag config b -font {Times 12 bold}
$w tag config i -font {Times 12 italic}
$w tag config em -font {Times 12 italic}
$w tag config pre -font {Courier 12}
$w tag config code -font {Courier 12}
$w tag config h1 -font {Times 18}
$w tag config h2 -font {Times 18}
$w tag config ul -lmargin1 40 -lmargin2 40
$w tag config dd -lmargin1 40 -lmargin2 40
$w tag config p
$w tag bind a <Enter> "$w config -cursor hand2"
$w tag bind a <Leave> "$w config -cursor {}"
$w tag bind a <ButtonRelease-1> "click $w %x %y"
# TODO: Extend argument parsing and handling
set baseAddress [lindex $argv 1]
set file [open [lindex $argv 0]]
set html [read $file]
close $file
set output [gumbo::parse $html]
proc makeAddress {address} {
global baseAddress
if {1 == [regexp {^https?.*} $address]} {
return "$address"
} elseif {1 == [regexp {^/[^/].*} $address]} {
return "[regsub {(https?://[^/]+)/.*} $baseAddress {\1}]$address"
} elseif {1 == [regexp {^//.*} $address]} {
return "https:$address"
} else {
return "$baseAddress$address"
}
}
proc click {w x y} {
set range [$w tag prevrange href [$w index @$x,$y]]
set address [eval $w get $range]
exec "./browse" [makeAddress $address]
}
proc displayNode {node tagList} {
# TODO: Avoid using global variables.
global w
set type [gumbo::node_get_type $node]
if {$type == $gumbo::GUMBO_NODE_ELEMENT} {
set tag [gumbo::element_get_tag_name $node]
set attributes [gumbo::element_get_attributes $node]
# TODO: This could be simplified in a way that allows for easy extension and won't end up in a long if-elseif-chain
if {$tag == "a"} {
$w insert end [lindex [array get $attributes] 1] [concat $tagList href]
} elseif {$tag == "img"} {
$w insert end "\n"
set lattr [array get $attributes]
set path [makeAddress [lindex $lattr [expr [lsearch -exact $lattr src] + 1]]]
set localPath [lindex [split [exec ./phttp $path] { }] 2]
image create photo $path -file $localPath
$w image create end -image $path
$w insert end "\n"
}
foreach child_node [gumbo::element_get_children $node] {
displayNode $child_node [concat $tag $tagList]
}
# TODO: Handle margins and blocks better than this.
if {$tag == "h1" || $tag == "h2" || $tag == "p"} {
$w insert end "\n\n" {}
} elseif {$tag == "pre" || $tag == "li" || $tag == "dt" || $tag == "ul" || $tag == "dd" || $tag == "dl"} {
$w insert end "\n" {}
}
} elseif {$type == $gumbo::GUMBO_NODE_TEXT} {
# TODO: This could be simplified.
if {0 <= [lsearch $tagList pre]} {
$w insert end [gumbo::text_get_text $node] $tagList
} else {
$w insert end [regsub -all {\s+} [gumbo::text_get_text $node] " "] $tagList
}
}
}
displayNode [gumbo::output_get_root $output] [list]
$w config -state disabled
gumbo::destroy_output $output
|