summaryrefslogtreecommitdiff
path: root/viewhtml
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