├── .gitignore ├── LICENSE ├── Makefile ├── README.md ├── src ├── 20190423_golang40 │ ├── Makefile │ ├── code │ │ └── deadloop.go │ ├── golang40-zh-TW.slide │ └── imgs │ │ ├── asm0.png │ │ ├── asm_doc.png │ │ ├── goasm.png │ │ ├── memoryLayoutC.jpg │ │ ├── php_pr.png │ │ ├── pr_response.png │ │ ├── trackstacksize.png │ │ └── twitch_heap.png ├── 20190819_coscup │ ├── Makefile │ ├── code │ │ ├── deadloop │ │ │ └── main.go │ │ └── goroutine_example │ │ │ └── main.go │ ├── coroutine.slide │ ├── coscup.slide │ ├── escape.slide │ ├── getgoid.slide │ ├── imgs │ │ ├── asm0.png │ │ ├── asm_doc.png │ │ ├── goasm.png │ │ ├── memoryLayoutC.jpg │ │ ├── php_pr.png │ │ ├── pr_response.png │ │ ├── trackstacksize.png │ │ └── twitch_heap.png │ ├── morestack.slide │ ├── plan9.slide │ └── task_struct.slide ├── README.md └── golang40 │ ├── Makefile │ ├── code │ └── deadloop.go │ ├── golang40-zh-TW.slide │ └── imgs │ ├── asm0.png │ ├── asm_doc.png │ ├── goasm.png │ ├── memoryLayoutC.jpg │ ├── php_pr.png │ ├── pr_response.png │ ├── trackstacksize.png │ └── twitch_heap.png └── themes ├── bright ├── static │ ├── atom-one-dark-reasonable.css │ ├── dir.css │ ├── dir.js │ ├── favicon.ico │ ├── highlight.pack.js │ ├── jquery-ui.js │ ├── jquery.js │ ├── notes.css │ ├── notes.js │ ├── obsidian.css │ ├── play.js │ ├── playground.js │ ├── slides.js │ ├── styles.css │ ├── template.css │ ├── template2.css │ ├── vs2015.css │ └── xcode.css └── templates │ ├── action.tmpl │ ├── article.tmpl │ ├── dir.tmpl │ └── slides.tmpl └── default ├── static ├── atom-one-dark-reasonable.css ├── dir.css ├── dir.js ├── favicon.ico ├── highlight.pack.js ├── jquery-ui.js ├── jquery.js ├── notes.css ├── notes.js ├── obsidian.css ├── play.js ├── playground.js ├── slides.js ├── styles.css ├── template.css ├── vs2015.css └── xcode.css └── templates ├── action.tmpl ├── article.tmpl ├── dir.tmpl └── slides.tmpl /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | node_modules -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Lee Xun leexun.official@gmail.com (c) 2019. All Rights Reserved 2 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | PORT=3999 2 | SLIDE_HOST=127.0.0.1 3 | 4 | all: help 5 | 6 | ## 2019-04-23 Golang meetup #40 7 | 20190423_golang40: 8 | mypresent \ 9 | -http 0.0.0.0:$(PORT) \ 10 | -orighost $(SLIDE_HOST) \ 11 | -content src/20190423_golang40/ \ 12 | -base themes/default 13 | 14 | ## 2019-04-23 Golang meetup #40 15 | 20190720_kaohsiung_kkbox: 16 | mypresent \ 17 | -http 0.0.0.0:$(PORT) \ 18 | -orighost $(SLIDE_HOST) \ 19 | -content src/20190720_kaohsiung_kkbox/ \ 20 | -base themes/bright 21 | 22 | ######### 23 | # Help ## 24 | ######### 25 | # COLORS 26 | GREEN := $(shell tput -Txterm setaf 2) 27 | YELLOW := $(shell tput -Txterm setaf 3) 28 | WHITE := $(shell tput -Txterm setaf 7) 29 | RESET := $(shell tput -Txterm sgr0) 30 | 31 | TARGET_MAX_CHAR_NUM=20 32 | ## Show help 33 | help: 34 | @echo '' 35 | @echo 'Usage:' 36 | @echo ' ${YELLOW}make${RESET} ${GREEN}${RESET}' 37 | @echo '' 38 | @echo 'Targets:' 39 | @awk '/^[a-zA-Z\-\_0-9]+:/ { \ 40 | helpMessage = match(lastLine, /^## (.*)/); \ 41 | if (helpMessage) { \ 42 | helpCommand = substr($$1, 0, index($$1, ":")); \ 43 | helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ 44 | printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \ 45 | } \ 46 | } \ 47 | { lastLine = $$0 }' $(MAKEFILE_LIST) -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # slides 2 | 3 | ## Prerequisite 4 | 5 | ``` 6 | go get -u -v github.com/leexun/mypresent 7 | ``` 8 | 9 | ## Get started 10 | 11 | ``` 12 | git clone git@github.com:LeeXun/slides.git 13 | cd slides 14 | make 15 | ``` 16 | 17 | ## Cautions 18 | Never serve a public web service by this tool. It is only for presentation and provides full control of remote code execution. 19 | 20 | -------------------------------------------------------------------------------- /src/20190423_golang40/Makefile: -------------------------------------------------------------------------------- 1 | PORT=3999 2 | SLIDE_HOST=127.0.0.1 3 | SLIDE_DIR=. 4 | THEME_DIR=./../../themes/default 5 | 6 | all: mypresent 7 | 8 | mypresent: 9 | mypresent \ 10 | -http 0.0.0.0:$(PORT) \ 11 | -orighost $(SLIDE_HOST) \ 12 | -content $(SLIDE_DIR)/ \ 13 | -base $(THEME_DIR)/ 14 | 15 | ######### 16 | # Help ## 17 | ######### 18 | # COLORS 19 | GREEN := $(shell tput -Txterm setaf 2) 20 | YELLOW := $(shell tput -Txterm setaf 3) 21 | WHITE := $(shell tput -Txterm setaf 7) 22 | RESET := $(shell tput -Txterm sgr0) 23 | 24 | TARGET_MAX_CHAR_NUM=20 25 | ## Show help 26 | help: 27 | @echo '' 28 | @echo 'Usage:' 29 | @echo ' ${YELLOW}make${RESET} ${GREEN}${RESET}' 30 | @echo '' 31 | @echo 'Targets:' 32 | @awk '/^[a-zA-Z\-\_0-9]+:/ { \ 33 | helpMessage = match(lastLine, /^## (.*)/); \ 34 | if (helpMessage) { \ 35 | helpCommand = substr($$1, 0, index($$1, ":")); \ 36 | helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ 37 | printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \ 38 | } \ 39 | } \ 40 | { lastLine = $$0 }' $(MAKEFILE_LIST) -------------------------------------------------------------------------------- /src/20190423_golang40/code/deadloop.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func deadloop() { 9 | for { 10 | } 11 | } 12 | 13 | func main() { 14 | go deadloop() 15 | for { 16 | fmt.Println("Main Loop") 17 | time.Sleep(time.Second * 1) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/asm0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/asm0.png -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/asm_doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/asm_doc.png -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/goasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/goasm.png -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/memoryLayoutC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/memoryLayoutC.jpg -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/php_pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/php_pr.png -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/pr_response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/pr_response.png -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/trackstacksize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/trackstacksize.png -------------------------------------------------------------------------------- /src/20190423_golang40/imgs/twitch_heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190423_golang40/imgs/twitch_heap.png -------------------------------------------------------------------------------- /src/20190819_coscup/Makefile: -------------------------------------------------------------------------------- 1 | PORT=3999 2 | SLIDE_HOST=127.0.0.1 3 | SLIDE_DIR=. 4 | THEME_DIR=./../../themes/default 5 | 6 | all: mypresent 7 | 8 | mypresent: 9 | mypresent \ 10 | -http 0.0.0.0:$(PORT) \ 11 | -orighost $(SLIDE_HOST) \ 12 | -content $(SLIDE_DIR)/ \ 13 | -base $(THEME_DIR)/ 14 | 15 | mypresent2: 16 | mypresent \ 17 | -http 0.0.0.0:$(PORT) \ 18 | -orighost $(SLIDE_HOST) \ 19 | -content $(SLIDE_DIR)/ \ 20 | -base ./../../themes/bright/ 21 | 22 | ######### 23 | # Help ## 24 | ######### 25 | # COLORS 26 | GREEN := $(shell tput -Txterm setaf 2) 27 | YELLOW := $(shell tput -Txterm setaf 3) 28 | WHITE := $(shell tput -Txterm setaf 7) 29 | RESET := $(shell tput -Txterm sgr0) 30 | 31 | TARGET_MAX_CHAR_NUM=20 32 | ## Show help 33 | help: 34 | @echo '' 35 | @echo 'Usage:' 36 | @echo ' ${YELLOW}make${RESET} ${GREEN}${RESET}' 37 | @echo '' 38 | @echo 'Targets:' 39 | @awk '/^[a-zA-Z\-\_0-9]+:/ { \ 40 | helpMessage = match(lastLine, /^## (.*)/); \ 41 | if (helpMessage) { \ 42 | helpCommand = substr($$1, 0, index($$1, ":")); \ 43 | helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ 44 | printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \ 45 | } \ 46 | } \ 47 | { lastLine = $$0 }' $(MAKEFILE_LIST) -------------------------------------------------------------------------------- /src/20190819_coscup/code/deadloop/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func deadloop() { 9 | for { 10 | } 11 | } 12 | 13 | func main() { 14 | go deadloop() 15 | for { 16 | fmt.Println("Main Loop") 17 | time.Sleep(time.Second * 1) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/20190819_coscup/code/goroutine_example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func deadloop(id int) { 9 | for { 10 | fmt.Println(id) 11 | time.Sleep(time.Second * 1) 12 | } 13 | } 14 | 15 | func main() { 16 | deadloop(1) 17 | } 18 | -------------------------------------------------------------------------------- /src/20190819_coscup/coroutine.slide: -------------------------------------------------------------------------------- 1 | ############################################################################################### 2 | * Many to 1 3 | ```html 4 |
  5 | 
  6 | 
  7 | 
  8 | 
  9 | 				+------+
 10 | 				|kernal|
 11 | 				+------+
 12 | 	    +---------------+------||-------+---------------+
 13 | 	+---+--+	+---+--+	+---+--+	+---+--+
 14 | 	| user |	| user |	| user |	| user |
 15 | 	+------+	+------+	+------+	+------+
 16 | 
 17 | 
18 | ```htmlend 19 | 20 | ############################################################################################### 21 | * 1 to 1 22 | ```html 23 |
 24 | 
 25 | 
 26 | 
 27 | 
 28 | 	+------+	+------+	+------+	+------+
 29 | 	|kernal|	|kernal|	|kernal|	|kernal|
 30 | 	+------+	+------+	+------+	+------+
 31 | 	    +---------------+---------------+---------------+
 32 | 	+------+	+------+	+------+	+------+
 33 | 	| user |	| user |	| user |	| user |
 34 | 	+------+	+------+	+------+	+------+
 35 | 
 36 | 
37 | ```htmlend 38 | 39 | ############################################################################################### 40 | * Many to Many 41 | ```html 42 |
 43 | 
 44 | 
 45 | 
 46 | 
 47 | 	+------+		+------+		+------+	
 48 | 	|kernal|		|kernal|		|kernal| .......
 49 | 	+------+		+------+		+------+
 50 | 
 51 | 	+------+	+------+	+------+	+------+
 52 | 	| user |	| user |	| user |	| user | .......
 53 | 	+------+	+------+	+------+	+------+
 54 | 
 55 | 
56 | ```htmlend 57 | 58 | ############################################################################################### 59 | * _ 60 | ```html 61 |

Golang 怎麼做?

62 | ```htmlend 63 | 64 | ############################################################################################### 65 | * _ 66 | ```html 67 |

Goroutine?Coroutine?

68 | ```htmlend 69 | 70 | ############################################################################################### 71 | * Coroutine 72 | ```html 73 |
 74 | 
 75 | // http://blog.linux.org.tw/~jserv/archives/001848.html
 76 | 
 77 | static int state = 0;
 78 | 
 79 | static void user_thread_1()
 80 | {
 81 |     state = 0;
 82 |     for ( ; ; ) {
 83 |         printf("1\n");
 84 |         state += 1;
 85 |         if (state > 10) {
 86 |             return;
 87 |         }
 88 |     }
 89 | }
 90 | 
 91 | static void user_thread_2()
 92 | {
 93 |     state = 0;
 94 |     for ( ; ; ) {
 95 |         printf("2\n");
 96 |         state += 1;
 97 |         if (state > 10) {
 98 |             return;
 99 |         }
100 |     }
101 | }
102 | 
103 | int main() 
104 | {
105 |   for ( ; ; ) {
106 |     user_thread_1();
107 |     user_thread_2();
108 |   }
109 |   return 0;
110 | }
111 | 
112 | 
113 | ```htmlend 114 | 115 | ############################################################################################### 116 | * Goroutine 117 | ```html 118 |
119 | 
120 | 
121 | 
122 | 	+------+	+------+	+------+	+------+
123 | 	| core |	| core |	| core |	| core |
124 | 	+------+	+------+	+------+	+------+
125 | 
126 | 	+------+	+------+	+------+	+------+
127 | 	|kernal|	|kernal|	|kernal|	|kernal|
128 | 	+------+	+------+	+------+	+------+
129 | 	    +---------------+---------------+---------------+
130 | 	+------+	+------+	+------+	+------+
131 | 	| user |	| user |	| user |	| user | <- 同一個 process
132 | 	+------+	+------+	+------+	+------+
133 | 
134 | 	G G G G G G G G G G G G G G G G G G G G G G G G G G G G ...
135 | 
136 | 
137 | ```htmlend 138 | 139 | ############################################################################################### 140 | * Why many to many? 141 | ```html 142 |
    143 |
  • 妥善利用硬體多核心
  • 144 |
  • 減少依賴 OS context switch
  • 145 |
  • 減少和 kernal 溝通成本
  • 146 |
  • 創建 thread 的開銷大
  • 147 |
  • 配合 golang 垃圾回收機制的實作
  • 148 |
149 | ```htmlend 150 | 151 | ############################################################################################### 152 | * Let's try this 153 | .monaco ./code/goroutine_example/main.go 154 | 155 | # 這邊要 demo 156 | #1. 會死 157 | #1. 加上 go 不會死 -------------------------------------------------------------------------------- /src/20190819_coscup/escape.slide: -------------------------------------------------------------------------------- 1 | ############################################################################################### 2 | * _ 3 | ```html 4 |

當時被 Go 吸引的原因

5 | ```htmlend 6 | 7 | ############################################################################################### 8 | * _ 9 | ```html 10 |

Assembly

11 | ```htmlend 12 | 13 | ############################################################################################### 14 | * C 的 helloworld! 15 | ```html 16 |
 17 | 
 18 |   int main()
 19 |   {
 20 |     printf("Hello, 世界\n");
 21 |     return 0;
 22 |   }
 23 | 
 24 | 
25 |
 26 | 
 27 |   0x00000000004004e7 <+0>:	push   %rbp
 28 |   0x00000000004004e8 <+1>:	mov    %rsp,%rbp
 29 |   0x00000000004004eb <+4>:	lea    0x92(%rip),%rdi # 0x400584
 30 |   0x00000000004004f2 <+11>:	callq  0x4003f0 
 31 |   0x00000000004004f7 <+16>:	mov    $0x0,%eax
 32 |   0x00000000004004fc <+21>:	pop    %rbp
 33 |   0x00000000004004fd <+22>:	retq  
 34 | 
 35 | 
36 | ```htmlend 37 | 38 | ############################################################################################### 39 | * _ 40 | ```html 41 |

有趣的是

42 | ```htmlend 43 | 44 | ############################################################################################### 45 | * Go 的 helloworld! 46 | ```html 47 |
 48 | 
 49 | package main
 50 | 
 51 | import "fmt"
 52 | 
 53 | func main() {
 54 | 	fmt.Println("Hello, 世界")
 55 | }
 56 | 
 57 | 
58 | ```htmlend 59 | 60 | ############################################################################################### 61 | * . . . 62 | ```html 63 |
 64 | 
 65 | 0x00000000004871b0 <+0>:	mov    %fs:0xfffffffffffffff8,%rcx
 66 | 0x00000000004871b9 <+9>:	cmp    0x10(%rcx),%rsp
 67 | 0x00000000004871bd <+13>:	jbe    0x487230 # main.main+128
 68 | 0x00000000004871bf <+15>:	sub    $0x58,%rsp
 69 | 0x00000000004871c3 <+19>:	mov    %rbp,0x50(%rsp)
 70 | 0x00000000004871c8 <+24>:	lea    0x50(%rsp),%rbp
 71 | 0x00000000004871cd <+29>:	xorps  %xmm0,%xmm0
 72 | 0x00000000004871d0 <+32>:	movups %xmm0,0x40(%rsp)
 73 | 0x00000000004871d5 <+37>:	lea    0x11204(%rip),%rax        # 0x4983e0
 74 | 0x00000000004871dc <+44>:	mov    %rax,0x40(%rsp)
 75 | 0x00000000004871e1 <+49>:	lea    0x485d8(%rip),%rax        # 0x4cf7c0 main.statictmp_0
 76 | 0x00000000004871e8 <+56>:	mov    %rax,0x48(%rsp)
 77 | 0x00000000004871ed <+61>:	nop
 78 | 0x00000000004871ee <+62>:	mov    0xd05fb(%rip),%rax        # 0x5577f0 os.Stdout
 79 | 0x00000000004871f5 <+69>:	lea    0x49ac4(%rip),%rcx        # 0x4d0cc0 go.itab.*os.File,io.Writer
 80 | 0x00000000004871fc <+76>:	mov    %rcx,(%rsp)
 81 | 0x0000000000487200 <+80>:	mov    %rax,0x8(%rsp)
 82 | 0x0000000000487205 <+85>:	lea    0x40(%rsp),%rax
 83 | 0x000000000048720a <+90>:	mov    %rax,0x10(%rsp)
 84 | 0x000000000048720f <+95>:	movq   $0x1,0x18(%rsp)
 85 | 0x0000000000487218 <+104>:	movq   $0x1,0x20(%rsp)
 86 | 0x0000000000487221 <+113>:	callq  0x480b60  # fmt.Fprintln
 87 | 0x0000000000487226 <+118>:	mov    0x50(%rsp),%rbp
 88 | 0x000000000048722b <+123>:	add    $0x58,%rsp
 89 | 0x000000000048722f <+127>:	retq   
 90 | 0x0000000000487230 <+128>:	callq  0x44f340 # runtime.morestack_noctxt
 91 | 0x0000000000487235 <+133>:	jmpq   0x4871b0 # main.main
 92 | 
 93 | 
94 | ```htmlend 95 | 96 | ############################################################################################### 97 | * _ 98 | ```html 99 |

Stack or Heap

100 | ```htmlend 101 | 102 | ############################################################################################### 103 | * 這好像哪裡有點神奇 104 | ```html 105 |
106 | 
107 | func newA() *int {
108 | 	var a int = 0
109 | 	return &a
110 | }
111 | 
112 | func newB() *int {
113 | 	var b int = 1
114 | 	return &b
115 | }
116 | 
117 | func main() {
118 | 	a := newA()
119 | 	b := newB()
120 | 	fmt.Printf("%v\n", *a)
121 | 	fmt.Printf("%v\n", *b)
122 | }
123 | 
124 | 
125 | ```htmlend 126 | 127 | ############################################################################################### 128 | * In C 129 | ```html 130 |
131 | 
132 | int *newA() {
133 |   int a = 0;
134 |   return &a;
135 | }
136 | 
137 | int *newB() {
138 |   int b = 1;
139 |   return &b;
140 | }
141 | 
142 | int main() {
143 |   int *a = newA();
144 |   int *b = newB();
145 |   printf("a: %d\n", *a);
146 |   printf("b: %d\n", *b);
147 |   return 0;
148 | }
149 | 
150 | 
151 | ```htmlend 152 | 153 | ############################################################################################### 154 | * In C 155 | ```html 156 |
157 | 
158 | int *newA() {
159 |   int a = 0;
160 |   return &a;
161 | }
162 | 
163 | int *newB() {
164 |   int b = 1;
165 |   return &b;
166 | }
167 | 
168 | int main() {
169 |   int *a = newA();
170 |   int *b = newB();
171 |   printf("a: %d\n", *a); // a: 1
172 |   printf("b: %d\n", *b); // b: 1490617567
173 |   return 0;
174 | }
175 | 
176 | 
177 | ```htmlend 178 | 179 | ############################################################################################### 180 | * In Go 181 | ```html 182 |
183 | 
184 | func newA() *int {
185 | 	var a int = 0
186 | 	return &a
187 | }
188 | 
189 | func newB() *int {
190 | 	var b int = 1
191 | 	return &b
192 | }
193 | 
194 | func main() {
195 | 	a := newA()
196 | 	b := newB()
197 | 	fmt.Printf("%v\n", *a)   // a: 0
198 | 	fmt.Printf("%v\n", *b)   // a: 1
199 | }
200 | 
201 | 
202 | ```htmlend 203 | 204 | ############################################################################################### 205 | * _ 206 | ```html 207 |

What happened?

208 | ```htmlend 209 | 210 | ############################################################################################### 211 | * Escape 212 | ```html 213 |
214 | 
215 |   high   +-------+
216 |          |  ...  |
217 |          +-------+
218 |          |  ...  |
219 |          +-------+           int *newA() {
220 |          |  ...  |               int a = 0; // loc1
221 |          +-------+               return &a;
222 |          |ret(&a)|           }
223 |          +-------+
224 |          | readdr|
225 |          +-------+
226 |          |   BP  |
227 |          +-------+
228 |          | a = 0 | 
229 |          +-------+ <- &a = 0x7ffeec3156dc
230 |          |  ...  | 
231 |   low    +-------+ 
232 | 
233 | 
234 | ```htmlend 235 | 236 | ############################################################################################### 237 | * Escape 238 | ```html 239 |
240 | 
241 |   high   +-------+ 
242 |          |  xxxx |
243 |          +-------+
244 |          |  xxxx |
245 |          +-------+
246 |          |  xxxx |
247 |          +-------+
248 |          |ret(&a)|
249 |          +-------+  function 已經結束
250 |          | readdr|
251 |          +-------+
252 |          |   BP  |
253 |          +-------+
254 |          | a = 0 | 
255 |          +-------+ <- &a 這還能用嗎?
256 |          |  xxxx | 
257 |   low    +-------+
258 | 
259 | 
260 | ```htmlend 261 | 262 | ############################################################################################### 263 | * Escape 264 | ```html 265 |
266 | 
267 |   high   +-------+
268 |          |  ...  |
269 |          +-------+
270 |          |  ...  |
271 |          +-------+           int *newB() {
272 |          |  ...  |               int b = 1; // loc1
273 |          +-------+               return &b;
274 |          |ret(&b)|           }
275 |          +-------+
276 |          | readdr|
277 |          +-------+
278 |          |   BP  |
279 |          +-------+
280 |          | b = 1 | 
281 |          +-------+ <- &b = 0x7ffeec3156dc 這個位址又被用走了
282 |          |  ...  |         之後又會被 printf 之後的用髒: 1490617567
283 |   low    +-------+ 
284 | 
285 | 
286 | ```htmlend 287 | 288 | ############################################################################################### 289 | * In Go 290 | ```html 291 |
292 | 
293 | func newA() *int {
294 | 	var a int = 0
295 | 	return &a
296 | }
297 | 
298 | func newB() *int {
299 | 	var b int = 1
300 | 	return &b
301 | }
302 | 
303 | func main() {
304 | 	a := newA()
305 | 	b := newB()
306 | 	fmt.Printf("%v\n", *a)   // a: 0
307 | 	fmt.Printf("%v\n", *b)   // a: 1
308 | }
309 | 
310 | 
311 | ```htmlend 312 | 313 | ############################################################################################### 314 | * Escape 315 | ```html 316 |
317 | 
318 |    go tool compile -m main.go
319 | // main.go:5:6: can inline X
320 | // main.go:10:6: can inline ChangeX
321 | // main.go:15:8: inlining call to X
322 | // main.go:16:9: inlining call to ChangeX
323 | // main.go:17:12: inlining call to fmt.Printf
324 |    main.go:7:9: &x escapes to heap            <- escape to heap!!!!
325 |    main.go:6:6: moved to heap: x
326 | // main.go:10:14: ChangeX xp does not escape
327 | // main.go:17:21: *x escapes to heap
328 | // main.go:17:12: io.Writer(os.Stdout) escapes to heap
329 | // main.go:15:8: main &x does not escape
330 | // main.go:17:12: main []interface {} literal does not escape
331 | // :1: os.(*File).close .this does not escape
332 | 
333 | 
334 | ```htmlend 335 | 336 | ############################################################################################### 337 | * Twitch heap 338 | .image imgs/twitch_heap.png 480 _ -------------------------------------------------------------------------------- /src/20190819_coscup/getgoid.slide: -------------------------------------------------------------------------------- 1 | 2 | ############################################################################################### 3 | * _ 4 | ```html 5 |

從組合語言開始

6 | ```htmlend 7 | #如果太複雜算不出來,那就用 go tool objdump, go vet 8 | 9 | ############################################################################################### 10 | * _ 11 | ```html 12 |

怎麼開始?

13 | ```htmlend 14 | 15 | ############################################################################################### 16 | * _ 17 | ```html 18 |

偷看 goroutine 的 id

19 | ```htmlend 20 | 21 | ############################################################################################### 22 | * Plan9 getgoid 23 | ```html 24 |
 25 | 
 26 | // src/runtime/runtime2.go
 27 | type g struct {
 28 | 	stack       stack   // offset known to runtime/cgo
 29 | 	stackguard0 uintptr // offset known to liblink
 30 | 	stackguard1 uintptr // offset known to liblink
 31 | 
 32 | 	_panic         *_panic // innermost panic - offset known to liblink
 33 | 	_defer         *_defer // innermost defer
 34 | 	m              *m      // current m; offset known to arm liblink
 35 | 	sched          gobuf
 36 | 	syscallsp      uintptr        
 37 | 	syscallpc      uintptr        
 38 | 	stktopsp       uintptr // expected sp at top of stack, to check in traceback
 39 | 	param          unsafe.Pointer // passed parameter on wakeup
 40 | 	atomicstatus   uint32
 41 | 	stackLock      uint32 // sigprof/scang lock; TODO: fold in to atomicstatus
 42 | 底加 ->	goid           int64  
 43 | 
 44 | 
45 | ```htmlend 46 | 47 | ############################################################################################### 48 | * Plan9 getgoid 49 | ```html 50 |
 51 | 
 52 | // src/runtime/stubs.go
 53 | package runtime
 54 | 
 55 | import "unsafe"
 56 | 
 57 | // Should be a built-in for unsafe.Pointer?
 58 | //go:nosplit
 59 | func add(p unsafe.Pointer, x uintptr) unsafe.Pointer {
 60 | 	return unsafe.Pointer(uintptr(p) + x)
 61 | }
 62 | 
 63 | // getg returns the pointer to the current g.
 64 | // The compiler rewrites calls to this function into instructions
 65 | // that fetch the g directly (from TLS or from the dedicated register).
 66 | func getg() *g <- 底加
 67 | 
 68 | 
 69 | 
70 | ```htmlend 71 | 72 | ############################################################################################### 73 | * _ 74 | ```html 75 |

?? func getg() *g ??

76 |

所以我說那個 body 呢

77 | ```htmlend 78 | 79 | ############################################################################################### 80 | * Plan9 getgoid 81 | ```html 82 |
 83 | 
 84 | // src/cmd/compile/internal/amd64/ssa.go
 85 | 	case ssa.OpAMD64LoweredGetG:   <- GetG!!!!
 86 | 		r := v.Reg()
 87 | 		// See the comments in cmd/internal/obj/x86/obj6.go
 88 | 		// near CanUse1InsnTLS for a detailed explanation of these instructions.
 89 | 		if x86.CanUse1InsnTLS(gc.Ctxt) { <- 可以只用一個指令就拿到 TLS
 90 | 			// MOVQ (TLS), r  
 91 | 			p := s.Prog(x86.AMOVQ)
 92 | 			p.From.Type = obj.TYPE_MEM
 93 | 			p.From.Reg = x86.REG_TLS
 94 | 			p.To.Type = obj.TYPE_REG
 95 | 			p.To.Reg = r
 96 | 		} else {                         <- 不行
 97 | 			// MOVQ TLS, r
 98 | 			// MOVQ (r)(TLS*1), r
 99 | 			p := s.Prog(x86.AMOVQ)
100 | 
101 | 
102 | ```htmlend 103 | 104 | ############################################################################################### 105 | * TLS, Thread local storage 106 | ```html 107 |
    108 |
  • 用意:利用 static or global memory 去儲存狀態
  • 109 |
  • Go 的 G,M,P 模型中 M 就相當於 thread
  • 110 |
  • Linux, libc pthread
  • 111 |
      112 |
    • pthread_key_create, pthread_key_delete
    • 113 |
    114 |
  • Windows
  • 115 |
      116 |
    • TlsGetValue, TlsSetValue
    • 117 |
    118 |
119 | ```htmlend 120 | .caption [[https://en.wikipedia.org/wiki/Win32_Thread_Information_Block][Win32 TIB TEB]] 121 | 122 | ############################################################################################### 123 | * _ 124 | ```html 125 |

Plan 9

126 | ```htmlend 127 | 128 | ############################################################################################### 129 | * Plan9 的指令操作方向 130 | ```html 131 |
132 | 
133 | 
134 |          plan9                            intel 
135 |            |                                | 
136 |       MOVQ $0x10, AX                   mov rax, 0x10
137 |            |------>                         <-----|
138 | 
139 | 
140 |        ; 和 AT&T 類似                     ; 和 intel 相反
141 | 
142 | 
143 | 
144 | ```htmlend 145 | .caption 凡事都以例外,好奇的話請看 [[https://quasilyte.dev/blog/files/x86_2.csv][完整列表]] 146 | ```html 147 |
    148 |
  • gdb 可以用 set disassembly-flavor intel 把他從 AT&T 改顯示 intel
  • 149 |
  • 為了不讓大家轉換得太辛苦,後面的 gdb 例子都是用 AT&T
  • 150 |
151 | ```htmlend 152 | 153 | ############################################################################################### 154 | * Plan9 getgoid 155 | ```html 156 |
157 | 
158 | // main_amd64.s
159 |  #include "funcdata.h"
160 |  #include "textflag.h"
161 | 
162 |  #define get_tls(r)	MOVQ TLS, r
163 |  #define g(r)		0(r)(TLS*1)	<- TLS, Thread local storage
164 |  #define g_goid(r)	152(r)		<- 152 是哪裡來的?
165 | 
166 |  TEXT ·getgoid(SB),NOSPLIT,$0
167 | 	 get_tls(CX)
168 | 	 MOVQ	g(CX), AX        <- 先到 g
169 | 	 MOVQ	g_goid(AX), AX   <- 再從 g 到 goid
170 | 	 MOVQ	AX, ret+0(FP)    
171 | 	 RET
172 | 
173 | 
174 | ```htmlend 175 | 176 | ############################################################################################### 177 | * Plan9 getgoid 178 | ```html 179 |
180 | 
181 | // main.go
182 | func getgoid() int64 // 不用 body
183 | 
184 | func routine() {
185 | 	// 這邊故意讓他 panic,看我們抓到的對不對
186 | 	panic(fmt.Sprintf("getgoid: %d\n", getgoid()))
187 | 	time.Sleep(time.Second * 1)
188 | }
189 | 
190 | func main() {
191 | 	go routine()
192 | 	for {
193 | 		time.Sleep(time.Second * 1)
194 | 		fmt.Printf("0: %x\n", getgoid())
195 | 	}
196 | }
197 | 
198 | 
199 | ```htmlend 200 | 201 | ############################################################################################### 202 | * Plan9 getgoid 203 | ```html 204 |
205 | 
206 | panic: getgoid: 18           <- 讚喔!
207 | 
208 | goroutine 18 [running]:      <-
209 | //main.routine()
210 | //	/root/lab/40gomeetup/code/getg/main.go:13 +0x111
211 | //created by main.main
212 | //	/root/lab/40gomeetup/code/getg/main.go:18 +0x47
213 | 
214 | 
215 | ```htmlend 216 | 217 | ############################################################################################### 218 | * 至於那個 152 是怎麼來的? 219 | ```html 220 |
221 | 
222 | // src/runtime/runtime2/go
223 | type stack struct { // *2
224 | 	lo uintptr
225 | 	hi uintptr
226 | }
227 | 
228 | type gobuf struct { // *7
229 | 	sp   uintptr
230 | 	pc   uintptr
231 | 	g    guintptr // type guintptr uintptr
232 | 	ctxt unsafe.Pointer
233 | 	ret  sys.Uintreg // type Uintreg uint64 看平台
234 | 	lr   uintptr
235 | 	bp   uintptr // for GOEXPERIMENT=framepointer
236 | }
237 | 
238 | 
239 | ```htmlend 240 | 241 | ############################################################################################### 242 | * 至於那個 152 是怎麼來的? 243 | ```html 244 |
245 | 
246 | // src/runtime/runtime2/go
247 | type g struct { // 2+7+1+9 = 19*8 = 152
248 | 	stack       stack   // 2
249 | 	stackguard0 uintptr // 1
250 | 	stackguard1 uintptr // 1
251 | 
252 | 	_panic         *_panic 	 // 1
253 | 	_defer         *_defer 	 // 1
254 | 	m              *m 	 // 1
255 | 	sched          gobuf	 // 7
256 | 	syscallsp      uintptr	 // 1        
257 | 	syscallpc      uintptr	 // 1
258 | 	stktopsp       uintptr	 // 1        
259 | 	param          unsafe.Pointer // 1
260 | 	atomicstatus   uint32 // 0.5
261 | 	stackLock      uint32 // 0.5
262 | 	goid           int64  <- 底加
263 |   //...
264 | 
265 | 
266 | ```htmlend 267 | 268 | ############################################################################################### 269 | * _ 270 | ```html 271 |

其實編譯原始碼時

272 |

有個檔案叫做 go_asm.h

273 | ```htmlend 274 | 275 | ############################################################################################### 276 | * _ 277 | .image imgs/goasm.png 278 | 279 | ############################################################################################### 280 | * 官方文件的雷 281 | .image imgs/asm_doc.png 350 _ 282 | .caption 是在 go_tls.h,不是 go_asm.h,而且 go_asm.h 在編譯完就被刪除了 283 | 284 | ############################################################################################### 285 | * PR 後官方的回應 286 | .image imgs/pr_response.png 480 _ -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/asm0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/asm0.png -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/asm_doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/asm_doc.png -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/goasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/goasm.png -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/memoryLayoutC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/memoryLayoutC.jpg -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/php_pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/php_pr.png -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/pr_response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/pr_response.png -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/trackstacksize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/trackstacksize.png -------------------------------------------------------------------------------- /src/20190819_coscup/imgs/twitch_heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/20190819_coscup/imgs/twitch_heap.png -------------------------------------------------------------------------------- /src/20190819_coscup/morestack.slide: -------------------------------------------------------------------------------- 1 | ############################################################################################### 2 | * _ 3 | ```html 4 |

runtime.morestack_noctxt

5 | ```htmlend 6 | 7 | ############################################################################################### 8 | * MoreStack 9 | ```html 10 |
 11 | 
 12 | // morestack but not preserving ctxt.
 13 | 
 14 | TEXT runtime·morestack_noctxt(SB),NOSPLIT,$0
 15 | 	MOVL	$0, DX
 16 | 	JMP	runtime·morestack(SB)
 17 | 
 18 | 
19 | ```htmlend 20 | 21 | ############################################################################################### 22 | * Closure 23 | ```html 24 |
 25 | 
 26 | func adder() func(int) int {
 27 | 	sum := 0
 28 | 	return func(x int) int { <- closure
 29 | 		sum += x
 30 | 		return sum
 31 | 	}
 32 | }
 33 | 
 34 | func main() {
 35 | 	pos, neg := adder(), adder()
 36 | 	for i := 0; i < 10; i++ {
 37 | 		fmt.Println(
 38 | 			pos(i),
 39 | 			neg(-2*i),
 40 | 		)
 41 | 	}
 42 | }
 43 | 
 44 | 
 45 | 
46 | ```htmlend 47 | 48 | ############################################################################################### 49 | * MoreStack 50 | ```html 51 |
 52 | 
 53 | // src/cmd/internal/obj/x86/obj6.go
 54 | 	// ...
 55 | 	morestack := "runtime.morestack"
 56 | 	switch {
 57 | 	case cursym.CFunc():
 58 | 		morestack = "runtime.morestackc"
 59 | 	case !cursym.Func.Text.From.Sym.NeedCtxt():  <- 不是 closure,不需要
 60 | 		morestack = "runtime.morestack_noctxt"
 61 | 	}
 62 | 
 63 | 
64 | ```htmlend 65 | 66 | ############################################################################################### 67 | * MoreStack 68 | ```html 69 |
 70 | 
 71 | TEXT runtime·morestack(SB),NOSPLIT,$0-0
 72 | 	// Cannot grow scheduler stack (m->g0).
 73 | 	get_tls(CX)
 74 | 	MOVQ	g(CX), BX
 75 | 	MOVQ	g_m(BX), BX
 76 | 	MOVQ	m_g0(BX), SI
 77 | 	CMPQ	g(CX), SI <- 是不是 g0
 78 | 	JNE	3(PC) <- 如果不是 g0 就跳三行 (( 跳過下面兩行
 79 | 	CALL	runtime·badmorestackg0(SB) <- 在 schedule stack
 80 | 	CALL	runtime·abort(SB)
 81 | 	...
 82 | 	MOVQ	m_g0(BX), BX
 83 | 	MOVQ	BX, g(CX)
 84 | 	MOVQ	(g_sched+gobuf_sp)(BX), SP
 85 | 	CALL	runtime·newstack(SB)    <- newstack!!
 86 | 	CALL	runtime·abort(SB)	// crash if newstack returns
 87 | 	RET
 88 | 
 89 | 
90 | ```htmlend 91 | 92 | ############################################################################################### 93 | * NewStack 94 | ```html 95 |
 96 | 
 97 | // src/runtime/stack.go
 98 | var maxstacksize uintptr = 1 << 20
 99 | // ...
100 | func newstack() {
101 | 	thisg := getg()
102 | 	// TODO: double check all gp. shouldn't be getg().
103 | 	// ...
104 | 	gp := thisg.m.curg  <- 得讓 m 來記住,不然換新時會消失
105 | 	// ...
106 | 		// Allocate a bigger segment and move the stack.
107 | 	oldsize := gp.stack.hi - gp.stack.lo
108 | 	newsize := oldsize * 2  <- 每次長大長兩倍
109 | 	if newsize > maxstacksize {
110 | 		print("runtime: goroutine stack exceeds ", maxstacksize, "-byte limit\n")
111 | 		throw("stack overflow")
112 | 	}
113 | 
114 | 
115 | ```htmlend 116 | 117 | ############################################################################################### 118 | * NewStack 119 | ```html 120 |
121 | 
122 | // src/runtime/stack.go
123 | // ...
124 | func newstack() {
125 | 	thisg := getg()
126 | 	// ...
127 | 	gp := thisg.m.curg
128 | 	// ...
129 | 	preempt := atomic.Loaduintptr(&gp.stackguard0) == stackPreempt
130 | 	// ...
131 | 		if preempt {
132 | 		if thisg.m.locks != 0 || thisg.m.mallocing != 0
133 | 		 || thisg.m.preemptoff != "" 
134 | 		 || thisg.m.p.ptr().status != _Prunning {
135 | 			// Let the goroutine keep running for now.
136 | 			// gp->preempt is set, so it will be preempted next time.
137 | 			gp.stackguard0 = gp.stack.lo + _StackGuard
138 | 			gogo(&gp.sched) // never return
139 | 		}
140 | 	}
141 | 
142 | 
143 | ```htmlend 144 | 145 | ############################################################################################### 146 | * NewStack 147 | ```html 148 |
149 | 
150 | // src/runtime/stack.go
151 | const (
152 | 	uintptrMask = 1<<(8*sys.PtrSize) - 1
153 | 
154 | 	// Goroutine preemption request.
155 | 	// Stored into g->stackguard0 to cause split stack check failure.
156 | 	// Must be greater than any real sp.
157 | 	// 0xfffffade in hex.            <- 剛剛看到的那個
158 | 	stackPreempt = uintptrMask & -1314
159 | 
160 | 	// Thread is forking.
161 | 	// Stored into g->stackguard0 to cause split stack check failure.
162 | 	// Must be greater than any real sp.
163 | 	stackFork = uintptrMask & -1234
164 | )
165 | 
166 | 
167 | ```htmlend 168 | 169 | ############################################################################################### 170 | * NewStack 171 | ```html 172 |
173 | 
174 | // src/runtime/stack.go
175 | 	if preempt {
176 | 		if gp == thisg.m.g0 {
177 | 			throw("runtime: preempt g0")
178 | 		}
179 | 		if thisg.m.p == 0 && thisg.m.locks == 0 {
180 | 			throw("runtime: g is running but p is not")
181 | 		}
182 | 		// Synchronize with scang.
183 | 		casgstatus(gp, _Grunning, _Gwaiting)
184 | 		// ...
185 | 		// Act like goroutine called runtime.Gosched.
186 | 		casgstatus(gp, _Gwaiting, _Grunning)
187 | 		gopreempt_m(gp) // never return  <- 就算正在跑還是處理一下就給插隊
188 | 	}
189 | 
190 | 
191 | ```htmlend -------------------------------------------------------------------------------- /src/20190819_coscup/task_struct.slide: -------------------------------------------------------------------------------- 1 | Process and Thread 2 | Presented by Lee Xun 3 | 4 | ############################################################################################### 5 | * _ 6 | ```html 7 |

Multi-process

8 |

Multi-thread?

9 | ```htmlend 10 | 11 | ############################################################################################### 12 | * 在 Linux, process, thread 都是 task_struct 13 | ```html 14 |
15 | 
16 | struct task_struct {
17 | 	void				*stack; // kernal stack
18 | 	volatile long			state; /* -1 unrunnable, 0 runnable, >0 stopped: */
19 | 	struct mm_struct		*mm; // 指向 virtual memory 區塊
20 | 	struct mm_struct		*active_mm; // 有緣再說
21 | 	pid_t				pid;
22 | 	struct pid			*thread_pid;
23 | 	struct list_head		children;
24 | 	struct list_head		sibling;
25 | 	/* ... */
26 | 	/* CPU-specific state of this task: */
27 | 	struct thread_struct		thread;
28 | 
29 | 	/*
30 | 	 * WARNING: on x86, 'thread_struct' contains a variable-sized
31 | 	 * structure.  It *MUST* be at the end of 'task_struct'.
32 | 	 *
33 | 	 * Do not put anything below here!
34 | 	 */
35 | }
36 | 
37 | 	// https://sourcegraph.com/github.com/torvalds/linux/-/blob/include/linux/sched.h#L634
38 | 
39 | 
40 | ```htmlend 41 | 42 | ############################################################################################### 43 | * Process and Thread 44 | ```html 45 |
46 | 
47 | struct mm_struct {
48 | 	unsigned long start_stack; // user stack
49 | 	/* ... */
50 | }
51 | 
52 | 	// https://sourcegraph.com/github.com/torvalds/linux/-/blob/include/linux/sched.h#L634
53 | 	// https://sourcegraph.com/github.com/torvalds/linux/-/blob/include/linux/mm_types.h#L354
54 | 	// https://sourcegraph.com/github.com/torvalds/linux/-/blob/arch/x86/include/asm/processor.h#L440:1
55 | 	// https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/createthread.c.html#103
56 | 
57 | 
58 | ```htmlend 59 | 60 | ############################################################################################### 61 | * Process and Thread 62 | ```html 63 |
64 | 
65 | // https://sourcegraph.com/github.com/torvalds/linux/-/blob/arch/x86/include/asm/processor.h#L440:1
66 | struct thread_struct {
67 | 	/* Cached TLS descriptors: */
68 | 	struct desc_struct	tls_array[GDT_ENTRY_TLS_ENTRIES];
69 | 	unsigned long		sp0; // kernal thread 的 rbp,stack 的尾
70 | 	unsigned long		sp; // kernal thread 的 rsp,stack 的頭
71 | 
72 | 
73 | 
74 | ```htmlend 75 | 76 | ############################################################################################### 77 | * Process and Thread 78 | ```html 79 |
80 | 
81 | // glibc/sysdeps/unix/sysv/linux/createthread.c
82 | // https://code.woboq.org/userspace/glibc/sysdeps/unix/sysv/linux/createthread.c.html#103
83 |   const int clone_flags = (CLONE_VM | CLONE_FS | CLONE_FILES | CLONE_SYSVSEM
84 |                            | CLONE_SIGHAND | CLONE_THREAD
85 |                            | CLONE_SETTLS | CLONE_PARENT_SETTID
86 |                            | CLONE_CHILD_CLEARTID
87 |                            | 0);
88 |   TLS_DEFINE_INIT_TP (tp, pd); // init thread pointer
89 |   if (__glibc_unlikely (ARCH_CLONE (&start_thread, STACK_VARIABLES_ARGS,
90 |                                     clone_flags, pd, &pd->tid, tp, &pd->tid)
91 |                         == -1))
92 | 		return errno;
93 | 
94 | 
95 | 
96 | ```htmlend -------------------------------------------------------------------------------- /src/README.md: -------------------------------------------------------------------------------- 1 | The deadloop example presented in my 2019 talks has been deprecated since the upgrade in go1.15 [ref: https://github.com/golang/go/issues/10958](https://github.com/golang/go/issues/10958). I will still keep the content just for reference :) 2 | -------------------------------------------------------------------------------- /src/golang40/Makefile: -------------------------------------------------------------------------------- 1 | PORT=3999 2 | SLIDE_HOST=127.0.0.1 3 | SLIDE_DIR=. 4 | THEME_DIR=./../../themes/default 5 | 6 | all: mypresent 7 | 8 | mypresent: 9 | mypresent \ 10 | -http 0.0.0.0:$(PORT) \ 11 | -orighost $(SLIDE_HOST) \ 12 | -content $(SLIDE_DIR)/ \ 13 | -base $(THEME_DIR)/ 14 | 15 | ######### 16 | # Help ## 17 | ######### 18 | # COLORS 19 | GREEN := $(shell tput -Txterm setaf 2) 20 | YELLOW := $(shell tput -Txterm setaf 3) 21 | WHITE := $(shell tput -Txterm setaf 7) 22 | RESET := $(shell tput -Txterm sgr0) 23 | 24 | TARGET_MAX_CHAR_NUM=20 25 | ## Show help 26 | help: 27 | @echo '' 28 | @echo 'Usage:' 29 | @echo ' ${YELLOW}make${RESET} ${GREEN}${RESET}' 30 | @echo '' 31 | @echo 'Targets:' 32 | @awk '/^[a-zA-Z\-\_0-9]+:/ { \ 33 | helpMessage = match(lastLine, /^## (.*)/); \ 34 | if (helpMessage) { \ 35 | helpCommand = substr($$1, 0, index($$1, ":")); \ 36 | helpMessage = substr(lastLine, RSTART + 3, RLENGTH); \ 37 | printf " ${YELLOW}%-$(TARGET_MAX_CHAR_NUM)s${RESET} ${GREEN}%s${RESET}\n", helpCommand, helpMessage; \ 38 | } \ 39 | } \ 40 | { lastLine = $$0 }' $(MAKEFILE_LIST) -------------------------------------------------------------------------------- /src/golang40/code/deadloop.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "time" 6 | ) 7 | 8 | func deadloop() { 9 | for { 10 | } 11 | } 12 | 13 | func main() { 14 | go deadloop() 15 | for { 16 | fmt.Println("Main Loop") 17 | time.Sleep(time.Second * 1) 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /src/golang40/imgs/asm0.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/asm0.png -------------------------------------------------------------------------------- /src/golang40/imgs/asm_doc.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/asm_doc.png -------------------------------------------------------------------------------- /src/golang40/imgs/goasm.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/goasm.png -------------------------------------------------------------------------------- /src/golang40/imgs/memoryLayoutC.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/memoryLayoutC.jpg -------------------------------------------------------------------------------- /src/golang40/imgs/php_pr.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/php_pr.png -------------------------------------------------------------------------------- /src/golang40/imgs/pr_response.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/pr_response.png -------------------------------------------------------------------------------- /src/golang40/imgs/trackstacksize.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/trackstacksize.png -------------------------------------------------------------------------------- /src/golang40/imgs/twitch_heap.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/src/golang40/imgs/twitch_heap.png -------------------------------------------------------------------------------- /themes/bright/static/atom-one-dark-reasonable.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Atom One Dark With support for ReasonML by Gidi Morris, based off work by Daniel Gamage 4 | 5 | Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax 6 | 7 | */ 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | line-height: 1.3em; 13 | color: #abb2bf; 14 | background: #282c34; 15 | border-radius: 5px; 16 | } 17 | .hljs-keyword, .hljs-operator { 18 | color: #F92672; 19 | } 20 | .hljs-pattern-match { 21 | color: #F92672; 22 | } 23 | .hljs-pattern-match .hljs-constructor { 24 | color: #61aeee; 25 | } 26 | .hljs-function { 27 | color: #61aeee; 28 | } 29 | .hljs-function .hljs-params { 30 | color: #A6E22E; 31 | } 32 | .hljs-function .hljs-params .hljs-typing { 33 | color: #FD971F; 34 | } 35 | .hljs-module-access .hljs-module { 36 | color: #7e57c2; 37 | } 38 | .hljs-constructor { 39 | color: #e2b93d; 40 | } 41 | .hljs-constructor .hljs-string { 42 | color: #9CCC65; 43 | } 44 | .hljs-comment, .hljs-quote { 45 | color: #b18eb1; 46 | font-style: italic; 47 | } 48 | .hljs-doctag, .hljs-formula { 49 | color: #c678dd; 50 | } 51 | .hljs-section, .hljs-name, .hljs-selector-tag, .hljs-deletion, .hljs-subst { 52 | color: #e06c75; 53 | } 54 | .hljs-literal { 55 | color: #56b6c2; 56 | } 57 | .hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta-string { 58 | color: #98c379; 59 | } 60 | .hljs-built_in, .hljs-class .hljs-title { 61 | color: #e6c07b; 62 | } 63 | .hljs-attr, .hljs-variable, .hljs-template-variable, .hljs-type, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-number { 64 | color: #d19a66; 65 | } 66 | .hljs-symbol, .hljs-bullet, .hljs-link, .hljs-meta, .hljs-selector-id, .hljs-title { 67 | color: #61aeee; 68 | } 69 | .hljs-emphasis { 70 | font-style: italic; 71 | } 72 | .hljs-strong { 73 | font-weight: bold; 74 | } 75 | .hljs-link { 76 | text-decoration: underline; 77 | } 78 | -------------------------------------------------------------------------------- /themes/bright/static/dir.css: -------------------------------------------------------------------------------- 1 | /* copied from $GOROOT/doc/style.css */ 2 | 3 | body { 4 | margin: 0; 5 | font-family: Helvetica, Arial, sans-serif; 6 | font-size: 16px; 7 | } 8 | pre, 9 | code { 10 | font-family: Menlo, monospace; 11 | font-size: 14px; 12 | } 13 | pre { 14 | line-height: 18px; 15 | } 16 | pre .comment { 17 | color: #375EAB; 18 | } 19 | pre .highlight, 20 | pre .highlight-comment, 21 | pre .selection-highlight, 22 | pre .selection-highlight-comment { 23 | background: #FFFF00; 24 | } 25 | pre .selection, 26 | pre .selection-comment { 27 | background: #FF9632; 28 | } 29 | pre .ln { 30 | color: #999; 31 | } 32 | body { 33 | color: #222; 34 | } 35 | a, 36 | .exampleHeading .text { 37 | color: #375EAB; 38 | text-decoration: none; 39 | } 40 | a:hover, 41 | .exampleHeading .text:hover { 42 | text-decoration: underline; 43 | } 44 | p, 45 | pre, 46 | ul, 47 | ol { 48 | margin: 20px; 49 | } 50 | pre { 51 | background: #e9e9e9; 52 | padding: 10px; 53 | 54 | -webkit-border-radius: 5px; 55 | -moz-border-radius: 5px; 56 | border-radius: 5px; 57 | } 58 | 59 | h1, 60 | h2, 61 | h3, 62 | h4, 63 | .rootHeading { 64 | margin: 20px 0; 65 | padding: 0; 66 | color: #375EAB; 67 | font-weight: bold; 68 | } 69 | h1 { 70 | font-size: 24px; 71 | } 72 | h2 { 73 | font-size: 20px; 74 | background: #E0EBF5; 75 | padding: 2px 5px; 76 | } 77 | h3 { 78 | font-size: 20px; 79 | } 80 | h3, 81 | h4 { 82 | margin: 20px 5px; 83 | } 84 | h4 { 85 | font-size: 16px; 86 | } 87 | 88 | dl { 89 | margin: 20px; 90 | } 91 | dd { 92 | margin: 2px 20px; 93 | } 94 | dl, 95 | dd { 96 | font-size: 14px; 97 | } 98 | div#nav table td { 99 | vertical-align: top; 100 | } 101 | 102 | div#heading { 103 | float: left; 104 | margin: 0 0 10px 0; 105 | padding: 21px 0; 106 | font-size: 20px; 107 | font-weight: normal; 108 | } 109 | div#heading a { 110 | color: #222; 111 | text-decoration: none; 112 | } 113 | 114 | div#topbar { 115 | background: #E0EBF5; 116 | height: 64px; 117 | } 118 | 119 | body { 120 | text-align: center; 121 | } 122 | div#page, 123 | div#topbar > .container { 124 | clear: both; 125 | text-align: left; 126 | margin-left: auto; 127 | margin-right: auto; 128 | padding: 0 20px; 129 | width: 900px; 130 | } 131 | div#page.wide, 132 | div#topbar > .wide { 133 | width: auto; 134 | } 135 | div#plusone { 136 | float: right; 137 | } 138 | 139 | div#footer { 140 | color: #666; 141 | font-size: 14px; 142 | margin: 40px 0; 143 | } 144 | 145 | div#menu > a, 146 | div#menu > input { 147 | padding: 10px; 148 | 149 | text-decoration: none; 150 | font-size: 16px; 151 | 152 | -webkit-border-radius: 5px; 153 | -moz-border-radius: 5px; 154 | border-radius: 5px; 155 | } 156 | div#menu > a, 157 | div#menu > input { 158 | border: 1px solid #375EAB; 159 | } 160 | div#menu > a { 161 | color: white; 162 | background: #375EAB; 163 | } 164 | 165 | div#menu { 166 | float: right; 167 | min-width: 590px; 168 | padding: 10px 0; 169 | text-align: right; 170 | } 171 | div#menu > a { 172 | margin-right: 5px; 173 | margin-bottom: 10px; 174 | 175 | padding: 10px; 176 | } 177 | div#menu > input { 178 | position: relative; 179 | top: 1px; 180 | width: 60px; 181 | background: white; 182 | color: #222; 183 | } 184 | div#menu > input.inactive { 185 | color: #999; 186 | } 187 | -------------------------------------------------------------------------------- /themes/bright/static/dir.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // copied from $GOROOT/doc/godocs.js 6 | 7 | function bindEvent(el, e, fn) { 8 | if (el.addEventListener){ 9 | el.addEventListener(e, fn, false); 10 | } else if (el.attachEvent){ 11 | el.attachEvent('on'+e, fn); 12 | } 13 | } 14 | 15 | function godocs_bindSearchEvents() { 16 | var search = document.getElementById('search'); 17 | if (!search) { 18 | // no search box (index disabled) 19 | return; 20 | } 21 | function clearInactive() { 22 | if (search.className == "inactive") { 23 | search.value = ""; 24 | search.className = ""; 25 | } 26 | } 27 | function restoreInactive() { 28 | if (search.value !== "") { 29 | return; 30 | } 31 | if (search.type != "search") { 32 | search.value = search.getAttribute("placeholder"); 33 | } 34 | search.className = "inactive"; 35 | } 36 | restoreInactive(); 37 | bindEvent(search, 'focus', clearInactive); 38 | bindEvent(search, 'blur', restoreInactive); 39 | } 40 | 41 | bindEvent(window, 'load', godocs_bindSearchEvents); 42 | -------------------------------------------------------------------------------- /themes/bright/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/themes/bright/static/favicon.ico -------------------------------------------------------------------------------- /themes/bright/static/highlight.pack.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.15.6 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(a){var E=[],u=Object.keys,N={},g={},n=/^(no-?highlight|plain|text)$/i,R=/\blang(?:uage)?-([\w-]+)\b/i,t=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,r={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},b="",h={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function _(e){return e.replace(/&/g,"&").replace(//g,">")}function d(e){return e.nodeName.toLowerCase()}function v(e,n){var t=e&&e.exec(n);return t&&0===t.index}function p(e){return n.test(e)}function l(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function M(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:"start",offset:t,node:r}),t=e(r,t),d(r).match(/br|hr|img|input/)||a.push({event:"stop",offset:t,node:r}));return t}(e,0),a}function i(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(i)}}function m(c){function s(e){return e&&e.source||e}function o(e,n){return new RegExp(s(e),"m"+(c.cI?"i":"")+(n?"g":""))}!function n(t,e){if(!t.compiled){if(t.compiled=!0,t.k=t.k||t.bK,t.k){var r={},a=function(t,e){c.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var n=e.split("|");r[n[0]]=[t,n[1]?Number(n[1]):1]})};"string"==typeof t.k?a("keyword",t.k):u(t.k).forEach(function(e){a(e,t.k[e])}),t.k=r}t.lR=o(t.l||/\w+/,!0),e&&(t.bK&&(t.b="\\b("+t.bK.split(" ").join("|")+")\\b"),t.b||(t.b=/\B|\b/),t.bR=o(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\B|\b/),t.e&&(t.eR=o(t.e)),t.tE=s(t.e)||"",t.eW&&e.tE&&(t.tE+=(t.e?"|":"")+e.tE)),t.i&&(t.iR=o(t.i)),null==t.r&&(t.r=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return(n="self"===e?t:e).v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return l(n,{v:null},e)})),n.cached_variants||n.eW&&[l(n)]||[n];var n})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e);var i=t.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([t.tE,t.i]).map(s).filter(Boolean);t.t=i.length?o(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i')+n+(t?"":b)}function s(){g+=null!=E.sL?function(){var e="string"==typeof E.sL;if(e&&!N[E.sL])return _(R);var n=e?C(E.sL,R,!0,i[E.sL]):O(R,E.sL.length?E.sL:void 0);return 0")+'"');return R+=n,n.length||1}var f=S(e);if(!f)throw new Error('Unknown language: "'+e+'"');m(f);var a,E=t||f,i={},g="";for(a=E;a!==f;a=a.parent)a.cN&&(g=u(a.cN,"",!0)+g);var R="",d=0;try{for(var c,p,M=0;E.t.lastIndex=M,c=E.t.exec(n);)p=r(n.substring(M,c.index),c[0]),M=c.index+p;for(r(n.substr(M)),a=E;a.parent;a=a.parent)a.cN&&(g+=b);return{r:d,value:g,language:e,top:E}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:_(n)};throw e}}function O(t,e){e=e||h.languages||u(N);var r={r:0,value:_(t)},a=r;return e.filter(S).filter(s).forEach(function(e){var n=C(e,t,!1);n.language=e,n.r>a.r&&(a=n),n.r>r.r&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function B(e){return h.tabReplace||h.useBR?e.replace(t,function(e,n){return h.useBR&&"\n"===e?"
":h.tabReplace?n.replace(/\t/g,h.tabReplace):""}):e}function c(e){var n,t,r,a,i,c,o,u,s,l,f=function(e){var n,t,r,a,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=R.exec(i))return S(t[1])?t[1]:"no-highlight";for(n=0,r=(i=i.split(/\s+/)).length;n/g,"\n"):n=e,i=n.textContent,r=f?C(f,i,!0):O(i),(t=M(n)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=r.value,r.value=function(e,n,t){var r=0,a="",i=[];function c(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){a+=""}function s(e){("start"===e.event?o:u)(e.node)}for(;e.length||n.length;){var l=c();if(a+=_(t.substring(r,l[0].offset)),r=l[0].offset,l===e){for(i.reverse().forEach(u);s(l.splice(0,1)[0]),(l=c())===e&&l.length&&l[0].offset===r;);i.reverse().forEach(o)}else"start"===l[0].event?i.push(l[0].node):i.pop(),s(l.splice(0,1)[0])}return a+_(t.substr(r))}(t,M(a),i)),r.value=B(r.value),e.innerHTML=r.value,e.className=(c=e.className,o=f,u=r.language,s=o?g[o]:u,l=[c.trim()],c.match(/\bhljs\b/)||l.push("hljs"),-1===c.indexOf(s)&&l.push(s),l.join(" ").trim()),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function o(){if(!o.called){o.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,c)}}function S(e){return e=(e||"").toLowerCase(),N[e]||N[g[e]]}function s(e){var n=S(e);return n&&!n.disableAutodetect}return a.highlight=C,a.highlightAuto=O,a.fixMarkup=B,a.highlightBlock=c,a.configure=function(e){h=l(h,e)},a.initHighlighting=o,a.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",o,!1),addEventListener("load",o,!1)},a.registerLanguage=function(n,e){var t=N[n]=e(a);i(t),t.aliases&&t.aliases.forEach(function(e){g[e]=n})},a.listLanguages=function(){return u(N)},a.getLanguage=S,a.autoDetection=s,a.inherit=l,a.IR=a.IDENT_RE="[a-zA-Z]\\w*",a.UIR=a.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",a.NR=a.NUMBER_RE="\\b\\d+(\\.\\d+)?",a.CNR=a.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",a.BNR=a.BINARY_NUMBER_RE="\\b(0b[01]+)",a.RSR=a.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",a.BE=a.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},a.ASM=a.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:"comment",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C("//","$"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C("/\\*","\\*/"),a.HCM=a.HASH_COMMENT_MODE=a.C("#","$"),a.NM=a.NUMBER_MODE={cN:"number",b:a.NR,r:0},a.CNM=a.C_NUMBER_MODE={cN:"number",b:a.CNR,r:0},a.BNM=a.BINARY_NUMBER_MODE={cN:"number",b:a.BNR,r:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:"number",b:a.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},a.RM=a.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[a.BE,{b:/\[/,e:/\]/,r:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:"title",b:a.IR,r:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:"title",b:a.UIR,r:0},a.METHOD_GUARD={b:"\\.\\s*"+a.UIR,r:0},a});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U|L)?"',e:'"',i:"\\n",c:[t.BE]},{b:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\((?:.|\n)*?\)\1"/},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e,{b:/\(/,e:/\)/,k:c,r:0,c:["self",t.CLCM,t.CBCM,r,s,e]}]},t.CLCM,t.CBCM,i]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b://,c:["self"]},t.TM]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,{cN:"string",b:/'/,e:/'/},t]}});hljs.registerLanguage("go",function(e){var t={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:t,i:""); 47 | 48 | w.document.title = window.document.title; 49 | 50 | var slides = w.document.createElement('iframe'); 51 | slides.id = 'presenter-slides'; 52 | slides.src = slidesUrl; 53 | w.document.body.appendChild(slides); 54 | // setTimeout needed for Firefox 55 | setTimeout(function() { 56 | slides.focus(); 57 | }, 100); 58 | 59 | var notes = w.document.createElement('div'); 60 | notes.id = 'presenter-notes'; 61 | notes.innerHTML = formattedNotes; 62 | w.document.body.appendChild(notes); 63 | 64 | w.document.close(); 65 | 66 | function addPresenterNotesStyle() { 67 | var el = w.document.createElement('link'); 68 | el.rel = 'stylesheet'; 69 | el.type = 'text/css'; 70 | el.href = PERMANENT_URL_PREFIX + 'notes.css'; 71 | w.document.body.appendChild(el); 72 | w.document.querySelector('head').appendChild(el); 73 | } 74 | 75 | addPresenterNotesStyle(); 76 | 77 | // Add listener on notesWindow to update notes when triggered from 78 | // parent window 79 | w.addEventListener('storage', updateNotes, false); 80 | }; 81 | 82 | function formatNotes(notes) { 83 | var formattedNotes = ''; 84 | if (notes) { 85 | for (var i = 0; i < notes.length; i++) { 86 | formattedNotes = formattedNotes + '

' + notes[i] + '

'; 87 | } 88 | } 89 | return formattedNotes; 90 | }; 91 | 92 | function updateNotes() { 93 | // When triggered from parent window, notesWindow is null 94 | // The storage event listener on notesWindow will update notes 95 | if (!notesWindow) return; 96 | var destSlide = parseInt(localStorage.getItem('destSlide'), 10); 97 | var section = sections[destSlide - 1]; 98 | var el = notesWindow.document.getElementById('presenter-notes'); 99 | 100 | if (!el) return; 101 | 102 | if (section && section.Notes) { 103 | el.innerHTML = formatNotes(section.Notes); 104 | } else if (destSlide == 0) { 105 | el.innerHTML = formatNotes(titleNotes); 106 | } else { 107 | el.innerHTML = ''; 108 | } 109 | }; 110 | 111 | /* Playground syncing */ 112 | 113 | // When presenter notes are enabled, playground click handlers are 114 | // stored here to sync click events on the correct playground 115 | var playgroundHandlers = {onRun: [], onKill: [], onClose: []}; 116 | 117 | function updatePlay(e) { 118 | var i = localStorage.getItem('play-index'); 119 | 120 | switch (e.key) { 121 | case 'play-index': 122 | return; 123 | case 'play-action': 124 | // Sync 'run', 'kill', 'close' actions 125 | var action = localStorage.getItem('play-action'); 126 | playgroundHandlers[action][i](e); 127 | return; 128 | case 'play-code': 129 | // Sync code editing 130 | var play = document.querySelectorAll('div.playground')[i]; 131 | play.innerHTML = localStorage.getItem('play-code'); 132 | return; 133 | case 'output-style': 134 | // Sync resizing of playground output 135 | var out = document.querySelectorAll('.output')[i]; 136 | out.style = localStorage.getItem('output-style'); 137 | return; 138 | } 139 | }; 140 | 141 | // Reset 'run', 'kill', 'close' storage items when synced 142 | // so that successive actions can be synced correctly 143 | function updatePlayStorage(action, index, e) { 144 | localStorage.setItem('play-index', index); 145 | 146 | if (localStorage.getItem('play-action') === action) { 147 | // We're the receiving window, and the message has been received 148 | localStorage.removeItem('play-action'); 149 | } else { 150 | // We're the triggering window, send the message 151 | localStorage.setItem('play-action', action); 152 | } 153 | 154 | if (action === 'onRun') { 155 | if (localStorage.getItem('play-shiftKey') === 'true') { 156 | localStorage.removeItem('play-shiftKey'); 157 | } else if (e.shiftKey) { 158 | localStorage.setItem('play-shiftKey', e.shiftKey); 159 | } 160 | } 161 | }; 162 | -------------------------------------------------------------------------------- /themes/bright/static/obsidian.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Obsidian style 3 | * ported by Alexander Marenin (http://github.com/ioncreature) 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | padding: 0.5em; 10 | background: #282b2e; 11 | } 12 | 13 | .hljs-keyword, 14 | .hljs-selector-tag, 15 | .hljs-literal, 16 | .hljs-selector-id { 17 | color: #93c763; 18 | } 19 | 20 | .hljs-number { 21 | color: #ffcd22; 22 | } 23 | 24 | .hljs { 25 | color: #e0e2e4; 26 | } 27 | 28 | .hljs-attribute { 29 | color: #668bb0; 30 | } 31 | 32 | .hljs-code, 33 | .hljs-class .hljs-title, 34 | .hljs-section { 35 | color: white; 36 | } 37 | 38 | .hljs-regexp, 39 | .hljs-link { 40 | color: #d39745; 41 | } 42 | 43 | .hljs-meta { 44 | color: #557182; 45 | } 46 | 47 | .hljs-tag, 48 | .hljs-name, 49 | .hljs-bullet, 50 | .hljs-subst, 51 | .hljs-emphasis, 52 | .hljs-type, 53 | .hljs-built_in, 54 | .hljs-selector-attr, 55 | .hljs-selector-pseudo, 56 | .hljs-addition, 57 | .hljs-variable, 58 | .hljs-template-tag, 59 | .hljs-template-variable { 60 | color: #8cbbad; 61 | } 62 | 63 | .hljs-string, 64 | .hljs-symbol { 65 | color: #ec7600; 66 | } 67 | 68 | .hljs-comment, 69 | .hljs-quote, 70 | .hljs-deletion { 71 | color: #818e96; 72 | } 73 | 74 | .hljs-selector-class { 75 | color: #A082BD 76 | } 77 | 78 | .hljs-keyword, 79 | .hljs-selector-tag, 80 | .hljs-literal, 81 | .hljs-doctag, 82 | .hljs-title, 83 | .hljs-section, 84 | .hljs-type, 85 | .hljs-name, 86 | .hljs-strong { 87 | font-weight: bold; 88 | } 89 | -------------------------------------------------------------------------------- /themes/bright/static/play.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@0.16.2/min/vs' }}); 5 | // window.MonacoEnvironment = { getWorkerUrl: () => proxy }; 6 | 7 | // let proxy = URL.createObjectURL(new Blob([` 8 | // self.MonacoEnvironment = { 9 | // baseUrl: 'https://unpkg.com/monaco-editor@0.16.2/min/' 10 | // }; 11 | // importScripts('https://unpkg.com/monaco-editor@0.16.2/min/vs/base/worker/workerMain.js'); 12 | // `], { type: 'text/javascript' })); 13 | 14 | require(["vs/editor/editor.main"], function () { 15 | initPlayground(SocketTransport()); 16 | }); 17 | 18 | window.editors = [] 19 | 20 | function initPlayground(transport) { 21 | 'use strict'; 22 | 23 | function text(node) { 24 | var s = ''; 25 | for (var i = 0; i < node.childNodes.length; i++) { 26 | var n = node.childNodes[i]; 27 | if (n.nodeType === 1) { 28 | if (n.tagName === 'BUTTON') continue 29 | if (n.tagName === 'SPAN' && n.className === 'number') continue; 30 | if (n.tagName === 'DIV' || n.tagName == 'BR') { 31 | s += "\n"; 32 | } 33 | s += text(n); 34 | continue; 35 | } 36 | if (n.nodeType === 3) { 37 | s += n.nodeValue; 38 | } 39 | } 40 | return s.replace('\xA0', ' '); // replace non-breaking spaces 41 | } 42 | 43 | // When presenter notes are enabled, the index passed 44 | // here will identify the playground to be synced 45 | function init(code, index) { 46 | var output = document.createElement('div'); 47 | var outpre = document.createElement('pre'); 48 | var running; 49 | var raw = code.dataset.raw 50 | var editor = monaco.editor.create(code, { 51 | value: raw, 52 | language: 'go', 53 | theme: 'vs', 54 | // theme: 'vs-dark', 55 | // theme: 'hc-black', 56 | fontSize: 18 57 | }); 58 | window.editors.push(editor) 59 | if ($ && $(output).resizable) { 60 | $(output).resizable({ 61 | handles: 'n,w,nw', 62 | minHeight: 27, 63 | minWidth: 135, 64 | maxHeight: 608, 65 | maxWidth: 990 66 | }); 67 | } 68 | 69 | function onKill() { 70 | if (running) running.Kill(); 71 | if (window.notesEnabled) updatePlayStorage('onKill', index); 72 | } 73 | 74 | function onRun(e) { 75 | var raw = editor.getValue() 76 | var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true'; 77 | if (running) running.Kill(); 78 | output.style.display = 'block'; 79 | outpre.innerHTML = ''; 80 | run1.style.display = 'none'; 81 | var options = {Race: sk}; 82 | running = transport.Run(raw, PlaygroundOutput(outpre), options); 83 | // running = transport.Run(text(code), PlaygroundOutput(outpre), options); 84 | if (window.notesEnabled) updatePlayStorage('onRun', index, e); 85 | } 86 | 87 | function onClose() { 88 | if (running) running.Kill(); 89 | output.style.display = 'none'; 90 | run1.style.display = 'inline-block'; 91 | if (window.notesEnabled) updatePlayStorage('onClose', index); 92 | } 93 | 94 | if (window.notesEnabled) { 95 | playgroundHandlers.onRun.push(onRun); 96 | playgroundHandlers.onClose.push(onClose); 97 | playgroundHandlers.onKill.push(onKill); 98 | } 99 | var run1 = document.createElement('button'); 100 | run1.innerHTML = 'Run'; 101 | run1.className = 'run'; 102 | run1.addEventListener("click", onRun, false); 103 | var run2 = document.createElement('button'); 104 | run2.className = 'run'; 105 | run2.innerHTML = 'Run'; 106 | run2.addEventListener("click", onRun, false); 107 | var kill = document.createElement('button'); 108 | kill.className = 'kill'; 109 | kill.innerHTML = 'Kill'; 110 | kill.addEventListener("click", onKill, false); 111 | var close = document.createElement('button'); 112 | close.className = 'close'; 113 | close.innerHTML = 'Close'; 114 | close.addEventListener("click", onClose, false); 115 | 116 | var button = document.createElement('div'); 117 | button.classList.add('buttons'); 118 | button.appendChild(run1); 119 | // Hack to simulate insertAfter 120 | code.parentNode.insertBefore(button, code.nextSibling); 121 | 122 | var buttons = document.createElement('div'); 123 | buttons.classList.add('buttons'); 124 | buttons.appendChild(run2); 125 | buttons.appendChild(kill); 126 | buttons.appendChild(close); 127 | 128 | output.classList.add('output'); 129 | output.appendChild(buttons); 130 | output.appendChild(outpre); 131 | output.style.display = 'none'; 132 | code.parentNode.insertBefore(output, button.nextSibling); 133 | } 134 | 135 | // var play = document.querySelectorAll('div.playground'); 136 | var monacos = document.querySelectorAll(` 137 | .slides > article.past > div.my-editor, 138 | .slides > article.next > div.my-editor, 139 | .slides > article.current > div.my-editor` 140 | ) 141 | for (var i = 0; i < monacos.length; i++) { 142 | if(!monacos[i].dataset.init) 143 | init(monacos[i], i); 144 | monacos[i].dataset.init = true 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /themes/bright/static/playground.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | In the absence of any formal way to specify interfaces in JavaScript, 7 | here's a skeleton implementation of a playground transport. 8 | 9 | function Transport() { 10 | // Set up any transport state (eg, make a websocket connection). 11 | return { 12 | Run: function(body, output, options) { 13 | // Compile and run the program 'body' with 'options'. 14 | // Call the 'output' callback to display program output. 15 | return { 16 | Kill: function() { 17 | // Kill the running program. 18 | } 19 | }; 20 | } 21 | }; 22 | } 23 | 24 | // The output callback is called multiple times, and each time it is 25 | // passed an object of this form. 26 | var write = { 27 | Kind: 'string', // 'start', 'stdout', 'stderr', 'end' 28 | Body: 'string' // content of write or end status message 29 | } 30 | 31 | // The first call must be of Kind 'start' with no body. 32 | // Subsequent calls may be of Kind 'stdout' or 'stderr' 33 | // and must have a non-null Body string. 34 | // The final call should be of Kind 'end' with an optional 35 | // Body string, signifying a failure ("killed", for example). 36 | 37 | // The output callback must be of this form. 38 | // See PlaygroundOutput (below) for an implementation. 39 | function outputCallback(write) { 40 | } 41 | */ 42 | 43 | // HTTPTransport is the default transport. 44 | // enableVet enables running vet if a program was compiled and ran successfully. 45 | // If vet returned any errors, display them before the output of a program. 46 | function HTTPTransport(enableVet) { 47 | 'use strict'; 48 | 49 | function playback(output, data) { 50 | // Backwards compatibility: default values do not affect the output. 51 | var events = data.Events || []; 52 | var errors = data.Errors || ""; 53 | var status = data.Status || 0; 54 | var isTest = data.IsTest || false; 55 | var testsFailed = data.TestsFailed || 0; 56 | 57 | var timeout; 58 | output({Kind: 'start'}); 59 | function next() { 60 | if (!events || events.length === 0) { 61 | if (isTest) { 62 | if (testsFailed > 0) { 63 | output({Kind: 'system', Body: '\n'+testsFailed+' test'+(testsFailed>1?'s':'')+' failed.'}); 64 | } else { 65 | output({Kind: 'system', Body: '\nAll tests passed.'}); 66 | } 67 | } else { 68 | if (status > 0) { 69 | output({Kind: 'end', Body: 'status ' + status + '.'}); 70 | } else { 71 | if (errors !== "") { 72 | // errors are displayed only in the case of timeout. 73 | output({Kind: 'end', Body: errors + '.'}); 74 | } else { 75 | output({Kind: 'end'}); 76 | } 77 | } 78 | } 79 | return; 80 | } 81 | var e = events.shift(); 82 | if (e.Delay === 0) { 83 | output({Kind: e.Kind, Body: e.Message}); 84 | next(); 85 | return; 86 | } 87 | timeout = setTimeout(function() { 88 | output({Kind: e.Kind, Body: e.Message}); 89 | next(); 90 | }, e.Delay / 1000000); 91 | } 92 | next(); 93 | return { 94 | Stop: function() { 95 | clearTimeout(timeout); 96 | } 97 | }; 98 | } 99 | 100 | function error(output, msg) { 101 | output({Kind: 'start'}); 102 | output({Kind: 'stderr', Body: msg}); 103 | output({Kind: 'end'}); 104 | } 105 | 106 | function buildFailed(output, msg) { 107 | output({Kind: 'start'}); 108 | output({Kind: 'stderr', Body: msg}); 109 | output({Kind: 'system', Body: '\nGo build failed.'}); 110 | } 111 | 112 | var seq = 0; 113 | return { 114 | Run: function(body, output, options) { 115 | seq++; 116 | var cur = seq; 117 | var playing; 118 | $.ajax('/compile', { 119 | type: 'POST', 120 | data: {'version': 2, 'body': body}, 121 | dataType: 'json', 122 | success: function(data) { 123 | if (seq != cur) return; 124 | if (!data) return; 125 | if (playing != null) playing.Stop(); 126 | if (data.Errors) { 127 | if (data.Errors === 'process took too long') { 128 | // Playback the output that was captured before the timeout. 129 | playing = playback(output, data); 130 | } else { 131 | buildFailed(output, data.Errors); 132 | } 133 | return; 134 | } 135 | 136 | if (!enableVet) { 137 | playing = playback(output, data); 138 | return; 139 | } 140 | 141 | $.ajax("/vet", { 142 | data: {"body": body}, 143 | type: "POST", 144 | dataType: "json", 145 | success: function(dataVet) { 146 | if (dataVet.Errors) { 147 | if (!data.Events) { 148 | data.Events = []; 149 | } 150 | // inject errors from the vet as the first events in the output 151 | data.Events.unshift({Message: 'Go vet exited.\n\n', Kind: 'system', Delay: 0}); 152 | data.Events.unshift({Message: dataVet.Errors, Kind: 'stderr', Delay: 0}); 153 | } 154 | playing = playback(output, data); 155 | }, 156 | error: function() { 157 | playing = playback(output, data); 158 | } 159 | }); 160 | }, 161 | error: function() { 162 | error(output, 'Error communicating with remote server.'); 163 | } 164 | }); 165 | return { 166 | Kill: function() { 167 | if (playing != null) playing.Stop(); 168 | output({Kind: 'end', Body: 'killed'}); 169 | } 170 | }; 171 | } 172 | }; 173 | } 174 | 175 | function SocketTransport() { 176 | 'use strict'; 177 | 178 | var id = 0; 179 | var outputs = {}; 180 | var started = {}; 181 | var websocket; 182 | var websocketDisabled = false; 183 | if (window.location.protocol == "http:") { 184 | websocket = new WebSocket('ws://' + window.location.host + '/socket'); 185 | } else if (window.location.protocol == "https:") { 186 | websocket = new WebSocket('wss://' + window.location.host + '/socket'); 187 | } else { 188 | websocketDisabled = true 189 | console.log("Static page mode:") 190 | console.log("No backend service provided.") 191 | console.log("Live demo and websocket are closed.") 192 | } 193 | 194 | if(!websocketDisabled) { 195 | websocket.onclose = function() { 196 | console.log('websocket connection closed'); 197 | }; 198 | 199 | websocket.onmessage = function(e) { 200 | var m = JSON.parse(e.data); 201 | var output = outputs[m.Id]; 202 | if (output === null) 203 | return; 204 | if (!started[m.Id]) { 205 | output({Kind: 'start'}); 206 | started[m.Id] = true; 207 | } 208 | output({Kind: m.Kind, Body: m.Body}); 209 | }; 210 | } 211 | 212 | 213 | function send(m) { 214 | if(!websocketDisabled) 215 | websocket.send(JSON.stringify(m)); 216 | } 217 | 218 | return { 219 | Run: function(body, output, options) { 220 | var thisID = id+''; 221 | id++; 222 | outputs[thisID] = output; 223 | send({Id: thisID, Kind: 'run', Body: body, Options: options}); 224 | return { 225 | Kill: function() { 226 | send({Id: thisID, Kind: 'kill'}); 227 | } 228 | }; 229 | } 230 | }; 231 | } 232 | 233 | function PlaygroundOutput(el) { 234 | 'use strict'; 235 | 236 | return function(write) { 237 | if (write.Kind == 'start') { 238 | el.innerHTML = ''; 239 | return; 240 | } 241 | 242 | var cl = 'system'; 243 | if (write.Kind == 'stdout' || write.Kind == 'stderr') 244 | cl = write.Kind; 245 | 246 | var m = write.Body; 247 | if (write.Kind == 'end') { 248 | m = '\nProgram exited' + (m?(': '+m):'.'); 249 | } 250 | 251 | if (m.indexOf('IMAGE:') === 0) { 252 | // TODO(adg): buffer all writes before creating image 253 | var url = 'data:image/png;base64,' + m.substr(6); 254 | var img = document.createElement('img'); 255 | img.src = url; 256 | el.appendChild(img); 257 | return; 258 | } 259 | 260 | // ^L clears the screen. 261 | var s = m.split('\x0c'); 262 | if (s.length > 1) { 263 | el.innerHTML = ''; 264 | m = s.pop(); 265 | } 266 | 267 | m = m.replace(/&/g, '&'); 268 | m = m.replace(//g, '>'); 270 | 271 | var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight; 272 | 273 | var span = document.createElement('span'); 274 | span.className = cl; 275 | span.innerHTML = m; 276 | el.appendChild(span); 277 | 278 | if (needScroll) 279 | el.scrollTop = el.scrollHeight - el.offsetHeight; 280 | }; 281 | } 282 | 283 | (function() { 284 | function lineHighlight(error) { 285 | var regex = /prog.go:([0-9]+)/g; 286 | var r = regex.exec(error); 287 | while (r) { 288 | $(".lines div").eq(r[1]-1).addClass("lineerror"); 289 | r = regex.exec(error); 290 | } 291 | } 292 | function highlightOutput(wrappedOutput) { 293 | return function(write) { 294 | if (write.Body) lineHighlight(write.Body); 295 | wrappedOutput(write); 296 | }; 297 | } 298 | function lineClear() { 299 | $(".lineerror").removeClass("lineerror"); 300 | } 301 | 302 | // opts is an object with these keys 303 | // codeEl - code editor element 304 | // outputEl - program output element 305 | // runEl - run button element 306 | // fmtEl - fmt button element (optional) 307 | // fmtImportEl - fmt "imports" checkbox element (optional) 308 | // shareEl - share button element (optional) 309 | // shareURLEl - share URL text input element (optional) 310 | // shareRedirect - base URL to redirect to on share (optional) 311 | // toysEl - toys select element (optional) 312 | // enableHistory - enable using HTML5 history API (optional) 313 | // transport - playground transport to use (default is HTTPTransport) 314 | // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) 315 | // enableVet - enable running vet and displaying its errors 316 | function playground(opts) { 317 | var code = $(opts.codeEl); 318 | var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); 319 | var running; 320 | 321 | // autoindent helpers. 322 | function insertTabs(n) { 323 | // find the selection start and end 324 | var start = code[0].selectionStart; 325 | var end = code[0].selectionEnd; 326 | // split the textarea content into two, and insert n tabs 327 | var v = code[0].value; 328 | var u = v.substr(0, start); 329 | for (var i=0; i 0) { 343 | curpos--; 344 | if (el.value[curpos] == "\t") { 345 | tabs++; 346 | } else if (tabs > 0 || el.value[curpos] == "\n") { 347 | break; 348 | } 349 | } 350 | setTimeout(function() { 351 | insertTabs(tabs); 352 | }, 1); 353 | } 354 | 355 | // NOTE(cbro): e is a jQuery event, not a DOM event. 356 | function handleSaveShortcut(e) { 357 | if (e.isDefaultPrevented()) return false; 358 | if (!e.metaKey && !e.ctrlKey) return false; 359 | if (e.key != "S" && e.key != "s") return false; 360 | 361 | e.preventDefault(); 362 | 363 | // Share and save 364 | share(function(url) { 365 | window.location.href = url + ".go?download=true"; 366 | }); 367 | 368 | return true; 369 | } 370 | 371 | function keyHandler(e) { 372 | if (opts.enableShortcuts && handleSaveShortcut(e)) return; 373 | 374 | if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab) 375 | insertTabs(1); 376 | e.preventDefault(); 377 | return false; 378 | } 379 | if (e.keyCode == 13) { // enter 380 | if (e.shiftKey) { // +shift 381 | run(); 382 | e.preventDefault(); 383 | return false; 384 | } if (e.ctrlKey) { // +control 385 | fmt(); 386 | e.preventDefault(); 387 | } else { 388 | autoindent(e.target); 389 | } 390 | } 391 | return true; 392 | } 393 | code.unbind('keydown').bind('keydown', keyHandler); 394 | var outdiv = $(opts.outputEl).empty(); 395 | var output = $('
').appendTo(outdiv);
396 | 
397 |     function body() {
398 |       return $(opts.codeEl).val();
399 |     }
400 |     function setBody(text) {
401 |       $(opts.codeEl).val(text);
402 |     }
403 |     function origin(href) {
404 |       return (""+href).split("/").slice(0, 3).join("/");
405 |     }
406 | 
407 |     var pushedEmpty = (window.location.pathname == "/");
408 |     function inputChanged() {
409 |       if (pushedEmpty) {
410 |         return;
411 |       }
412 |       pushedEmpty = true;
413 |       $(opts.shareURLEl).hide();
414 |       window.history.pushState(null, "", "/");
415 |     }
416 |     function popState(e) {
417 |       if (e === null) {
418 |         return;
419 |       }
420 |       if (e && e.state && e.state.code) {
421 |         setBody(e.state.code);
422 |       }
423 |     }
424 |     var rewriteHistory = false;
425 |     if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
426 |       rewriteHistory = true;
427 |       code[0].addEventListener('input', inputChanged);
428 |       window.addEventListener('popstate', popState);
429 |     }
430 | 
431 |     function setError(error) {
432 |       if (running) running.Kill();
433 |       lineClear();
434 |       lineHighlight(error);
435 |       output.empty().addClass("error").text(error);
436 |     }
437 |     function loading() {
438 |       lineClear();
439 |       if (running) running.Kill();
440 |       output.removeClass("error").text('Waiting for remote server...');
441 |     }
442 |     function run() {
443 |       loading();
444 |       running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
445 |     }
446 | 
447 |     function fmt() {
448 |       loading();
449 |       var data = {"body": body()};
450 |       if ($(opts.fmtImportEl).is(":checked")) {
451 |         data["imports"] = "true";
452 |       }
453 |       $.ajax("/fmt", {
454 |         data: data,
455 |         type: "POST",
456 |         dataType: "json",
457 |         success: function(data) {
458 |           if (data.Error) {
459 |             setError(data.Error);
460 |           } else {
461 |             setBody(data.Body);
462 |             setError("");
463 |           }
464 |         }
465 |       });
466 |     }
467 | 
468 |     var shareURL; // jQuery element to show the shared URL.
469 |     var sharing = false; // true if there is a pending request.
470 |     var shareCallbacks = [];
471 |     function share(opt_callback) {
472 |       if (opt_callback) shareCallbacks.push(opt_callback);
473 | 
474 |       if (sharing) return;
475 |       sharing = true;
476 | 
477 |       var sharingData = body();
478 |       $.ajax("/share", {
479 |         processData: false,
480 |         data: sharingData,
481 |         type: "POST",
482 |         contentType: "text/plain; charset=utf-8",
483 |         complete: function(xhr) {
484 |           sharing = false;
485 |           if (xhr.status != 200) {
486 |             alert("Server error; try again.");
487 |             return;
488 |           }
489 |           if (opts.shareRedirect) {
490 |             window.location = opts.shareRedirect + xhr.responseText;
491 |           }
492 |           var path = "/p/" + xhr.responseText;
493 |           var url = origin(window.location) + path;
494 | 
495 |           for (var i = 0; i < shareCallbacks.length; i++) {
496 |             shareCallbacks[i](url);
497 |           }
498 |           shareCallbacks = [];
499 | 
500 |           if (shareURL) {
501 |             shareURL.show().val(url).focus().select();
502 | 
503 |             if (rewriteHistory) {
504 |               var historyData = {"code": sharingData};
505 |               window.history.pushState(historyData, "", path);
506 |               pushedEmpty = false;
507 |             }
508 |           }
509 |         }
510 |       });
511 |     }
512 | 
513 |     $(opts.runEl).click(run);
514 |     $(opts.fmtEl).click(fmt);
515 | 
516 |     if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
517 |       if (opts.shareURLEl) {
518 |         shareURL = $(opts.shareURLEl).hide();
519 |       }
520 |       $(opts.shareEl).click(function() {
521 |         share();
522 |       });
523 |     }
524 | 
525 |     if (opts.toysEl !== null) {
526 |       $(opts.toysEl).bind('change', function() {
527 |         var toy = $(this).val();
528 |         $.ajax("/doc/play/"+toy, {
529 |           processData: false,
530 |           type: "GET",
531 |           complete: function(xhr) {
532 |             if (xhr.status != 200) {
533 |               alert("Server error; try again.");
534 |               return;
535 |             }
536 |             setBody(xhr.responseText);
537 |           }
538 |         });
539 |       });
540 |     }
541 |   }
542 | 
543 |   window.playground = playground;
544 | })();
545 | 


--------------------------------------------------------------------------------
/themes/bright/static/styles.css:
--------------------------------------------------------------------------------
  1 | :root {
  2 |   --background-color: #1e1e1e;
  3 |   --article-bg-color: rgb(255, 255, 255);
  4 |   --font-color: #1e1e1e;
  5 |   --article-title-padding: 20px 0px 30px 20px;
  6 |   --codeblocks-height: 75%;
  7 |   --kktix-green: #64c025;
  8 |   --kktix-darkgreen: #436929;
  9 |   --border-first-color: var(--kktix-green);
 10 |   --border-second-color: var(--kktix-darkgreen);
 11 |   --footer-first-color: #333;
 12 |   --footer-second-color: #333;
 13 |   --border-top-width: 8px;
 14 |   --border-bottom-width: 8px;
 15 |   --footer-border-height: var(--border-bottom-width);
 16 |   --border-top-image: linear-gradient(to right, 
 17 |   var(--border-first-color) 33%, 
 18 |   var(--border-second-color) 33%, 
 19 |   var(--border-second-color) 66%, 
 20 |   var(--border-first-color) 66%, 
 21 |   var(--border-first-color) 100%) 8 0 0 0;
 22 |   --footer-border-color: linear-gradient(to right, 
 23 |   var(--footer-first-color) 33%, 
 24 |   var(--footer-second-color) 33%, 
 25 |   var(--footer-second-color) 66%, 
 26 |   var(--footer-first-color) 66%, 
 27 |   var(--footer-first-color) 100%);
 28 |   --letter-spacing: 2px;
 29 |   --slogan-font-size: 45px;
 30 | }
 31 | 
 32 | @media screen {
 33 |   /* Framework */
 34 |   html {
 35 |     height: 100%;
 36 |   }
 37 | 
 38 |   body {
 39 |     margin: 0;
 40 |     padding: 0;
 41 | 
 42 |     display: block !important;
 43 |     height: 100%;
 44 |     height: 100vh;
 45 | 
 46 |     overflow: hidden;
 47 |     /* background: white; */
 48 |     background: var(--background-color); 
 49 |     /* background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
 50 |     background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
 51 |     background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
 52 |     background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190))); */
 53 | 
 54 |     -webkit-font-smoothing: antialiased;
 55 |   }
 56 | 
 57 |   /* 這行必需要加,不然 editor 會出不來 */
 58 |   .my-editor {
 59 |     /* position: absolute; */
 60 |     /* display: block !important; */
 61 |     left: 0;
 62 |     top: 0;
 63 |     width: 100%;
 64 |     height: var(--codeblocks-height);
 65 |     margin: 0;
 66 |     padding: 0;
 67 |     /* overflow: hidden; */
 68 |   }
 69 |   .article-footer {
 70 |     width: 100%;
 71 |     height: var(--footer-border-height);
 72 |     background-image: var(--footer-border-color);
 73 |     position: absolute;
 74 |     bottom: 0;
 75 |     left: 0;
 76 |     right: 0;
 77 |   }
 78 |   .slides {
 79 |     width: 100%;
 80 |     height: 100%;
 81 |     left: 0;
 82 |     top: 0;
 83 | 
 84 |     position: absolute;
 85 | 
 86 |     -webkit-transform: translate3d(0, 0, 0);
 87 |   }
 88 | 
 89 |   .slides > article {
 90 |     display: block;
 91 | 
 92 |     position: absolute;
 93 |     overflow: hidden;
 94 | 
 95 |     width: 900px;
 96 |     height: 700px;
 97 | 
 98 |     left: 50%;
 99 |     top: 50%;
100 | 
101 |     margin-left: -450px;
102 |     margin-top: -350px;
103 | 
104 |     padding: 40px 60px var(--footer-border-height);
105 | 
106 |     box-sizing: border-box;
107 |     -o-box-sizing: border-box;
108 |     -moz-box-sizing: border-box;
109 |     -webkit-box-sizing: border-box;
110 | 
111 |     border-top: var(--border-top-width) solid;
112 |     border-image: var(--border-top-image);
113 |     
114 |     background-color: var(--article-bg-color);
115 | 
116 |     /* border: 1px solid rgba(0, 0, 0, .3); */
117 | 
118 |     /* transition: transform .3s ease-out;
119 |     -o-transition: -o-transform .3s ease-out;
120 |     -moz-transition: -moz-transform .3s ease-out;
121 |     -webkit-transition: -webkit-transform .3s ease-out; */
122 |   }
123 |   .slides.layout-widescreen > article {
124 |     margin-left: -550px;
125 |     width: 1100px;
126 |   }
127 |   .slides.layout-faux-widescreen > article {
128 |     margin-left: -550px;
129 |     width: 1100px;
130 | 
131 |     padding: 40px 160px;
132 |   }
133 | 
134 |   .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
135 |   .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
136 |     background-position-x: 0, 840px;
137 |   }
138 | 
139 |   /* Clickable/tappable areas */
140 | 
141 |   .slide-area {
142 |     z-index: 1000;
143 | 
144 |     position: absolute;
145 |     left: 0;
146 |     top: 0;
147 |     width: 150px;
148 |     height: 700px;
149 | 
150 |     left: 50%;
151 |     top: 50%;
152 | 
153 |     cursor: pointer;
154 |     margin-top: -350px;
155 | 
156 |     tap-highlight-color: transparent;
157 |     -o-tap-highlight-color: transparent;
158 |     -moz-tap-highlight-color: transparent;
159 |     -webkit-tap-highlight-color: transparent;
160 |   }
161 |   #prev-slide-area {
162 |     margin-left: -550px;
163 |   }
164 |   #next-slide-area {
165 |     margin-left: 400px;
166 |   }
167 |   .slides.layout-widescreen #prev-slide-area,
168 |   .slides.layout-faux-widescreen #prev-slide-area {
169 |     margin-left: -650px;
170 |   }
171 |   .slides.layout-widescreen #next-slide-area,
172 |   .slides.layout-faux-widescreen #next-slide-area {
173 |     margin-left: 500px;
174 |   }
175 | 
176 |   /* Slides */
177 | 
178 |   .slides > article {
179 |     display: none;
180 |   }
181 |   /* .slides > article.slide-hide {
182 |     display: none;
183 |   } */
184 |   .slides > article.far-past {
185 |     display: block;
186 |     transform: translate(-2040px);
187 |     -o-transform: translate(-2040px);
188 |     -moz-transform: translate(-2040px);
189 |     -webkit-transform: translate3d(-2040px, 0, 0);
190 |   }
191 |   .slides > article.past {
192 |     display: block;
193 |     transform: translate(-1020px);
194 |     -o-transform: translate(-1020px);
195 |     -moz-transform: translate(-1020px);
196 |     -webkit-transform: translate3d(-1020px, 0, 0);
197 |   }
198 |   .slides > article.current {
199 |     display: block;
200 |     transform: translate(0);
201 |     -o-transform: translate(0);
202 |     -moz-transform: translate(0);
203 |     -webkit-transform: translate3d(0, 0, 0);
204 |   }
205 |   .slides > article.next {
206 |     display: block;
207 |     transform: translate(1020px);
208 |     -o-transform: translate(1020px);
209 |     -moz-transform: translate(1020px);
210 |     -webkit-transform: translate3d(1020px, 0, 0);
211 |   }
212 |   .slides > article.far-next {
213 |     display: block;
214 |     transform: translate(2040px);
215 |     -o-transform: translate(2040px);
216 |     -moz-transform: translate(2040px);
217 |     -webkit-transform: translate3d(2040px, 0, 0);
218 |   }
219 | 
220 |   .slides.layout-widescreen > article.far-past,
221 |   .slides.layout-faux-widescreen > article.far-past {
222 |     display: block;
223 |     transform: translate(-2260px);
224 |     -o-transform: translate(-2260px);
225 |     -moz-transform: translate(-2260px);
226 |     -webkit-transform: translate3d(-2260px, 0, 0);
227 |   }
228 |   .slides.layout-widescreen > article.past,
229 |   .slides.layout-faux-widescreen > article.past {
230 |     display: block;
231 |     transform: translate(-1130px);
232 |     -o-transform: translate(-1130px);
233 |     -moz-transform: translate(-1130px);
234 |     -webkit-transform: translate3d(-1130px, 0, 0);
235 |   }
236 |   .slides.layout-widescreen > article.current,
237 |   .slides.layout-faux-widescreen > article.current {
238 |     display: block;
239 |     transform: translate(0);
240 |     -o-transform: translate(0);
241 |     -moz-transform: translate(0);
242 |     -webkit-transform: translate3d(0, 0, 0);
243 |   }
244 |   .slides.layout-widescreen > article.next,
245 |   .slides.layout-faux-widescreen > article.next {
246 |     display: block;
247 |     transform: translate(1130px);
248 |     -o-transform: translate(1130px);
249 |     -moz-transform: translate(1130px);
250 |     -webkit-transform: translate3d(1130px, 0, 0);
251 |   }
252 |   .slides.layout-widescreen > article.far-next,
253 |   .slides.layout-faux-widescreen > article.far-next {
254 |     display: block;
255 |     transform: translate(2260px);
256 |     -o-transform: translate(2260px);
257 |     -moz-transform: translate(2260px);
258 |     -webkit-transform: translate3d(2260px, 0, 0);
259 |   }
260 | }
261 | 
262 | @media print {
263 |   /* Set page layout */
264 |   @page {
265 |     size: A4 landscape;
266 |   }
267 | 
268 |   body {
269 |     display: block !important;
270 |   }
271 | 
272 |   .slides > article {
273 |     display: block;
274 | 
275 |     position: relative;
276 | 
277 |     page-break-inside: never;
278 |     page-break-after: always;
279 | 
280 |     overflow: hidden;
281 |   }
282 | 
283 |   /* div.code {
284 |     background: rgb(240, 240, 240);
285 |   } */
286 | 
287 |   /* Add explicit links */
288 |   a:link:after, a:visited:after {
289 |    content: " (" attr(href) ") ";
290 |    font-size: 50%;
291 |   }
292 | 
293 |   #help {
294 |     display: none;
295 |     visibility: hidden;
296 |   }
297 | }
298 | 
299 | /* Styles for slides */
300 | 
301 | .slides > article {
302 |   /* font-family: 'Open Sans', Arial, sans-serif; */
303 |   font-family: Arial, sans-serif;
304 | 
305 |   color: var(--font-color);
306 |   /* text-shadow: 0 1px 1px rgba(0, 0, 0, .1); */
307 | 
308 |   font-size: 26px;
309 |   line-height: 36px;
310 | }
311 | 
312 | b {
313 |   font-weight: 600;
314 | }
315 | 
316 | a {
317 |   color: rgb(0, 102, 204);
318 |   text-decoration: none;
319 | }
320 | a:visited {
321 |   color: rgba(0, 102, 204, .75);
322 | }
323 | a:hover {
324 |   color: black;
325 | }
326 | 
327 | article.background {
328 |   background-size: contain;
329 |   background-repeat: round;
330 | }
331 | 
332 | .pagenumber {
333 |   color: var(--font-color);
334 |   font-size: 75%;
335 |   position: absolute;
336 |   bottom: 0px;
337 |   right: 10px;
338 | }
339 | 
340 | /* Code */
341 | 
342 | div.playground {
343 |   position: relative;
344 | }
345 | div.output {
346 |   position: absolute;
347 |   left: 50%;
348 |   top: 50%;
349 |   right: 40px;
350 |   bottom: 40px;
351 |   background: #202020;
352 |   padding: 5px 10px;
353 |   z-index: 2;
354 | 
355 |   border-radius: 10px;
356 |   -o-border-radius: 10px;
357 |   -moz-border-radius: 10px;
358 |   -webkit-border-radius: 10px;
359 | 
360 | }
361 | div.output pre {
362 |   margin: 0;
363 |   padding: 0;
364 |   background: none;
365 |   border: none;
366 |   width: 100%;
367 |   height: 100%;
368 |   overflow: auto;
369 | }
370 | div.output .stdout, div.output pre {
371 |   color: #e6e6e6;
372 | }
373 | div.output .stderr, div.output .error {
374 |   color: rgb(255, 200, 200);
375 | }
376 | div.output .system, div.output .exit {
377 |   color: rgb(255, 230, 120)
378 | }
379 | .buttons {
380 |   position: relative;
381 |   float: right;
382 |   top: -60px;
383 |   right: 10px;
384 | }
385 | div.output .buttons {
386 |   position: absolute;
387 |   float: none;
388 |   top: auto;
389 |   right: 5px;
390 |   bottom: 5px;
391 | }
392 | 
393 | /* Presenter details */
394 | .presenter {
395 |   margin-top: 20px;
396 | }
397 | .presenter p,
398 | .presenter .link {
399 |   margin: 0;
400 |   font-size: 28px;
401 |   line-height: 1.2em;
402 | }
403 | 
404 | /* Output resize details */
405 | .ui-resizable-handle {
406 |   position: absolute;
407 | }
408 | .ui-resizable-n {
409 |   cursor: n-resize;
410 |   height: 7px;
411 |   width: 100%;
412 |   top: -5px;
413 |   left: 0;
414 | }
415 | .ui-resizable-w {
416 |   cursor: w-resize;
417 |   width: 7px;
418 |   left: -5px;
419 |   top: 0;
420 |   height: 100%;
421 | }
422 | .ui-resizable-nw {
423 |   cursor: nw-resize;
424 |   width: 9px;
425 |   height: 9px;
426 |   left: -5px;
427 |   top: -5px;
428 | }
429 | iframe {
430 |   border: none;
431 | }
432 | figcaption {
433 |   color: #666;
434 |   text-align: center;
435 |   font-size: 0.75em;
436 | }
437 | 
438 | #help {
439 |   display: none;
440 |   font-family: 'Open Sans', Arial, sans-serif;
441 |   text-align: center;
442 |   color: white;
443 |   background: #000;
444 |   opacity: 0.5;
445 |   position: fixed;
446 |   bottom: 25px;
447 |   left: 50px;
448 |   right: 50px;
449 |   padding: 20px;
450 | 
451 |   border-radius: 10px;
452 |   -o-border-radius: 10px;
453 |   -moz-border-radius: 10px;
454 |   -webkit-border-radius: 10px;
455 | }
456 | 
457 | .article-title {
458 |   font-size: 42px;
459 |   padding: 0;
460 |   margin: 0;
461 |   padding: var(--article-title-padding);
462 |   font-weight: 600;
463 |   color: var(--font-color)
464 | }
465 | 
466 | .slogan {
467 |   text-align: center;
468 |   color: var(--font-color);
469 |   font-size: var(--slogan-font-size);
470 | }
471 | 
472 | .slogan-10 {
473 |   padding-top: 10%;
474 | }
475 | 
476 | .slogan-15 {
477 |   padding-top: 15%;
478 | }
479 | 
480 | .bold {
481 |   font-weight: 600;
482 | }
483 | 
484 | .content {
485 |   padding-top: 20px;
486 |   padding-left: 50px;
487 | }
488 | 
489 | ul {
490 |   margin: 0;
491 |   padding: 0;
492 |   margin-top: 20px;
493 |   margin-left: 1.5em;
494 | }
495 | 
496 | li {
497 |   padding: 0;
498 |   margin: 0 0 .5em 0;
499 | }
500 | 
501 | .landing-title {
502 |   font-size: 60px;
503 |   line-height: 100px;
504 | 
505 |   padding: 0;
506 |   padding-top: 200px;
507 |   padding-right: 40px;
508 | 
509 |   font-weight: 600;
510 | 
511 |   color: var(--font-color);
512 | }
513 | 
514 | /* table {
515 |   width: 100%;
516 |   border-collapse: collapse;
517 |   margin-top: 40px;
518 | }
519 | th {
520 |   font-weight: 600;
521 |   text-align: left;
522 | }
523 | td,
524 | th {
525 |   border: 1px solid rgb(224, 224, 224);
526 |   padding: 5px 10px;
527 |   vertical-align: top;
528 | } */
529 | 
530 | 
531 | .embeded-gist {
532 |   overflow-y: scroll;
533 |   height: 60%;
534 |   width: 100%;
535 |   padding:0;
536 |   margin: 0 auto;
537 | }
538 | 
539 | code {
540 |   /* font-family: 'Open Sans', Arial, sans-serif !important; */
541 |   font-family: Menlo, Monaco, "Courier New", monospace !important;
542 | }
543 | 
544 | .code {
545 |   overflow-y: scroll;
546 |   height: auto;
547 |   max-height: 85%;
548 |   width: 100%;
549 |   padding: 0;
550 |   margin: 0;
551 |   
552 | }
553 | 
554 | .code18 {
555 |   font-size: 18px;
556 |   line-height: 27px;
557 | }
558 | 
559 | .code20 {
560 |   font-size: 20px;
561 |   line-height: 29px;
562 | }
563 | 
564 | .code22 {
565 |   font-size: 22px;
566 |   line-height: 31px;
567 | }
568 | 
569 | .hljs {
570 |   padding: 0px 10px 10px 30px !important;
571 |   margin-top: -20px !important;
572 | }
573 | 
574 | .code pre {
575 |   padding: 0;
576 |   margin: 0;
577 | }
578 | 
579 | .code code {
580 |   padding: 0;
581 |   margin: 0;
582 | }
583 | 
584 | .h75 {
585 |   height: 75%;
586 | }
587 | 
588 | .h70 {
589 |   height: 70%;
590 | }
591 | 
592 | .h65 {
593 |   height: 65%;
594 | }
595 | 
596 | .h60 {
597 |   height: 60%;
598 | }
599 | 
600 | .h55 {
601 |   height: 55%;
602 | }
603 | 
604 | .h50 {
605 |   height: 50%;
606 | }
607 | 
608 | .f20 {
609 |   font-size: 20px;
610 |   line-height: 22px;
611 | }
612 | 
613 | ::selection {
614 |   background: #f5e3a6;
615 |   color: #fff;
616 | }
617 | 
618 | /* pre {
619 |   margin: 0;
620 |   padding: 0;
621 | 
622 |   font-family: 'Droid Sans Mono', 'Courier New', monospace;
623 |   font-size: 18px;
624 |   line-height: 24px;
625 | 
626 |   color: black;
627 | }
628 | 
629 | pre.numbers span:before {
630 |   content: attr(num);
631 |   margin-right: 1em;
632 |   display: inline-block;
633 | } */
634 | 
635 | /* code {
636 |   font-size: 95%;
637 |   font-family: 'Droid Sans Mono', 'Courier New', monospace;
638 | 
639 |   color: black;
640 | } */
641 | 
642 | article > .image,
643 | article > .video {
644 |   text-align: center;
645 | }
646 | 
647 | /* div.code {
648 |   padding: 5px 10px;
649 |   margin-top: 20px;
650 |   margin-bottom: 20px;
651 |   overflow: hidden;
652 |   overflow-y:scroll; 
653 |   height: var(--codeblocks-height);
654 | 
655 |   background: rgb(240, 240, 240);
656 |   border: 1px solid rgb(224, 224, 224);
657 | }
658 | div.code {
659 |   outline: 0px solid transparent;
660 | } */
661 | 
662 | .codeblock {
663 |   margin: 0px 0px 0px 0px;
664 |   padding: 0px 0px 0px 0px;
665 | }


--------------------------------------------------------------------------------
/themes/bright/static/template.css:
--------------------------------------------------------------------------------
  1 | /*
  2 | 
  3 | XCode style (c) Angel Garcia 
  4 | 
  5 | */
  6 | 
  7 | .hljs {
  8 |   display: block;
  9 |   overflow-x: auto;
 10 |   padding: 0.5em;
 11 |   background: #fff;
 12 |   color: black;
 13 | }
 14 | 
 15 | /* Gray DOCTYPE selectors like WebKit */
 16 | .xml .hljs-meta {
 17 |   color: #c0c0c0;
 18 | }
 19 | 
 20 | .hljs-comment,
 21 | .hljs-quote {
 22 |   color: #007400;
 23 | }
 24 | 
 25 | .hljs-tag,
 26 | .hljs-attribute,
 27 | .hljs-keyword,
 28 | .hljs-selector-tag,
 29 | .hljs-literal,
 30 | .hljs-name {
 31 |   color: #aa0d91;
 32 | }
 33 | 
 34 | .hljs-variable,
 35 | .hljs-template-variable {
 36 |   color: #3F6E74;
 37 | }
 38 | 
 39 | .hljs-code,
 40 | .hljs-string,
 41 | .hljs-meta-string {
 42 |   color: #c41a16;
 43 | }
 44 | 
 45 | .hljs-regexp,
 46 | .hljs-link {
 47 |   color: #0E0EFF;
 48 | }
 49 | 
 50 | .hljs-title,
 51 | .hljs-symbol,
 52 | .hljs-bullet,
 53 | .hljs-number {
 54 |   color: #1c00cf;
 55 | }
 56 | 
 57 | .hljs-section,
 58 | .hljs-meta {
 59 |   color: #643820;
 60 | }
 61 | 
 62 | 
 63 | .hljs-class .hljs-title,
 64 | .hljs-type,
 65 | .hljs-built_in,
 66 | .hljs-builtin-name,
 67 | .hljs-params {
 68 |   color: #5c2699;
 69 | }
 70 | 
 71 | .hljs-attr {
 72 |   color: #836C28;
 73 | }
 74 | 
 75 | .hljs-subst {
 76 |   color: #000;
 77 | }
 78 | 
 79 | .hljs-formula {
 80 |   background-color: #eee;
 81 |   font-style: italic;
 82 | }
 83 | 
 84 | .hljs-addition {
 85 |   background-color: #baeeba;
 86 | }
 87 | 
 88 | .hljs-deletion {
 89 |   background-color: #ffc8bd;
 90 | }
 91 | 
 92 | .hljs-selector-id,
 93 | .hljs-selector-class {
 94 |   color: #9b703f;
 95 | }
 96 | 
 97 | .hljs-doctag,
 98 | .hljs-strong {
 99 |   font-weight: bold;
100 | }
101 | 
102 | .hljs-emphasis {
103 |   font-style: italic;
104 | }
105 | 


--------------------------------------------------------------------------------
/themes/bright/static/template2.css:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Visual Studio 2015 dark style
  3 |  * Author: Nicolas LLOBERA 
  4 |  */
  5 | 
  6 | .hljs {
  7 |   display: block;
  8 |   overflow-x: auto;
  9 |   padding: 0.5em;
 10 |   background: #1E1E1E;
 11 |   color: #DCDCDC;
 12 | }
 13 | 
 14 | .hljs-keyword,
 15 | .hljs-literal,
 16 | .hljs-symbol,
 17 | .hljs-name {
 18 |   color: #569CD6;
 19 | }
 20 | .hljs-link {
 21 |   color: #569CD6;
 22 |   text-decoration: underline;
 23 | }
 24 | 
 25 | .hljs-built_in,
 26 | .hljs-type {
 27 |   color: #4EC9B0;
 28 | }
 29 | 
 30 | .hljs-number,
 31 | .hljs-class {
 32 |   color: #B8D7A3;
 33 | }
 34 | 
 35 | .hljs-string,
 36 | .hljs-meta-string {
 37 |   color: #D69D85;
 38 | }
 39 | 
 40 | .hljs-regexp,
 41 | .hljs-template-tag {
 42 |   color: #9A5334;
 43 | }
 44 | 
 45 | .hljs-subst,
 46 | .hljs-function,
 47 | .hljs-title,
 48 | .hljs-params,
 49 | .hljs-formula {
 50 |   color: #DCDCDC;
 51 | }
 52 | 
 53 | .hljs-comment,
 54 | .hljs-quote {
 55 |   color: #57A64A;
 56 |   font-style: italic;
 57 | }
 58 | 
 59 | .hljs-doctag {
 60 |   color: #608B4E;
 61 | }
 62 | 
 63 | .hljs-meta,
 64 | .hljs-meta-keyword,
 65 | .hljs-tag {
 66 |   color: #9B9B9B;
 67 | }
 68 | 
 69 | .hljs-variable,
 70 | .hljs-template-variable {
 71 |   color: #BD63C5;
 72 | }
 73 | 
 74 | .hljs-attr,
 75 | .hljs-attribute,
 76 | .hljs-builtin-name {
 77 |   color: #9CDCFE;
 78 | }
 79 | 
 80 | .hljs-section {
 81 |   color: gold;
 82 | }
 83 | 
 84 | .hljs-emphasis {
 85 |   font-style: italic;
 86 | }
 87 | 
 88 | .hljs-strong {
 89 |   font-weight: bold;
 90 | }
 91 | 
 92 | /*.hljs-code {
 93 |   font-family:'Monospace';
 94 | }*/
 95 | 
 96 | .hljs-bullet,
 97 | .hljs-selector-tag,
 98 | .hljs-selector-id,
 99 | .hljs-selector-class,
100 | .hljs-selector-attr,
101 | .hljs-selector-pseudo {
102 |   color: #D7BA7D;
103 | }
104 | 
105 | .hljs-addition {
106 |   background-color: #144212;
107 |   display: inline-block;
108 |   width: 100%;
109 | }
110 | 
111 | .hljs-deletion {
112 |   background-color: #600;
113 |   display: inline-block;
114 |   width: 100%;
115 | }
116 | 


--------------------------------------------------------------------------------
/themes/bright/static/vs2015.css:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Visual Studio 2015 dark style
  3 |  * Author: Nicolas LLOBERA 
  4 |  */
  5 | 
  6 | .hljs {
  7 |   display: block;
  8 |   overflow-x: auto;
  9 |   padding: 0.5em;
 10 |   background: #1E1E1E;
 11 |   color: #DCDCDC;
 12 | }
 13 | 
 14 | .hljs-keyword,
 15 | .hljs-literal,
 16 | .hljs-symbol,
 17 | .hljs-name {
 18 |   color: #569CD6;
 19 | }
 20 | .hljs-link {
 21 |   color: #569CD6;
 22 |   text-decoration: underline;
 23 | }
 24 | 
 25 | .hljs-built_in,
 26 | .hljs-type {
 27 |   color: #4EC9B0;
 28 | }
 29 | 
 30 | .hljs-number,
 31 | .hljs-class {
 32 |   color: #B8D7A3;
 33 | }
 34 | 
 35 | .hljs-string,
 36 | .hljs-meta-string {
 37 |   color: #D69D85;
 38 | }
 39 | 
 40 | .hljs-regexp,
 41 | .hljs-template-tag {
 42 |   color: #9A5334;
 43 | }
 44 | 
 45 | .hljs-subst,
 46 | .hljs-function,
 47 | .hljs-title,
 48 | .hljs-params,
 49 | .hljs-formula {
 50 |   color: #DCDCDC;
 51 | }
 52 | 
 53 | .hljs-comment,
 54 | .hljs-quote {
 55 |   color: #57A64A;
 56 |   font-style: italic;
 57 | }
 58 | 
 59 | .hljs-doctag {
 60 |   color: #608B4E;
 61 | }
 62 | 
 63 | .hljs-meta,
 64 | .hljs-meta-keyword,
 65 | .hljs-tag {
 66 |   color: #9B9B9B;
 67 | }
 68 | 
 69 | .hljs-variable,
 70 | .hljs-template-variable {
 71 |   color: #BD63C5;
 72 | }
 73 | 
 74 | .hljs-attr,
 75 | .hljs-attribute,
 76 | .hljs-builtin-name {
 77 |   color: #9CDCFE;
 78 | }
 79 | 
 80 | .hljs-section {
 81 |   color: gold;
 82 | }
 83 | 
 84 | .hljs-emphasis {
 85 |   font-style: italic;
 86 | }
 87 | 
 88 | .hljs-strong {
 89 |   font-weight: bold;
 90 | }
 91 | 
 92 | /*.hljs-code {
 93 |   font-family:'Monospace';
 94 | }*/
 95 | 
 96 | .hljs-bullet,
 97 | .hljs-selector-tag,
 98 | .hljs-selector-id,
 99 | .hljs-selector-class,
100 | .hljs-selector-attr,
101 | .hljs-selector-pseudo {
102 |   color: #D7BA7D;
103 | }
104 | 
105 | .hljs-addition {
106 |   background-color: #144212;
107 |   display: inline-block;
108 |   width: 100%;
109 | }
110 | 
111 | .hljs-deletion {
112 |   background-color: #600;
113 |   display: inline-block;
114 |   width: 100%;
115 | }
116 | 


--------------------------------------------------------------------------------
/themes/bright/static/xcode.css:
--------------------------------------------------------------------------------
  1 | /*
  2 | 
  3 | XCode style (c) Angel Garcia 
  4 | 
  5 | */
  6 | 
  7 | .hljs {
  8 |   display: block;
  9 |   overflow-x: auto;
 10 |   padding: 0.5em;
 11 |   background: #fff;
 12 |   color: black;
 13 | }
 14 | 
 15 | /* Gray DOCTYPE selectors like WebKit */
 16 | .xml .hljs-meta {
 17 |   color: #c0c0c0;
 18 | }
 19 | 
 20 | .hljs-comment,
 21 | .hljs-quote {
 22 |   color: #007400;
 23 | }
 24 | 
 25 | .hljs-tag,
 26 | .hljs-attribute,
 27 | .hljs-keyword,
 28 | .hljs-selector-tag,
 29 | .hljs-literal,
 30 | .hljs-name {
 31 |   color: #aa0d91;
 32 | }
 33 | 
 34 | .hljs-variable,
 35 | .hljs-template-variable {
 36 |   color: #3F6E74;
 37 | }
 38 | 
 39 | .hljs-code,
 40 | .hljs-string,
 41 | .hljs-meta-string {
 42 |   color: #c41a16;
 43 | }
 44 | 
 45 | .hljs-regexp,
 46 | .hljs-link {
 47 |   color: #0E0EFF;
 48 | }
 49 | 
 50 | .hljs-title,
 51 | .hljs-symbol,
 52 | .hljs-bullet,
 53 | .hljs-number {
 54 |   color: #1c00cf;
 55 | }
 56 | 
 57 | .hljs-section,
 58 | .hljs-meta {
 59 |   color: #643820;
 60 | }
 61 | 
 62 | 
 63 | .hljs-class .hljs-title,
 64 | .hljs-type,
 65 | .hljs-built_in,
 66 | .hljs-builtin-name,
 67 | .hljs-params {
 68 |   color: #5c2699;
 69 | }
 70 | 
 71 | .hljs-attr {
 72 |   color: #836C28;
 73 | }
 74 | 
 75 | .hljs-subst {
 76 |   color: #000;
 77 | }
 78 | 
 79 | .hljs-formula {
 80 |   background-color: #eee;
 81 |   font-style: italic;
 82 | }
 83 | 
 84 | .hljs-addition {
 85 |   background-color: #baeeba;
 86 | }
 87 | 
 88 | .hljs-deletion {
 89 |   background-color: #ffc8bd;
 90 | }
 91 | 
 92 | .hljs-selector-id,
 93 | .hljs-selector-class {
 94 |   color: #9b703f;
 95 | }
 96 | 
 97 | .hljs-doctag,
 98 | .hljs-strong {
 99 |   font-weight: bold;
100 | }
101 | 
102 | .hljs-emphasis {
103 |   font-style: italic;
104 | }
105 | 


--------------------------------------------------------------------------------
/themes/bright/templates/action.tmpl:
--------------------------------------------------------------------------------
 1 | {/*
 2 | This is the action template.
 3 | It determines how the formatting actions are rendered.
 4 | */}
 5 | 
 6 | {{define "section"}}
 7 |   {{.FormattedNumber}} {{.Title}}
 8 |   {{range .Elem}}{{elem $.Template .}}{{end}}
 9 | {{end}}
10 | 
11 | {{define "list"}}
12 |   
    13 | {{range .Bullet}} 14 |
  • {{style .}}
  • 15 | {{end}} 16 |
17 | {{end}} 18 | 19 | {{define "text"}} 20 | {{if .Pre}} 21 |
{{range .Lines}}{{.}}{{end}}
22 | {{else}} 23 |

24 | {{range $i, $l := .Lines}}{{if $i}}{{template "newline"}} 25 | {{end}}{{style $l}}{{end}} 26 |

27 | {{end}} 28 | {{end}} 29 | 30 | {{define "code"}} 31 |
{{.Text}}
32 | {{end}} 33 | 34 | {{define "monaco"}} 35 |
36 | {{end}} 37 | 38 | {{define "image"}} 39 |
40 | 41 |
42 | {{end}} 43 | 44 | {{define "video"}} 45 |
46 | 49 |
50 | {{end}} 51 | 52 | {{define "background"}} 53 |
54 | 55 |
56 | {{end}} 57 | 58 | {{define "iframe"}} 59 | 60 | {{end}} 61 | 62 | {{define "link"}}{{end}} 63 | 64 | {{define "html"}}{{.HTML}}{{end}} 65 | 66 | {{define "inlinehtml"}}{{.HTML}}{{end}} 67 | 68 | {{define "caption"}}
{{style .Text}}
{{end}} 69 | -------------------------------------------------------------------------------- /themes/bright/templates/article.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the article template. It defines how articles are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 10 | 27 | 28 | 29 | 30 |
31 |
32 |
{{.Title}} 33 | {{with .Subtitle}}{{.}}{{end}} 34 | {{if .Authors}} 35 | {{range .Authors}} 36 |
37 | {{range .Elem}}{{elem $.Template .}}{{end}} 38 |
39 | {{end}} 40 | {{end}} 41 |
42 |
43 |
44 |
45 |
46 | {{with .Sections}} 47 |
48 |
Contents
49 | {{template "TOC" .}} 50 |
51 | {{end}} 52 | 53 | {{range .Sections}} 54 | {{elem $.Template .}} 55 | {{end}}{{/* of Section block */}} 56 | 57 |
58 |
59 | 60 | {{if .PlayEnabled}} 61 | 62 | {{end}} 63 | 64 | 74 | 75 | 76 | {{end}} 77 | 78 | {{define "TOC"}} 79 |
    80 | {{range .}} 81 |
  • {{.Title}}
  • 82 | {{with .Sections}}{{template "TOC-Inner" .}}{{end}} 83 | {{end}} 84 |
85 | {{end}} 86 | 87 | {{define "TOC-Inner"}} 88 |
    89 | {{range .}} 90 |
  • {{.Title}}
  • 91 | {{with .Sections}}{{template "TOC-Inner" .}}{{end}} 92 | {{end}} 93 |
94 | {{end}} 95 | 96 | {{define "newline"}} 97 | {{/* No automatic line break. Paragraphs are free-form. */}} 98 | {{end}} 99 | -------------------------------------------------------------------------------- /themes/bright/templates/dir.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Talks - The Go Programming Language 6 | 7 | 8 | 25 | 26 | 27 | 28 |
29 | 30 |
31 | 39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 |

Go talks

47 | 48 | {{with .Path}}

{{.}}

{{end}} 49 | 50 | {{with .Articles}} 51 |

Articles:

52 |
53 | {{range .}} 54 |
{{.Name}}: {{.Title}}
55 | {{end}} 56 |
57 | {{end}} 58 | 59 | {{with .Slides}} 60 |

Slide decks:

61 |
62 | {{range .}} 63 |
{{.Name}}: {{.Title}}
64 | {{end}} 65 |
66 | {{end}} 67 | 68 | {{with .Other}} 69 |

Files:

70 |
71 | {{range .}} 72 |
{{.Name}}
73 | {{end}} 74 |
75 | {{end}} 76 | 77 | {{with .Dirs}} 78 |

Sub-directories:

79 |
80 | {{range .}} 81 |
{{.Name}}
82 | {{end}} 83 |
84 | {{end}} 85 | 86 |
87 | 88 | 96 | 97 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /themes/bright/templates/slides.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the slide template. It defines how presentations are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 12 | 14 | 15 | 17 | 19 | 20 | 21 | 22 | {{if .NotesEnabled}} 23 | 27 | 28 | {{end}} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | 42 | 43 | 44 |
45 | 46 |
47 |

{{.Title}}

48 | {{with .Subtitle}}

{{.}}

{{end}} 49 | {{if not .Time.IsZero}}

{{.Time.Format "2 January 2006"}}

{{end}} 50 | {{range .Authors}} 51 |
52 | {{range .TextElem}}{{elem $.Template .}}{{end}} 53 |
54 | {{end}} 55 | 56 |
57 | 58 | {{range $i, $s := .Sections}} 59 | 60 |
61 | {{if $s.Elem}} 62 |

{{$s.Title}}

63 | {{range $s.Elem}}{{elem $.Template .}}{{end}} 64 | {{else}} 65 |

{{$s.Title}}

66 | {{end}} 67 | {{pagenum $s 1}} 68 | 69 |
70 | 71 | {{end}}{{/* of Slide block */}} 72 | 73 |
74 | 75 |
76 | Use the left and right arrow keys or click the left and right 77 | edges of the page to navigate between slides.
78 | (Press 'H' or navigate to hide this message.) 79 |
80 | 81 | 91 | 92 | 93 | {{end}} 94 | 95 | {{define "newline"}} 96 |
97 | {{end}} 98 | -------------------------------------------------------------------------------- /themes/default/static/atom-one-dark-reasonable.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | Atom One Dark With support for ReasonML by Gidi Morris, based off work by Daniel Gamage 4 | 5 | Original One Dark Syntax theme from https://github.com/atom/one-dark-syntax 6 | 7 | */ 8 | .hljs { 9 | display: block; 10 | overflow-x: auto; 11 | padding: 0.5em; 12 | line-height: 1.3em; 13 | color: #abb2bf; 14 | background: #282c34; 15 | border-radius: 5px; 16 | } 17 | .hljs-keyword, .hljs-operator { 18 | color: #F92672; 19 | } 20 | .hljs-pattern-match { 21 | color: #F92672; 22 | } 23 | .hljs-pattern-match .hljs-constructor { 24 | color: #61aeee; 25 | } 26 | .hljs-function { 27 | color: #61aeee; 28 | } 29 | .hljs-function .hljs-params { 30 | color: #A6E22E; 31 | } 32 | .hljs-function .hljs-params .hljs-typing { 33 | color: #FD971F; 34 | } 35 | .hljs-module-access .hljs-module { 36 | color: #7e57c2; 37 | } 38 | .hljs-constructor { 39 | color: #e2b93d; 40 | } 41 | .hljs-constructor .hljs-string { 42 | color: #9CCC65; 43 | } 44 | .hljs-comment, .hljs-quote { 45 | color: #b18eb1; 46 | font-style: italic; 47 | } 48 | .hljs-doctag, .hljs-formula { 49 | color: #c678dd; 50 | } 51 | .hljs-section, .hljs-name, .hljs-selector-tag, .hljs-deletion, .hljs-subst { 52 | color: #e06c75; 53 | } 54 | .hljs-literal { 55 | color: #56b6c2; 56 | } 57 | .hljs-string, .hljs-regexp, .hljs-addition, .hljs-attribute, .hljs-meta-string { 58 | color: #98c379; 59 | } 60 | .hljs-built_in, .hljs-class .hljs-title { 61 | color: #e6c07b; 62 | } 63 | .hljs-attr, .hljs-variable, .hljs-template-variable, .hljs-type, .hljs-selector-class, .hljs-selector-attr, .hljs-selector-pseudo, .hljs-number { 64 | color: #d19a66; 65 | } 66 | .hljs-symbol, .hljs-bullet, .hljs-link, .hljs-meta, .hljs-selector-id, .hljs-title { 67 | color: #61aeee; 68 | } 69 | .hljs-emphasis { 70 | font-style: italic; 71 | } 72 | .hljs-strong { 73 | font-weight: bold; 74 | } 75 | .hljs-link { 76 | text-decoration: underline; 77 | } 78 | -------------------------------------------------------------------------------- /themes/default/static/dir.css: -------------------------------------------------------------------------------- 1 | /* copied from $GOROOT/doc/style.css */ 2 | 3 | body { 4 | margin: 0; 5 | font-family: Helvetica, Arial, sans-serif; 6 | font-size: 16px; 7 | } 8 | pre, 9 | code { 10 | font-family: Menlo, monospace; 11 | font-size: 14px; 12 | } 13 | pre { 14 | line-height: 18px; 15 | } 16 | pre .comment { 17 | color: #375EAB; 18 | } 19 | pre .highlight, 20 | pre .highlight-comment, 21 | pre .selection-highlight, 22 | pre .selection-highlight-comment { 23 | background: #FFFF00; 24 | } 25 | pre .selection, 26 | pre .selection-comment { 27 | background: #FF9632; 28 | } 29 | pre .ln { 30 | color: #999; 31 | } 32 | body { 33 | color: #222; 34 | } 35 | a, 36 | .exampleHeading .text { 37 | color: #375EAB; 38 | text-decoration: none; 39 | } 40 | a:hover, 41 | .exampleHeading .text:hover { 42 | text-decoration: underline; 43 | } 44 | p, 45 | pre, 46 | ul, 47 | ol { 48 | margin: 20px; 49 | } 50 | pre { 51 | background: #e9e9e9; 52 | padding: 10px; 53 | 54 | -webkit-border-radius: 5px; 55 | -moz-border-radius: 5px; 56 | border-radius: 5px; 57 | } 58 | 59 | h1, 60 | h2, 61 | h3, 62 | h4, 63 | .rootHeading { 64 | margin: 20px 0; 65 | padding: 0; 66 | color: #375EAB; 67 | font-weight: bold; 68 | } 69 | h1 { 70 | font-size: 24px; 71 | } 72 | h2 { 73 | font-size: 20px; 74 | background: #E0EBF5; 75 | padding: 2px 5px; 76 | } 77 | h3 { 78 | font-size: 20px; 79 | } 80 | h3, 81 | h4 { 82 | margin: 20px 5px; 83 | } 84 | h4 { 85 | font-size: 16px; 86 | } 87 | 88 | dl { 89 | margin: 20px; 90 | } 91 | dd { 92 | margin: 2px 20px; 93 | } 94 | dl, 95 | dd { 96 | font-size: 14px; 97 | } 98 | div#nav table td { 99 | vertical-align: top; 100 | } 101 | 102 | div#heading { 103 | float: left; 104 | margin: 0 0 10px 0; 105 | padding: 21px 0; 106 | font-size: 20px; 107 | font-weight: normal; 108 | } 109 | div#heading a { 110 | color: #222; 111 | text-decoration: none; 112 | } 113 | 114 | div#topbar { 115 | background: #E0EBF5; 116 | height: 64px; 117 | } 118 | 119 | body { 120 | text-align: center; 121 | } 122 | div#page, 123 | div#topbar > .container { 124 | clear: both; 125 | text-align: left; 126 | margin-left: auto; 127 | margin-right: auto; 128 | padding: 0 20px; 129 | width: 900px; 130 | } 131 | div#page.wide, 132 | div#topbar > .wide { 133 | width: auto; 134 | } 135 | div#plusone { 136 | float: right; 137 | } 138 | 139 | div#footer { 140 | color: #666; 141 | font-size: 14px; 142 | margin: 40px 0; 143 | } 144 | 145 | div#menu > a, 146 | div#menu > input { 147 | padding: 10px; 148 | 149 | text-decoration: none; 150 | font-size: 16px; 151 | 152 | -webkit-border-radius: 5px; 153 | -moz-border-radius: 5px; 154 | border-radius: 5px; 155 | } 156 | div#menu > a, 157 | div#menu > input { 158 | border: 1px solid #375EAB; 159 | } 160 | div#menu > a { 161 | color: white; 162 | background: #375EAB; 163 | } 164 | 165 | div#menu { 166 | float: right; 167 | min-width: 590px; 168 | padding: 10px 0; 169 | text-align: right; 170 | } 171 | div#menu > a { 172 | margin-right: 5px; 173 | margin-bottom: 10px; 174 | 175 | padding: 10px; 176 | } 177 | div#menu > input { 178 | position: relative; 179 | top: 1px; 180 | width: 60px; 181 | background: white; 182 | color: #222; 183 | } 184 | div#menu > input.inactive { 185 | color: #999; 186 | } 187 | -------------------------------------------------------------------------------- /themes/default/static/dir.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | // copied from $GOROOT/doc/godocs.js 6 | 7 | function bindEvent(el, e, fn) { 8 | if (el.addEventListener){ 9 | el.addEventListener(e, fn, false); 10 | } else if (el.attachEvent){ 11 | el.attachEvent('on'+e, fn); 12 | } 13 | } 14 | 15 | function godocs_bindSearchEvents() { 16 | var search = document.getElementById('search'); 17 | if (!search) { 18 | // no search box (index disabled) 19 | return; 20 | } 21 | function clearInactive() { 22 | if (search.className == "inactive") { 23 | search.value = ""; 24 | search.className = ""; 25 | } 26 | } 27 | function restoreInactive() { 28 | if (search.value !== "") { 29 | return; 30 | } 31 | if (search.type != "search") { 32 | search.value = search.getAttribute("placeholder"); 33 | } 34 | search.className = "inactive"; 35 | } 36 | restoreInactive(); 37 | bindEvent(search, 'focus', clearInactive); 38 | bindEvent(search, 'blur', restoreInactive); 39 | } 40 | 41 | bindEvent(window, 'load', godocs_bindSearchEvents); 42 | -------------------------------------------------------------------------------- /themes/default/static/favicon.ico: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/LeeXun/slides/f1f6a370bad8d42f4e1e3af27cdfd5690cb24486/themes/default/static/favicon.ico -------------------------------------------------------------------------------- /themes/default/static/highlight.pack.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.15.6 | BSD3 License | git.io/hljslicense */ 2 | !function(e){var n="object"==typeof window&&window||"object"==typeof self&&self;"undefined"!=typeof exports?e(exports):n&&(n.hljs=e({}),"function"==typeof define&&define.amd&&define([],function(){return n.hljs}))}(function(a){var E=[],u=Object.keys,N={},g={},n=/^(no-?highlight|plain|text)$/i,R=/\blang(?:uage)?-([\w-]+)\b/i,t=/((^(<[^>]+>|\t|)+|(?:\n)))/gm,r={case_insensitive:"cI",lexemes:"l",contains:"c",keywords:"k",subLanguage:"sL",className:"cN",begin:"b",beginKeywords:"bK",end:"e",endsWithParent:"eW",illegal:"i",excludeBegin:"eB",excludeEnd:"eE",returnBegin:"rB",returnEnd:"rE",relevance:"r",variants:"v",IDENT_RE:"IR",UNDERSCORE_IDENT_RE:"UIR",NUMBER_RE:"NR",C_NUMBER_RE:"CNR",BINARY_NUMBER_RE:"BNR",RE_STARTERS_RE:"RSR",BACKSLASH_ESCAPE:"BE",APOS_STRING_MODE:"ASM",QUOTE_STRING_MODE:"QSM",PHRASAL_WORDS_MODE:"PWM",C_LINE_COMMENT_MODE:"CLCM",C_BLOCK_COMMENT_MODE:"CBCM",HASH_COMMENT_MODE:"HCM",NUMBER_MODE:"NM",C_NUMBER_MODE:"CNM",BINARY_NUMBER_MODE:"BNM",CSS_NUMBER_MODE:"CSSNM",REGEXP_MODE:"RM",TITLE_MODE:"TM",UNDERSCORE_TITLE_MODE:"UTM",COMMENT:"C",beginRe:"bR",endRe:"eR",illegalRe:"iR",lexemesRe:"lR",terminators:"t",terminator_end:"tE"},b="",h={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0};function _(e){return e.replace(/&/g,"&").replace(//g,">")}function d(e){return e.nodeName.toLowerCase()}function v(e,n){var t=e&&e.exec(n);return t&&0===t.index}function p(e){return n.test(e)}function l(e){var n,t={},r=Array.prototype.slice.call(arguments,1);for(n in e)t[n]=e[n];return r.forEach(function(e){for(n in e)t[n]=e[n]}),t}function M(e){var a=[];return function e(n,t){for(var r=n.firstChild;r;r=r.nextSibling)3===r.nodeType?t+=r.nodeValue.length:1===r.nodeType&&(a.push({event:"start",offset:t,node:r}),t=e(r,t),d(r).match(/br|hr|img|input/)||a.push({event:"stop",offset:t,node:r}));return t}(e,0),a}function i(e){if(r&&!e.langApiRestored){for(var n in e.langApiRestored=!0,r)e[n]&&(e[r[n]]=e[n]);(e.c||[]).concat(e.v||[]).forEach(i)}}function m(c){function s(e){return e&&e.source||e}function o(e,n){return new RegExp(s(e),"m"+(c.cI?"i":"")+(n?"g":""))}!function n(t,e){if(!t.compiled){if(t.compiled=!0,t.k=t.k||t.bK,t.k){var r={},a=function(t,e){c.cI&&(e=e.toLowerCase()),e.split(" ").forEach(function(e){var n=e.split("|");r[n[0]]=[t,n[1]?Number(n[1]):1]})};"string"==typeof t.k?a("keyword",t.k):u(t.k).forEach(function(e){a(e,t.k[e])}),t.k=r}t.lR=o(t.l||/\w+/,!0),e&&(t.bK&&(t.b="\\b("+t.bK.split(" ").join("|")+")\\b"),t.b||(t.b=/\B|\b/),t.bR=o(t.b),t.endSameAsBegin&&(t.e=t.b),t.e||t.eW||(t.e=/\B|\b/),t.e&&(t.eR=o(t.e)),t.tE=s(t.e)||"",t.eW&&e.tE&&(t.tE+=(t.e?"|":"")+e.tE)),t.i&&(t.iR=o(t.i)),null==t.r&&(t.r=1),t.c||(t.c=[]),t.c=Array.prototype.concat.apply([],t.c.map(function(e){return(n="self"===e?t:e).v&&!n.cached_variants&&(n.cached_variants=n.v.map(function(e){return l(n,{v:null},e)})),n.cached_variants||n.eW&&[l(n)]||[n];var n})),t.c.forEach(function(e){n(e,t)}),t.starts&&n(t.starts,e);var i=t.c.map(function(e){return e.bK?"\\.?(?:"+e.b+")\\.?":e.b}).concat([t.tE,t.i]).map(s).filter(Boolean);t.t=i.length?o(function(e,n){for(var t=/\[(?:[^\\\]]|\\.)*\]|\(\??|\\([1-9][0-9]*)|\\./,r=0,a="",i=0;i')+n+(t?"":b)}function s(){g+=null!=E.sL?function(){var e="string"==typeof E.sL;if(e&&!N[E.sL])return _(R);var n=e?C(E.sL,R,!0,i[E.sL]):O(R,E.sL.length?E.sL:void 0);return 0")+'"');return R+=n,n.length||1}var f=S(e);if(!f)throw new Error('Unknown language: "'+e+'"');m(f);var a,E=t||f,i={},g="";for(a=E;a!==f;a=a.parent)a.cN&&(g=u(a.cN,"",!0)+g);var R="",d=0;try{for(var c,p,M=0;E.t.lastIndex=M,c=E.t.exec(n);)p=r(n.substring(M,c.index),c[0]),M=c.index+p;for(r(n.substr(M)),a=E;a.parent;a=a.parent)a.cN&&(g+=b);return{r:d,value:g,language:e,top:E}}catch(e){if(e.message&&-1!==e.message.indexOf("Illegal"))return{r:0,value:_(n)};throw e}}function O(t,e){e=e||h.languages||u(N);var r={r:0,value:_(t)},a=r;return e.filter(S).filter(s).forEach(function(e){var n=C(e,t,!1);n.language=e,n.r>a.r&&(a=n),n.r>r.r&&(a=r,r=n)}),a.language&&(r.second_best=a),r}function B(e){return h.tabReplace||h.useBR?e.replace(t,function(e,n){return h.useBR&&"\n"===e?"
":h.tabReplace?n.replace(/\t/g,h.tabReplace):""}):e}function c(e){var n,t,r,a,i,c,o,u,s,l,f=function(e){var n,t,r,a,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=R.exec(i))return S(t[1])?t[1]:"no-highlight";for(n=0,r=(i=i.split(/\s+/)).length;n/g,"\n"):n=e,i=n.textContent,r=f?C(f,i,!0):O(i),(t=M(n)).length&&((a=document.createElementNS("http://www.w3.org/1999/xhtml","div")).innerHTML=r.value,r.value=function(e,n,t){var r=0,a="",i=[];function c(){return e.length&&n.length?e[0].offset!==n[0].offset?e[0].offset"}function u(e){a+=""}function s(e){("start"===e.event?o:u)(e.node)}for(;e.length||n.length;){var l=c();if(a+=_(t.substring(r,l[0].offset)),r=l[0].offset,l===e){for(i.reverse().forEach(u);s(l.splice(0,1)[0]),(l=c())===e&&l.length&&l[0].offset===r;);i.reverse().forEach(o)}else"start"===l[0].event?i.push(l[0].node):i.pop(),s(l.splice(0,1)[0])}return a+_(t.substr(r))}(t,M(a),i)),r.value=B(r.value),e.innerHTML=r.value,e.className=(c=e.className,o=f,u=r.language,s=o?g[o]:u,l=[c.trim()],c.match(/\bhljs\b/)||l.push("hljs"),-1===c.indexOf(s)&&l.push(s),l.join(" ").trim()),e.result={language:r.language,re:r.r},r.second_best&&(e.second_best={language:r.second_best.language,re:r.second_best.r}))}function o(){if(!o.called){o.called=!0;var e=document.querySelectorAll("pre code");E.forEach.call(e,c)}}function S(e){return e=(e||"").toLowerCase(),N[e]||N[g[e]]}function s(e){var n=S(e);return n&&!n.disableAutodetect}return a.highlight=C,a.highlightAuto=O,a.fixMarkup=B,a.highlightBlock=c,a.configure=function(e){h=l(h,e)},a.initHighlighting=o,a.initHighlightingOnLoad=function(){addEventListener("DOMContentLoaded",o,!1),addEventListener("load",o,!1)},a.registerLanguage=function(n,e){var t=N[n]=e(a);i(t),t.aliases&&t.aliases.forEach(function(e){g[e]=n})},a.listLanguages=function(){return u(N)},a.getLanguage=S,a.autoDetection=s,a.inherit=l,a.IR=a.IDENT_RE="[a-zA-Z]\\w*",a.UIR=a.UNDERSCORE_IDENT_RE="[a-zA-Z_]\\w*",a.NR=a.NUMBER_RE="\\b\\d+(\\.\\d+)?",a.CNR=a.C_NUMBER_RE="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",a.BNR=a.BINARY_NUMBER_RE="\\b(0b[01]+)",a.RSR=a.RE_STARTERS_RE="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",a.BE=a.BACKSLASH_ESCAPE={b:"\\\\[\\s\\S]",r:0},a.ASM=a.APOS_STRING_MODE={cN:"string",b:"'",e:"'",i:"\\n",c:[a.BE]},a.QSM=a.QUOTE_STRING_MODE={cN:"string",b:'"',e:'"',i:"\\n",c:[a.BE]},a.PWM=a.PHRASAL_WORDS_MODE={b:/\b(a|an|the|are|I'm|isn't|don't|doesn't|won't|but|just|should|pretty|simply|enough|gonna|going|wtf|so|such|will|you|your|they|like|more)\b/},a.C=a.COMMENT=function(e,n,t){var r=a.inherit({cN:"comment",b:e,e:n,c:[]},t||{});return r.c.push(a.PWM),r.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),r},a.CLCM=a.C_LINE_COMMENT_MODE=a.C("//","$"),a.CBCM=a.C_BLOCK_COMMENT_MODE=a.C("/\\*","\\*/"),a.HCM=a.HASH_COMMENT_MODE=a.C("#","$"),a.NM=a.NUMBER_MODE={cN:"number",b:a.NR,r:0},a.CNM=a.C_NUMBER_MODE={cN:"number",b:a.CNR,r:0},a.BNM=a.BINARY_NUMBER_MODE={cN:"number",b:a.BNR,r:0},a.CSSNM=a.CSS_NUMBER_MODE={cN:"number",b:a.NR+"(%|em|ex|ch|rem|vw|vh|vmin|vmax|cm|mm|in|pt|pc|px|deg|grad|rad|turn|s|ms|Hz|kHz|dpi|dpcm|dppx)?",r:0},a.RM=a.REGEXP_MODE={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[a.BE,{b:/\[/,e:/\]/,r:0,c:[a.BE]}]},a.TM=a.TITLE_MODE={cN:"title",b:a.IR,r:0},a.UTM=a.UNDERSCORE_TITLE_MODE={cN:"title",b:a.UIR,r:0},a.METHOD_GUARD={b:"\\.\\s*"+a.UIR,r:0},a});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[{b:'(u8?|U|L)?"',e:'"',i:"\\n",c:[t.BE]},{b:/(?:u8?|U|L)?R"([^()\\ ]{0,16})\((?:.|\n)*?\)\1"/},{b:"'\\\\?.",e:"'",i:"."}]},s={cN:"number",v:[{b:"\\b(0b[01']+)"},{b:"(-?)\\b([\\d']+(\\.[\\d']*)?|\\.[\\d']+)(u|U|l|L|ul|UL|f|F|b|B)"},{b:"(-?)(\\b0[xX][a-fA-F0-9']+|(\\b[\\d']+(\\.[\\d']*)?|\\.[\\d']+)([eE][-+]?[\\d']+)?)"}],r:0},i={cN:"meta",b:/#\s*[a-z]+\b/,e:/$/,k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef include"},c:[{b:/\\\n/,r:0},t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:/<[^\n>]*>/,e:/$/,i:"\\n"},t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch import module export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const for static_cast|10 union namespace unsigned long volatile static protected bool template mutable if public friend do goto auto void enum else break extern using asm case typeid short reinterpret_cast|10 default double register explicit signed typename try this switch continue inline delete alignof constexpr decltype noexcept static_assert thread_local restrict _Bool complex _Complex _Imaginary atomic_bool atomic_char atomic_schar atomic_uchar atomic_short atomic_ushort atomic_int atomic_uint atomic_long atomic_ulong atomic_llong atomic_ullong new throw return and or not",built_in:"std string cin cout cerr clog stdin stdout stderr stringstream istringstream ostringstream auto_ptr deque list queue stack vector map set bitset multiset multimap unordered_set unordered_map unordered_multiset unordered_multimap array shared_ptr abort abs acos asin atan2 atan calloc ceil cosh cos exit exp fabs floor fmod fprintf fputs free frexp fscanf isalnum isalpha iscntrl isdigit isgraph islower isprint ispunct isspace isupper isxdigit tolower toupper labs ldexp log10 log malloc realloc memchr memcmp memcpy memset modf pow printf putchar puts scanf sinh sin snprintf sprintf sqrt sscanf strcat strchr strcmp strcpy strcspn strlen strncat strncmp strncpy strpbrk strrchr strspn strstr tanh tan vfprintf vprintf vsprintf endl initializer_list unique_ptr",literal:"true false nullptr NULL"},n=[e,t.CLCM,t.CBCM,s,r];return{aliases:["c","cc","h","c++","h++","hpp"],k:c,i:"",k:c,c:["self",e]},{b:t.IR+"::",k:c},{v:[{b:/=/,e:/;/},{b:/\(/,e:/\)/},{bK:"new throw return else",e:/;/}],k:c,c:n.concat([{b:/\(/,e:/\)/,k:c,c:n.concat(["self"]),r:0}]),r:0},{cN:"function",b:"("+t.IR+"[\\*&\\s]+)+"+a,rB:!0,e:/[{;=]/,eE:!0,k:c,i:/[^\w\s\*&]/,c:[{b:a,rB:!0,c:[t.TM],r:0},{cN:"params",b:/\(/,e:/\)/,k:c,r:0,c:[t.CLCM,t.CBCM,r,s,e,{b:/\(/,e:/\)/,k:c,r:0,c:["self",t.CLCM,t.CBCM,r,s,e]}]},t.CLCM,t.CBCM,i]},{cN:"class",bK:"class struct",e:/[{;:]/,c:[{b://,c:["self"]},t.TM]}]),exports:{preprocessor:i,strings:r,k:c}}});hljs.registerLanguage("bash",function(e){var t={cN:"variable",v:[{b:/\$[\w\d#@][\w\d_]*/},{b:/\$\{(.*?)}/}]},s={cN:"string",b:/"/,e:/"/,c:[e.BE,t,{cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]}]};return{aliases:["sh","zsh"],l:/\b-?[a-z\._]+\b/,k:{keyword:"if then else elif fi for while in do done case esac function",literal:"true false",built_in:"break cd continue eval exec exit export getopts hash pwd readonly return shift test times trap umask unset alias bind builtin caller command declare echo enable help let local logout mapfile printf read readarray source type typeset ulimit unalias set shopt autoload bg bindkey bye cap chdir clone comparguments compcall compctl compdescribe compfiles compgroups compquote comptags comptry compvalues dirs disable disown echotc echoti emulate fc fg float functions getcap getln history integer jobs kill limit log noglob popd print pushd pushln rehash sched setcap setopt stat suspend ttyctl unfunction unhash unlimit unsetopt vared wait whence where which zcompile zformat zftp zle zmodload zparseopts zprof zpty zregexparse zsocket zstyle ztcp",_:"-ne -eq -lt -gt -f -d -e -s -l -a"},c:[{cN:"meta",b:/^#![^\n]+sh\s*$/,r:10},{cN:"function",b:/\w[\w\d_]*\s*\(\s*\)\s*\{/,rB:!0,c:[e.inherit(e.TM,{b:/\w[\w\d_]*/})],r:0},e.HCM,s,{cN:"string",b:/'/,e:/'/},t]}});hljs.registerLanguage("go",function(e){var t={keyword:"break default func interface select case map struct chan else goto package switch const fallthrough if range type continue for import return var go defer bool byte complex64 complex128 float32 float64 int8 int16 int32 int64 string uint8 uint16 uint32 uint64 int uint uintptr rune",literal:"true false iota nil",built_in:"append cap close complex copy imag len make new panic print println real recover delete"};return{aliases:["golang"],k:t,i:""); 47 | 48 | w.document.title = window.document.title; 49 | 50 | var slides = w.document.createElement('iframe'); 51 | slides.id = 'presenter-slides'; 52 | slides.src = slidesUrl; 53 | w.document.body.appendChild(slides); 54 | // setTimeout needed for Firefox 55 | setTimeout(function() { 56 | slides.focus(); 57 | }, 100); 58 | 59 | var notes = w.document.createElement('div'); 60 | notes.id = 'presenter-notes'; 61 | notes.innerHTML = formattedNotes; 62 | w.document.body.appendChild(notes); 63 | 64 | w.document.close(); 65 | 66 | function addPresenterNotesStyle() { 67 | var el = w.document.createElement('link'); 68 | el.rel = 'stylesheet'; 69 | el.type = 'text/css'; 70 | el.href = PERMANENT_URL_PREFIX + 'notes.css'; 71 | w.document.body.appendChild(el); 72 | w.document.querySelector('head').appendChild(el); 73 | } 74 | 75 | addPresenterNotesStyle(); 76 | 77 | // Add listener on notesWindow to update notes when triggered from 78 | // parent window 79 | w.addEventListener('storage', updateNotes, false); 80 | }; 81 | 82 | function formatNotes(notes) { 83 | var formattedNotes = ''; 84 | if (notes) { 85 | for (var i = 0; i < notes.length; i++) { 86 | formattedNotes = formattedNotes + '

' + notes[i] + '

'; 87 | } 88 | } 89 | return formattedNotes; 90 | }; 91 | 92 | function updateNotes() { 93 | // When triggered from parent window, notesWindow is null 94 | // The storage event listener on notesWindow will update notes 95 | if (!notesWindow) return; 96 | var destSlide = parseInt(localStorage.getItem('destSlide'), 10); 97 | var section = sections[destSlide - 1]; 98 | var el = notesWindow.document.getElementById('presenter-notes'); 99 | 100 | if (!el) return; 101 | 102 | if (section && section.Notes) { 103 | el.innerHTML = formatNotes(section.Notes); 104 | } else if (destSlide == 0) { 105 | el.innerHTML = formatNotes(titleNotes); 106 | } else { 107 | el.innerHTML = ''; 108 | } 109 | }; 110 | 111 | /* Playground syncing */ 112 | 113 | // When presenter notes are enabled, playground click handlers are 114 | // stored here to sync click events on the correct playground 115 | var playgroundHandlers = {onRun: [], onKill: [], onClose: []}; 116 | 117 | function updatePlay(e) { 118 | var i = localStorage.getItem('play-index'); 119 | 120 | switch (e.key) { 121 | case 'play-index': 122 | return; 123 | case 'play-action': 124 | // Sync 'run', 'kill', 'close' actions 125 | var action = localStorage.getItem('play-action'); 126 | playgroundHandlers[action][i](e); 127 | return; 128 | case 'play-code': 129 | // Sync code editing 130 | var play = document.querySelectorAll('div.playground')[i]; 131 | play.innerHTML = localStorage.getItem('play-code'); 132 | return; 133 | case 'output-style': 134 | // Sync resizing of playground output 135 | var out = document.querySelectorAll('.output')[i]; 136 | out.style = localStorage.getItem('output-style'); 137 | return; 138 | } 139 | }; 140 | 141 | // Reset 'run', 'kill', 'close' storage items when synced 142 | // so that successive actions can be synced correctly 143 | function updatePlayStorage(action, index, e) { 144 | localStorage.setItem('play-index', index); 145 | 146 | if (localStorage.getItem('play-action') === action) { 147 | // We're the receiving window, and the message has been received 148 | localStorage.removeItem('play-action'); 149 | } else { 150 | // We're the triggering window, send the message 151 | localStorage.setItem('play-action', action); 152 | } 153 | 154 | if (action === 'onRun') { 155 | if (localStorage.getItem('play-shiftKey') === 'true') { 156 | localStorage.removeItem('play-shiftKey'); 157 | } else if (e.shiftKey) { 158 | localStorage.setItem('play-shiftKey', e.shiftKey); 159 | } 160 | } 161 | }; 162 | -------------------------------------------------------------------------------- /themes/default/static/obsidian.css: -------------------------------------------------------------------------------- 1 | /** 2 | * Obsidian style 3 | * ported by Alexander Marenin (http://github.com/ioncreature) 4 | */ 5 | 6 | .hljs { 7 | display: block; 8 | overflow-x: auto; 9 | padding: 0.5em; 10 | background: #282b2e; 11 | } 12 | 13 | .hljs-keyword, 14 | .hljs-selector-tag, 15 | .hljs-literal, 16 | .hljs-selector-id { 17 | color: #93c763; 18 | } 19 | 20 | .hljs-number { 21 | color: #ffcd22; 22 | } 23 | 24 | .hljs { 25 | color: #e0e2e4; 26 | } 27 | 28 | .hljs-attribute { 29 | color: #668bb0; 30 | } 31 | 32 | .hljs-code, 33 | .hljs-class .hljs-title, 34 | .hljs-section { 35 | color: white; 36 | } 37 | 38 | .hljs-regexp, 39 | .hljs-link { 40 | color: #d39745; 41 | } 42 | 43 | .hljs-meta { 44 | color: #557182; 45 | } 46 | 47 | .hljs-tag, 48 | .hljs-name, 49 | .hljs-bullet, 50 | .hljs-subst, 51 | .hljs-emphasis, 52 | .hljs-type, 53 | .hljs-built_in, 54 | .hljs-selector-attr, 55 | .hljs-selector-pseudo, 56 | .hljs-addition, 57 | .hljs-variable, 58 | .hljs-template-tag, 59 | .hljs-template-variable { 60 | color: #8cbbad; 61 | } 62 | 63 | .hljs-string, 64 | .hljs-symbol { 65 | color: #ec7600; 66 | } 67 | 68 | .hljs-comment, 69 | .hljs-quote, 70 | .hljs-deletion { 71 | color: #818e96; 72 | } 73 | 74 | .hljs-selector-class { 75 | color: #A082BD 76 | } 77 | 78 | .hljs-keyword, 79 | .hljs-selector-tag, 80 | .hljs-literal, 81 | .hljs-doctag, 82 | .hljs-title, 83 | .hljs-section, 84 | .hljs-type, 85 | .hljs-name, 86 | .hljs-strong { 87 | font-weight: bold; 88 | } 89 | -------------------------------------------------------------------------------- /themes/default/static/play.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | require.config({ paths: { 'vs': 'https://unpkg.com/monaco-editor@0.16.2/min/vs' }}); 5 | // window.MonacoEnvironment = { getWorkerUrl: () => proxy }; 6 | 7 | // let proxy = URL.createObjectURL(new Blob([` 8 | // self.MonacoEnvironment = { 9 | // baseUrl: 'https://unpkg.com/monaco-editor@0.16.2/min/' 10 | // }; 11 | // importScripts('https://unpkg.com/monaco-editor@0.16.2/min/vs/base/worker/workerMain.js'); 12 | // `], { type: 'text/javascript' })); 13 | 14 | require(["vs/editor/editor.main"], function () { 15 | initPlayground(SocketTransport()); 16 | }); 17 | 18 | window.editors = [] 19 | 20 | function initPlayground(transport) { 21 | 'use strict'; 22 | 23 | function text(node) { 24 | var s = ''; 25 | for (var i = 0; i < node.childNodes.length; i++) { 26 | var n = node.childNodes[i]; 27 | if (n.nodeType === 1) { 28 | if (n.tagName === 'BUTTON') continue 29 | if (n.tagName === 'SPAN' && n.className === 'number') continue; 30 | if (n.tagName === 'DIV' || n.tagName == 'BR') { 31 | s += "\n"; 32 | } 33 | s += text(n); 34 | continue; 35 | } 36 | if (n.nodeType === 3) { 37 | s += n.nodeValue; 38 | } 39 | } 40 | return s.replace('\xA0', ' '); // replace non-breaking spaces 41 | } 42 | 43 | // When presenter notes are enabled, the index passed 44 | // here will identify the playground to be synced 45 | function init(code, index) { 46 | var output = document.createElement('div'); 47 | var outpre = document.createElement('pre'); 48 | var running; 49 | var raw = code.dataset.raw 50 | var editor = monaco.editor.create(code, { 51 | value: raw, 52 | language: 'go', 53 | // theme: 'vs', 54 | theme: 'vs-dark', 55 | // theme: 'hc-black', 56 | fontSize: 18 57 | }); 58 | window.editors.push(editor) 59 | if ($ && $(output).resizable) { 60 | $(output).resizable({ 61 | handles: 'n,w,nw', 62 | minHeight: 27, 63 | minWidth: 135, 64 | maxHeight: 608, 65 | maxWidth: 990 66 | }); 67 | } 68 | 69 | function onKill() { 70 | if (running) running.Kill(); 71 | if (window.notesEnabled) updatePlayStorage('onKill', index); 72 | } 73 | 74 | function onRun(e) { 75 | var raw = editor.getValue() 76 | var sk = e.shiftKey || localStorage.getItem('play-shiftKey') === 'true'; 77 | if (running) running.Kill(); 78 | output.style.display = 'block'; 79 | outpre.innerHTML = ''; 80 | run1.style.display = 'none'; 81 | var options = {Race: sk}; 82 | running = transport.Run(raw, PlaygroundOutput(outpre), options); 83 | // running = transport.Run(text(code), PlaygroundOutput(outpre), options); 84 | if (window.notesEnabled) updatePlayStorage('onRun', index, e); 85 | } 86 | 87 | function onClose() { 88 | if (running) running.Kill(); 89 | output.style.display = 'none'; 90 | run1.style.display = 'inline-block'; 91 | if (window.notesEnabled) updatePlayStorage('onClose', index); 92 | } 93 | 94 | if (window.notesEnabled) { 95 | playgroundHandlers.onRun.push(onRun); 96 | playgroundHandlers.onClose.push(onClose); 97 | playgroundHandlers.onKill.push(onKill); 98 | } 99 | var run1 = document.createElement('button'); 100 | run1.innerHTML = 'Run'; 101 | run1.className = 'run'; 102 | run1.addEventListener("click", onRun, false); 103 | var run2 = document.createElement('button'); 104 | run2.className = 'run'; 105 | run2.innerHTML = 'Run'; 106 | run2.addEventListener("click", onRun, false); 107 | var kill = document.createElement('button'); 108 | kill.className = 'kill'; 109 | kill.innerHTML = 'Kill'; 110 | kill.addEventListener("click", onKill, false); 111 | var close = document.createElement('button'); 112 | close.className = 'close'; 113 | close.innerHTML = 'Close'; 114 | close.addEventListener("click", onClose, false); 115 | 116 | var button = document.createElement('div'); 117 | button.classList.add('buttons'); 118 | button.appendChild(run1); 119 | // Hack to simulate insertAfter 120 | code.parentNode.insertBefore(button, code.nextSibling); 121 | 122 | var buttons = document.createElement('div'); 123 | buttons.classList.add('buttons'); 124 | buttons.appendChild(run2); 125 | buttons.appendChild(kill); 126 | buttons.appendChild(close); 127 | 128 | output.classList.add('output'); 129 | output.appendChild(buttons); 130 | output.appendChild(outpre); 131 | output.style.display = 'none'; 132 | code.parentNode.insertBefore(output, button.nextSibling); 133 | } 134 | 135 | // var play = document.querySelectorAll('div.playground'); 136 | var monacos = document.querySelectorAll(` 137 | .slides > article.past > div.my-editor, 138 | .slides > article.next > div.my-editor, 139 | .slides > article.current > div.my-editor` 140 | ) 141 | for (var i = 0; i < monacos.length; i++) { 142 | if(!monacos[i].dataset.init) 143 | init(monacos[i], i); 144 | monacos[i].dataset.init = true 145 | } 146 | } 147 | -------------------------------------------------------------------------------- /themes/default/static/playground.js: -------------------------------------------------------------------------------- 1 | // Copyright 2012 The Go Authors. All rights reserved. 2 | // Use of this source code is governed by a BSD-style 3 | // license that can be found in the LICENSE file. 4 | 5 | /* 6 | In the absence of any formal way to specify interfaces in JavaScript, 7 | here's a skeleton implementation of a playground transport. 8 | 9 | function Transport() { 10 | // Set up any transport state (eg, make a websocket connection). 11 | return { 12 | Run: function(body, output, options) { 13 | // Compile and run the program 'body' with 'options'. 14 | // Call the 'output' callback to display program output. 15 | return { 16 | Kill: function() { 17 | // Kill the running program. 18 | } 19 | }; 20 | } 21 | }; 22 | } 23 | 24 | // The output callback is called multiple times, and each time it is 25 | // passed an object of this form. 26 | var write = { 27 | Kind: 'string', // 'start', 'stdout', 'stderr', 'end' 28 | Body: 'string' // content of write or end status message 29 | } 30 | 31 | // The first call must be of Kind 'start' with no body. 32 | // Subsequent calls may be of Kind 'stdout' or 'stderr' 33 | // and must have a non-null Body string. 34 | // The final call should be of Kind 'end' with an optional 35 | // Body string, signifying a failure ("killed", for example). 36 | 37 | // The output callback must be of this form. 38 | // See PlaygroundOutput (below) for an implementation. 39 | function outputCallback(write) { 40 | } 41 | */ 42 | 43 | // HTTPTransport is the default transport. 44 | // enableVet enables running vet if a program was compiled and ran successfully. 45 | // If vet returned any errors, display them before the output of a program. 46 | function HTTPTransport(enableVet) { 47 | 'use strict'; 48 | 49 | function playback(output, data) { 50 | // Backwards compatibility: default values do not affect the output. 51 | var events = data.Events || []; 52 | var errors = data.Errors || ""; 53 | var status = data.Status || 0; 54 | var isTest = data.IsTest || false; 55 | var testsFailed = data.TestsFailed || 0; 56 | 57 | var timeout; 58 | output({Kind: 'start'}); 59 | function next() { 60 | if (!events || events.length === 0) { 61 | if (isTest) { 62 | if (testsFailed > 0) { 63 | output({Kind: 'system', Body: '\n'+testsFailed+' test'+(testsFailed>1?'s':'')+' failed.'}); 64 | } else { 65 | output({Kind: 'system', Body: '\nAll tests passed.'}); 66 | } 67 | } else { 68 | if (status > 0) { 69 | output({Kind: 'end', Body: 'status ' + status + '.'}); 70 | } else { 71 | if (errors !== "") { 72 | // errors are displayed only in the case of timeout. 73 | output({Kind: 'end', Body: errors + '.'}); 74 | } else { 75 | output({Kind: 'end'}); 76 | } 77 | } 78 | } 79 | return; 80 | } 81 | var e = events.shift(); 82 | if (e.Delay === 0) { 83 | output({Kind: e.Kind, Body: e.Message}); 84 | next(); 85 | return; 86 | } 87 | timeout = setTimeout(function() { 88 | output({Kind: e.Kind, Body: e.Message}); 89 | next(); 90 | }, e.Delay / 1000000); 91 | } 92 | next(); 93 | return { 94 | Stop: function() { 95 | clearTimeout(timeout); 96 | } 97 | }; 98 | } 99 | 100 | function error(output, msg) { 101 | output({Kind: 'start'}); 102 | output({Kind: 'stderr', Body: msg}); 103 | output({Kind: 'end'}); 104 | } 105 | 106 | function buildFailed(output, msg) { 107 | output({Kind: 'start'}); 108 | output({Kind: 'stderr', Body: msg}); 109 | output({Kind: 'system', Body: '\nGo build failed.'}); 110 | } 111 | 112 | var seq = 0; 113 | return { 114 | Run: function(body, output, options) { 115 | seq++; 116 | var cur = seq; 117 | var playing; 118 | $.ajax('/compile', { 119 | type: 'POST', 120 | data: {'version': 2, 'body': body}, 121 | dataType: 'json', 122 | success: function(data) { 123 | if (seq != cur) return; 124 | if (!data) return; 125 | if (playing != null) playing.Stop(); 126 | if (data.Errors) { 127 | if (data.Errors === 'process took too long') { 128 | // Playback the output that was captured before the timeout. 129 | playing = playback(output, data); 130 | } else { 131 | buildFailed(output, data.Errors); 132 | } 133 | return; 134 | } 135 | 136 | if (!enableVet) { 137 | playing = playback(output, data); 138 | return; 139 | } 140 | 141 | $.ajax("/vet", { 142 | data: {"body": body}, 143 | type: "POST", 144 | dataType: "json", 145 | success: function(dataVet) { 146 | if (dataVet.Errors) { 147 | if (!data.Events) { 148 | data.Events = []; 149 | } 150 | // inject errors from the vet as the first events in the output 151 | data.Events.unshift({Message: 'Go vet exited.\n\n', Kind: 'system', Delay: 0}); 152 | data.Events.unshift({Message: dataVet.Errors, Kind: 'stderr', Delay: 0}); 153 | } 154 | playing = playback(output, data); 155 | }, 156 | error: function() { 157 | playing = playback(output, data); 158 | } 159 | }); 160 | }, 161 | error: function() { 162 | error(output, 'Error communicating with remote server.'); 163 | } 164 | }); 165 | return { 166 | Kill: function() { 167 | if (playing != null) playing.Stop(); 168 | output({Kind: 'end', Body: 'killed'}); 169 | } 170 | }; 171 | } 172 | }; 173 | } 174 | 175 | function SocketTransport() { 176 | 'use strict'; 177 | 178 | var id = 0; 179 | var outputs = {}; 180 | var started = {}; 181 | var websocket; 182 | var websocketDisabled = false; 183 | if (window.location.protocol == "http:") { 184 | websocket = new WebSocket('ws://' + window.location.host + '/socket'); 185 | } else if (window.location.protocol == "https:") { 186 | websocket = new WebSocket('wss://' + window.location.host + '/socket'); 187 | } else { 188 | websocketDisabled = true 189 | console.log("Static page mode:") 190 | console.log("No backend service provided.") 191 | console.log("Live demo and websocket are closed.") 192 | } 193 | 194 | if(!websocketDisabled) { 195 | websocket.onclose = function() { 196 | console.log('websocket connection closed'); 197 | }; 198 | 199 | websocket.onmessage = function(e) { 200 | var m = JSON.parse(e.data); 201 | var output = outputs[m.Id]; 202 | if (output === null) 203 | return; 204 | if (!started[m.Id]) { 205 | output({Kind: 'start'}); 206 | started[m.Id] = true; 207 | } 208 | output({Kind: m.Kind, Body: m.Body}); 209 | }; 210 | } 211 | 212 | 213 | function send(m) { 214 | if(!websocketDisabled) 215 | websocket.send(JSON.stringify(m)); 216 | } 217 | 218 | return { 219 | Run: function(body, output, options) { 220 | var thisID = id+''; 221 | id++; 222 | outputs[thisID] = output; 223 | send({Id: thisID, Kind: 'run', Body: body, Options: options}); 224 | return { 225 | Kill: function() { 226 | send({Id: thisID, Kind: 'kill'}); 227 | } 228 | }; 229 | } 230 | }; 231 | } 232 | 233 | function PlaygroundOutput(el) { 234 | 'use strict'; 235 | 236 | return function(write) { 237 | if (write.Kind == 'start') { 238 | el.innerHTML = ''; 239 | return; 240 | } 241 | 242 | var cl = 'system'; 243 | if (write.Kind == 'stdout' || write.Kind == 'stderr') 244 | cl = write.Kind; 245 | 246 | var m = write.Body; 247 | if (write.Kind == 'end') { 248 | m = '\nProgram exited' + (m?(': '+m):'.'); 249 | } 250 | 251 | if (m.indexOf('IMAGE:') === 0) { 252 | // TODO(adg): buffer all writes before creating image 253 | var url = 'data:image/png;base64,' + m.substr(6); 254 | var img = document.createElement('img'); 255 | img.src = url; 256 | el.appendChild(img); 257 | return; 258 | } 259 | 260 | // ^L clears the screen. 261 | var s = m.split('\x0c'); 262 | if (s.length > 1) { 263 | el.innerHTML = ''; 264 | m = s.pop(); 265 | } 266 | 267 | m = m.replace(/&/g, '&'); 268 | m = m.replace(//g, '>'); 270 | 271 | var needScroll = (el.scrollTop + el.offsetHeight) == el.scrollHeight; 272 | 273 | var span = document.createElement('span'); 274 | span.className = cl; 275 | span.innerHTML = m; 276 | el.appendChild(span); 277 | 278 | if (needScroll) 279 | el.scrollTop = el.scrollHeight - el.offsetHeight; 280 | }; 281 | } 282 | 283 | (function() { 284 | function lineHighlight(error) { 285 | var regex = /prog.go:([0-9]+)/g; 286 | var r = regex.exec(error); 287 | while (r) { 288 | $(".lines div").eq(r[1]-1).addClass("lineerror"); 289 | r = regex.exec(error); 290 | } 291 | } 292 | function highlightOutput(wrappedOutput) { 293 | return function(write) { 294 | if (write.Body) lineHighlight(write.Body); 295 | wrappedOutput(write); 296 | }; 297 | } 298 | function lineClear() { 299 | $(".lineerror").removeClass("lineerror"); 300 | } 301 | 302 | // opts is an object with these keys 303 | // codeEl - code editor element 304 | // outputEl - program output element 305 | // runEl - run button element 306 | // fmtEl - fmt button element (optional) 307 | // fmtImportEl - fmt "imports" checkbox element (optional) 308 | // shareEl - share button element (optional) 309 | // shareURLEl - share URL text input element (optional) 310 | // shareRedirect - base URL to redirect to on share (optional) 311 | // toysEl - toys select element (optional) 312 | // enableHistory - enable using HTML5 history API (optional) 313 | // transport - playground transport to use (default is HTTPTransport) 314 | // enableShortcuts - whether to enable shortcuts (Ctrl+S/Cmd+S to save) (default is false) 315 | // enableVet - enable running vet and displaying its errors 316 | function playground(opts) { 317 | var code = $(opts.codeEl); 318 | var transport = opts['transport'] || new HTTPTransport(opts['enableVet']); 319 | var running; 320 | 321 | // autoindent helpers. 322 | function insertTabs(n) { 323 | // find the selection start and end 324 | var start = code[0].selectionStart; 325 | var end = code[0].selectionEnd; 326 | // split the textarea content into two, and insert n tabs 327 | var v = code[0].value; 328 | var u = v.substr(0, start); 329 | for (var i=0; i 0) { 343 | curpos--; 344 | if (el.value[curpos] == "\t") { 345 | tabs++; 346 | } else if (tabs > 0 || el.value[curpos] == "\n") { 347 | break; 348 | } 349 | } 350 | setTimeout(function() { 351 | insertTabs(tabs); 352 | }, 1); 353 | } 354 | 355 | // NOTE(cbro): e is a jQuery event, not a DOM event. 356 | function handleSaveShortcut(e) { 357 | if (e.isDefaultPrevented()) return false; 358 | if (!e.metaKey && !e.ctrlKey) return false; 359 | if (e.key != "S" && e.key != "s") return false; 360 | 361 | e.preventDefault(); 362 | 363 | // Share and save 364 | share(function(url) { 365 | window.location.href = url + ".go?download=true"; 366 | }); 367 | 368 | return true; 369 | } 370 | 371 | function keyHandler(e) { 372 | if (opts.enableShortcuts && handleSaveShortcut(e)) return; 373 | 374 | if (e.keyCode == 9 && !e.ctrlKey) { // tab (but not ctrl-tab) 375 | insertTabs(1); 376 | e.preventDefault(); 377 | return false; 378 | } 379 | if (e.keyCode == 13) { // enter 380 | if (e.shiftKey) { // +shift 381 | run(); 382 | e.preventDefault(); 383 | return false; 384 | } if (e.ctrlKey) { // +control 385 | fmt(); 386 | e.preventDefault(); 387 | } else { 388 | autoindent(e.target); 389 | } 390 | } 391 | return true; 392 | } 393 | code.unbind('keydown').bind('keydown', keyHandler); 394 | var outdiv = $(opts.outputEl).empty(); 395 | var output = $('
').appendTo(outdiv);
396 | 
397 |     function body() {
398 |       return $(opts.codeEl).val();
399 |     }
400 |     function setBody(text) {
401 |       $(opts.codeEl).val(text);
402 |     }
403 |     function origin(href) {
404 |       return (""+href).split("/").slice(0, 3).join("/");
405 |     }
406 | 
407 |     var pushedEmpty = (window.location.pathname == "/");
408 |     function inputChanged() {
409 |       if (pushedEmpty) {
410 |         return;
411 |       }
412 |       pushedEmpty = true;
413 |       $(opts.shareURLEl).hide();
414 |       window.history.pushState(null, "", "/");
415 |     }
416 |     function popState(e) {
417 |       if (e === null) {
418 |         return;
419 |       }
420 |       if (e && e.state && e.state.code) {
421 |         setBody(e.state.code);
422 |       }
423 |     }
424 |     var rewriteHistory = false;
425 |     if (window.history && window.history.pushState && window.addEventListener && opts.enableHistory) {
426 |       rewriteHistory = true;
427 |       code[0].addEventListener('input', inputChanged);
428 |       window.addEventListener('popstate', popState);
429 |     }
430 | 
431 |     function setError(error) {
432 |       if (running) running.Kill();
433 |       lineClear();
434 |       lineHighlight(error);
435 |       output.empty().addClass("error").text(error);
436 |     }
437 |     function loading() {
438 |       lineClear();
439 |       if (running) running.Kill();
440 |       output.removeClass("error").text('Waiting for remote server...');
441 |     }
442 |     function run() {
443 |       loading();
444 |       running = transport.Run(body(), highlightOutput(PlaygroundOutput(output[0])));
445 |     }
446 | 
447 |     function fmt() {
448 |       loading();
449 |       var data = {"body": body()};
450 |       if ($(opts.fmtImportEl).is(":checked")) {
451 |         data["imports"] = "true";
452 |       }
453 |       $.ajax("/fmt", {
454 |         data: data,
455 |         type: "POST",
456 |         dataType: "json",
457 |         success: function(data) {
458 |           if (data.Error) {
459 |             setError(data.Error);
460 |           } else {
461 |             setBody(data.Body);
462 |             setError("");
463 |           }
464 |         }
465 |       });
466 |     }
467 | 
468 |     var shareURL; // jQuery element to show the shared URL.
469 |     var sharing = false; // true if there is a pending request.
470 |     var shareCallbacks = [];
471 |     function share(opt_callback) {
472 |       if (opt_callback) shareCallbacks.push(opt_callback);
473 | 
474 |       if (sharing) return;
475 |       sharing = true;
476 | 
477 |       var sharingData = body();
478 |       $.ajax("/share", {
479 |         processData: false,
480 |         data: sharingData,
481 |         type: "POST",
482 |         contentType: "text/plain; charset=utf-8",
483 |         complete: function(xhr) {
484 |           sharing = false;
485 |           if (xhr.status != 200) {
486 |             alert("Server error; try again.");
487 |             return;
488 |           }
489 |           if (opts.shareRedirect) {
490 |             window.location = opts.shareRedirect + xhr.responseText;
491 |           }
492 |           var path = "/p/" + xhr.responseText;
493 |           var url = origin(window.location) + path;
494 | 
495 |           for (var i = 0; i < shareCallbacks.length; i++) {
496 |             shareCallbacks[i](url);
497 |           }
498 |           shareCallbacks = [];
499 | 
500 |           if (shareURL) {
501 |             shareURL.show().val(url).focus().select();
502 | 
503 |             if (rewriteHistory) {
504 |               var historyData = {"code": sharingData};
505 |               window.history.pushState(historyData, "", path);
506 |               pushedEmpty = false;
507 |             }
508 |           }
509 |         }
510 |       });
511 |     }
512 | 
513 |     $(opts.runEl).click(run);
514 |     $(opts.fmtEl).click(fmt);
515 | 
516 |     if (opts.shareEl !== null && (opts.shareURLEl !== null || opts.shareRedirect !== null)) {
517 |       if (opts.shareURLEl) {
518 |         shareURL = $(opts.shareURLEl).hide();
519 |       }
520 |       $(opts.shareEl).click(function() {
521 |         share();
522 |       });
523 |     }
524 | 
525 |     if (opts.toysEl !== null) {
526 |       $(opts.toysEl).bind('change', function() {
527 |         var toy = $(this).val();
528 |         $.ajax("/doc/play/"+toy, {
529 |           processData: false,
530 |           type: "GET",
531 |           complete: function(xhr) {
532 |             if (xhr.status != 200) {
533 |               alert("Server error; try again.");
534 |               return;
535 |             }
536 |             setBody(xhr.responseText);
537 |           }
538 |         });
539 |       });
540 |     }
541 |   }
542 | 
543 |   window.playground = playground;
544 | })();
545 | 


--------------------------------------------------------------------------------
/themes/default/static/styles.css:
--------------------------------------------------------------------------------
  1 | :root {
  2 |   /* --background-color: rgb(215, 215, 215); */
  3 |   --background-color: #555;
  4 |   --article-bg-color: #1e1e1e;
  5 |   --article-title-padding: 20px 0px 30px 20px;
  6 |   --font-color: #ccc;
  7 |   --codeblocks-height: 75%;
  8 |   --kktix-green: #64c025;
  9 |   --kktix-darkgreen: #436929;
 10 |   --border-first-color: var(--kktix-green);
 11 |   --border-second-color: var(--kktix-darkgreen);
 12 |   --footer-first-color: #333;
 13 |   --footer-second-color: #333;
 14 |   --border-top-width: 8px;
 15 |   --border-bottom-width: 8px;
 16 |   --footer-border-height: var(--border-bottom-width);
 17 |   --border-top-image: linear-gradient(to right, 
 18 |   var(--border-first-color) 33%, 
 19 |   var(--border-second-color) 33%, 
 20 |   var(--border-second-color) 66%, 
 21 |   var(--border-first-color) 66%, 
 22 |   var(--border-first-color) 100%) 8 0 0 0;
 23 |   --footer-border-color: linear-gradient(to right, 
 24 |   var(--footer-first-color) 33%, 
 25 |   var(--footer-second-color) 33%, 
 26 |   var(--footer-second-color) 66%, 
 27 |   var(--footer-first-color) 66%, 
 28 |   var(--footer-first-color) 100%);
 29 |   --letter-spacing: 2px;
 30 |   --slogan-font-size: 45px;
 31 | }
 32 | 
 33 | @media screen {
 34 |   /* Framework */
 35 |   html {
 36 |     height: 100%;
 37 |   }
 38 | 
 39 |   body {
 40 |     margin: 0;
 41 |     padding: 0;
 42 | 
 43 |     display: block !important;
 44 |     height: 100%;
 45 |     height: 100vh;
 46 | 
 47 |     overflow: hidden;
 48 |     /* background: white; */
 49 |     background: var(--background-color); 
 50 |     /* background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
 51 |     background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
 52 |     background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190));
 53 |     background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190))); */
 54 | 
 55 |     -webkit-font-smoothing: antialiased;
 56 |   }
 57 | 
 58 |   /* 這行必需要加,不然 editor 會出不來 */
 59 |   .my-editor {
 60 |     /* position: absolute; */
 61 |     /* display: block !important; */
 62 |     left: 0;
 63 |     top: 0;
 64 |     width: 100%;
 65 |     height: var(--codeblocks-height);
 66 |     margin: 0;
 67 |     padding: 0;
 68 |     /* overflow: hidden; */
 69 |   }
 70 |   .article-footer {
 71 |     width: 100%;
 72 |     height: var(--footer-border-height);
 73 |     background-image: var(--footer-border-color);
 74 |     position: absolute;
 75 |     bottom: 0;
 76 |     left: 0;
 77 |     right: 0;
 78 |   }
 79 |   .slides {
 80 |     width: 100%;
 81 |     height: 100%;
 82 |     left: 0;
 83 |     top: 0;
 84 | 
 85 |     position: absolute;
 86 | 
 87 |     -webkit-transform: translate3d(0, 0, 0);
 88 |   }
 89 | 
 90 |   .slides > article {
 91 |     display: block;
 92 | 
 93 |     position: absolute;
 94 |     overflow: hidden;
 95 | 
 96 |     width: 900px;
 97 |     height: 700px;
 98 | 
 99 |     left: 50%;
100 |     top: 50%;
101 | 
102 |     margin-left: -450px;
103 |     margin-top: -350px;
104 | 
105 |     padding: 40px 60px var(--footer-border-height);
106 | 
107 |     box-sizing: border-box;
108 |     -o-box-sizing: border-box;
109 |     -moz-box-sizing: border-box;
110 |     -webkit-box-sizing: border-box;
111 | 
112 |     border-top: var(--border-top-width) solid;
113 |     border-image: var(--border-top-image);
114 |     
115 |     background-color: var(--article-bg-color);
116 | 
117 |     /* border: 1px solid rgba(0, 0, 0, .3); */
118 | 
119 |     /* transition: transform .3s ease-out;
120 |     -o-transition: -o-transform .3s ease-out;
121 |     -moz-transition: -moz-transform .3s ease-out;
122 |     -webkit-transition: -webkit-transform .3s ease-out; */
123 |   }
124 |   .slides.layout-widescreen > article {
125 |     margin-left: -550px;
126 |     width: 1100px;
127 |   }
128 |   .slides.layout-faux-widescreen > article {
129 |     margin-left: -550px;
130 |     width: 1100px;
131 | 
132 |     padding: 40px 160px;
133 |   }
134 | 
135 |   .slides.layout-widescreen > article:not(.nobackground):not(.biglogo),
136 |   .slides.layout-faux-widescreen > article:not(.nobackground):not(.biglogo) {
137 |     background-position-x: 0, 840px;
138 |   }
139 | 
140 |   /* Clickable/tappable areas */
141 | 
142 |   .slide-area {
143 |     z-index: 1000;
144 | 
145 |     position: absolute;
146 |     left: 0;
147 |     top: 0;
148 |     width: 150px;
149 |     height: 700px;
150 | 
151 |     left: 50%;
152 |     top: 50%;
153 | 
154 |     cursor: pointer;
155 |     margin-top: -350px;
156 | 
157 |     tap-highlight-color: transparent;
158 |     -o-tap-highlight-color: transparent;
159 |     -moz-tap-highlight-color: transparent;
160 |     -webkit-tap-highlight-color: transparent;
161 |   }
162 |   #prev-slide-area {
163 |     margin-left: -550px;
164 |   }
165 |   #next-slide-area {
166 |     margin-left: 400px;
167 |   }
168 |   .slides.layout-widescreen #prev-slide-area,
169 |   .slides.layout-faux-widescreen #prev-slide-area {
170 |     margin-left: -650px;
171 |   }
172 |   .slides.layout-widescreen #next-slide-area,
173 |   .slides.layout-faux-widescreen #next-slide-area {
174 |     margin-left: 500px;
175 |   }
176 | 
177 |   /* Slides */
178 | 
179 |   .slides > article {
180 |     display: none;
181 |   }
182 |   /* .slides > article.slide-hide {
183 |     display: none;
184 |   } */
185 |   .slides > article.far-past {
186 |     display: block;
187 |     transform: translate(-2040px);
188 |     -o-transform: translate(-2040px);
189 |     -moz-transform: translate(-2040px);
190 |     -webkit-transform: translate3d(-2040px, 0, 0);
191 |   }
192 |   .slides > article.past {
193 |     display: block;
194 |     transform: translate(-1020px);
195 |     -o-transform: translate(-1020px);
196 |     -moz-transform: translate(-1020px);
197 |     -webkit-transform: translate3d(-1020px, 0, 0);
198 |   }
199 |   .slides > article.current {
200 |     display: block;
201 |     transform: translate(0);
202 |     -o-transform: translate(0);
203 |     -moz-transform: translate(0);
204 |     -webkit-transform: translate3d(0, 0, 0);
205 |   }
206 |   .slides > article.next {
207 |     display: block;
208 |     transform: translate(1020px);
209 |     -o-transform: translate(1020px);
210 |     -moz-transform: translate(1020px);
211 |     -webkit-transform: translate3d(1020px, 0, 0);
212 |   }
213 |   .slides > article.far-next {
214 |     display: block;
215 |     transform: translate(2040px);
216 |     -o-transform: translate(2040px);
217 |     -moz-transform: translate(2040px);
218 |     -webkit-transform: translate3d(2040px, 0, 0);
219 |   }
220 | 
221 |   .slides.layout-widescreen > article.far-past,
222 |   .slides.layout-faux-widescreen > article.far-past {
223 |     display: block;
224 |     transform: translate(-2260px);
225 |     -o-transform: translate(-2260px);
226 |     -moz-transform: translate(-2260px);
227 |     -webkit-transform: translate3d(-2260px, 0, 0);
228 |   }
229 |   .slides.layout-widescreen > article.past,
230 |   .slides.layout-faux-widescreen > article.past {
231 |     display: block;
232 |     transform: translate(-1130px);
233 |     -o-transform: translate(-1130px);
234 |     -moz-transform: translate(-1130px);
235 |     -webkit-transform: translate3d(-1130px, 0, 0);
236 |   }
237 |   .slides.layout-widescreen > article.current,
238 |   .slides.layout-faux-widescreen > article.current {
239 |     display: block;
240 |     transform: translate(0);
241 |     -o-transform: translate(0);
242 |     -moz-transform: translate(0);
243 |     -webkit-transform: translate3d(0, 0, 0);
244 |   }
245 |   .slides.layout-widescreen > article.next,
246 |   .slides.layout-faux-widescreen > article.next {
247 |     display: block;
248 |     transform: translate(1130px);
249 |     -o-transform: translate(1130px);
250 |     -moz-transform: translate(1130px);
251 |     -webkit-transform: translate3d(1130px, 0, 0);
252 |   }
253 |   .slides.layout-widescreen > article.far-next,
254 |   .slides.layout-faux-widescreen > article.far-next {
255 |     display: block;
256 |     transform: translate(2260px);
257 |     -o-transform: translate(2260px);
258 |     -moz-transform: translate(2260px);
259 |     -webkit-transform: translate3d(2260px, 0, 0);
260 |   }
261 | }
262 | 
263 | @media print {
264 |   /* Set page layout */
265 |   @page {
266 |     size: A4 landscape;
267 |   }
268 | 
269 |   body {
270 |     display: block !important;
271 |   }
272 | 
273 |   .slides > article {
274 |     display: block;
275 | 
276 |     position: relative;
277 | 
278 |     page-break-inside: never;
279 |     page-break-after: always;
280 | 
281 |     overflow: hidden;
282 |   }
283 | 
284 |   /* div.code {
285 |     background: rgb(240, 240, 240);
286 |   } */
287 | 
288 |   /* Add explicit links */
289 |   a:link:after, a:visited:after {
290 |    content: " (" attr(href) ") ";
291 |    font-size: 50%;
292 |   }
293 | 
294 |   #help {
295 |     display: none;
296 |     visibility: hidden;
297 |   }
298 | }
299 | 
300 | /* Styles for slides */
301 | 
302 | .slides > article {
303 |   /* font-family: 'Open Sans', Arial, sans-serif; */
304 |   font-family: Arial, sans-serif;
305 | 
306 |   color: var(--font-color);
307 |   /* text-shadow: 0 1px 1px rgba(0, 0, 0, .1); */
308 | 
309 |   font-size: 26px;
310 |   line-height: 36px;
311 | }
312 | 
313 | b {
314 |   font-weight: 600;
315 | }
316 | 
317 | a {
318 |   color: rgb(0, 102, 204);
319 |   text-decoration: none;
320 | }
321 | a:visited {
322 |   color: rgba(0, 102, 204, .75);
323 | }
324 | a:hover {
325 |   color: black;
326 | }
327 | 
328 | article.background {
329 |   background-size: contain;
330 |   background-repeat: round;
331 | }
332 | 
333 | .pagenumber {
334 |   color: var(--font-color);
335 |   font-size: 75%;
336 |   position: absolute;
337 |   bottom: 0px;
338 |   right: 10px;
339 | }
340 | 
341 | /* Code */
342 | 
343 | div.playground {
344 |   position: relative;
345 | }
346 | div.output {
347 |   position: absolute;
348 |   left: 50%;
349 |   top: 50%;
350 |   right: 40px;
351 |   bottom: 40px;
352 |   background: #202020;
353 |   padding: 5px 10px;
354 |   z-index: 2;
355 | 
356 |   border-radius: 10px;
357 |   -o-border-radius: 10px;
358 |   -moz-border-radius: 10px;
359 |   -webkit-border-radius: 10px;
360 | 
361 | }
362 | div.output pre {
363 |   margin: 0;
364 |   padding: 0;
365 |   background: none;
366 |   border: none;
367 |   width: 100%;
368 |   height: 100%;
369 |   overflow: auto;
370 | }
371 | div.output .stdout, div.output pre {
372 |   color: #e6e6e6;
373 | }
374 | div.output .stderr, div.output .error {
375 |   color: rgb(255, 200, 200);
376 | }
377 | div.output .system, div.output .exit {
378 |   color: rgb(255, 230, 120)
379 | }
380 | .buttons {
381 |   position: relative;
382 |   float: right;
383 |   top: -60px;
384 |   right: 10px;
385 | }
386 | div.output .buttons {
387 |   position: absolute;
388 |   float: none;
389 |   top: auto;
390 |   right: 5px;
391 |   bottom: 5px;
392 | }
393 | 
394 | /* Presenter details */
395 | .presenter {
396 |   margin-top: 20px;
397 | }
398 | .presenter p,
399 | .presenter .link {
400 |   margin: 0;
401 |   font-size: 28px;
402 |   line-height: 1.2em;
403 | }
404 | 
405 | /* Output resize details */
406 | .ui-resizable-handle {
407 |   position: absolute;
408 | }
409 | .ui-resizable-n {
410 |   cursor: n-resize;
411 |   height: 7px;
412 |   width: 100%;
413 |   top: -5px;
414 |   left: 0;
415 | }
416 | .ui-resizable-w {
417 |   cursor: w-resize;
418 |   width: 7px;
419 |   left: -5px;
420 |   top: 0;
421 |   height: 100%;
422 | }
423 | .ui-resizable-nw {
424 |   cursor: nw-resize;
425 |   width: 9px;
426 |   height: 9px;
427 |   left: -5px;
428 |   top: -5px;
429 | }
430 | iframe {
431 |   border: none;
432 | }
433 | figcaption {
434 |   color: #666;
435 |   text-align: center;
436 |   font-size: 0.75em;
437 | }
438 | 
439 | #help {
440 |   display: none;
441 |   font-family: 'Open Sans', Arial, sans-serif;
442 |   text-align: center;
443 |   color: white;
444 |   background: #000;
445 |   opacity: 0.5;
446 |   position: fixed;
447 |   bottom: 25px;
448 |   left: 50px;
449 |   right: 50px;
450 |   padding: 20px;
451 | 
452 |   border-radius: 10px;
453 |   -o-border-radius: 10px;
454 |   -moz-border-radius: 10px;
455 |   -webkit-border-radius: 10px;
456 | }
457 | 
458 | .article-title {
459 |   font-size: 42px;
460 |   padding: 0;
461 |   margin: 0;
462 |   padding: var(--article-title-padding);
463 |   font-weight: 600;
464 |   color: var(--font-color)
465 | }
466 | 
467 | .slogan {
468 |   text-align: center;
469 |   color: var(--font-color);
470 |   font-size: var(--slogan-font-size);
471 | }
472 | 
473 | .slogan-10 {
474 |   padding-top: 10%;
475 | }
476 | 
477 | .slogan-15 {
478 |   padding-top: 15%;
479 | }
480 | 
481 | .bold {
482 |   font-weight: 600;
483 | }
484 | 
485 | .content {
486 |   padding-top: 20px;
487 |   padding-left: 50px;
488 | }
489 | 
490 | ul {
491 |   margin: 0;
492 |   padding: 0;
493 |   margin-top: 20px;
494 |   margin-left: 1.5em;
495 | }
496 | 
497 | li {
498 |   padding: 0;
499 |   margin: 0 0 .5em 0;
500 | }
501 | 
502 | .landing-title {
503 |   font-size: 60px;
504 |   line-height: 100px;
505 | 
506 |   padding: 0;
507 |   padding-top: 200px;
508 |   padding-right: 40px;
509 | 
510 |   font-weight: 600;
511 | 
512 |   color: var(--font-color);
513 | }
514 | 
515 | /* table {
516 |   width: 100%;
517 |   border-collapse: collapse;
518 |   margin-top: 40px;
519 | }
520 | th {
521 |   font-weight: 600;
522 |   text-align: left;
523 | }
524 | td,
525 | th {
526 |   border: 1px solid rgb(224, 224, 224);
527 |   padding: 5px 10px;
528 |   vertical-align: top;
529 | } */
530 | 
531 | 
532 | .embeded-gist {
533 |   overflow-y: scroll;
534 |   height: 60%;
535 |   width: 100%;
536 |   padding:0;
537 |   margin: 0 auto;
538 | }
539 | 
540 | code {
541 |   /* font-family: 'Open Sans', Arial, sans-serif !important; */
542 |   font-family: Menlo, Monaco, "Courier New", monospace !important;
543 | }
544 | 
545 | .code {
546 |   overflow-y: scroll;
547 |   height: auto;
548 |   max-height: 85%;
549 |   width: 100%;
550 |   padding: 0;
551 |   margin: 0;
552 |   
553 | }
554 | 
555 | .code18 {
556 |   font-size: 18px;
557 |   line-height: 27px;
558 | }
559 | 
560 | .code20 {
561 |   font-size: 20px;
562 |   line-height: 29px;
563 | }
564 | 
565 | .code22 {
566 |   font-size: 22px;
567 |   line-height: 31px;
568 | }
569 | 
570 | .hljs {
571 |   padding: 0px 10px 10px 30px !important;
572 |   margin-top: -20px !important;
573 | }
574 | 
575 | .code pre {
576 |   padding: 0;
577 |   margin: 0;
578 | }
579 | 
580 | .code code {
581 |   padding: 0;
582 |   margin: 0;
583 | }
584 | 
585 | .h75 {
586 |   height: 75%;
587 | }
588 | 
589 | .h70 {
590 |   height: 70%;
591 | }
592 | 
593 | .h65 {
594 |   height: 65%;
595 | }
596 | 
597 | .h60 {
598 |   height: 60%;
599 | }
600 | 
601 | .h55 {
602 |   height: 55%;
603 | }
604 | 
605 | .h50 {
606 |   height: 50%;
607 | }
608 | 
609 | .f20 {
610 |   font-size: 20px;
611 |   line-height: 22px;
612 | }
613 | 
614 | ::selection {
615 |   background: #f5e3a6;
616 |   color: #fff;
617 | }
618 | 
619 | /* pre {
620 |   margin: 0;
621 |   padding: 0;
622 | 
623 |   font-family: 'Droid Sans Mono', 'Courier New', monospace;
624 |   font-size: 18px;
625 |   line-height: 24px;
626 | 
627 |   color: black;
628 | }
629 | 
630 | pre.numbers span:before {
631 |   content: attr(num);
632 |   margin-right: 1em;
633 |   display: inline-block;
634 | } */
635 | 
636 | /* code {
637 |   font-size: 95%;
638 |   font-family: 'Droid Sans Mono', 'Courier New', monospace;
639 | 
640 |   color: black;
641 | } */
642 | 
643 | article > .image,
644 | article > .video {
645 |   text-align: center;
646 | }
647 | 
648 | /* div.code {
649 |   padding: 5px 10px;
650 |   margin-top: 20px;
651 |   margin-bottom: 20px;
652 |   overflow: hidden;
653 |   overflow-y:scroll; 
654 |   height: var(--codeblocks-height);
655 | 
656 |   background: rgb(240, 240, 240);
657 |   border: 1px solid rgb(224, 224, 224);
658 | }
659 | div.code {
660 |   outline: 0px solid transparent;
661 | } */
662 | 
663 | .codeblock {
664 |   margin: 0px 0px 0px 0px;
665 |   padding: 0px 0px 0px 0px;
666 | }


--------------------------------------------------------------------------------
/themes/default/static/template.css:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Visual Studio 2015 dark style
  3 |  * Author: Nicolas LLOBERA 
  4 |  */
  5 | 
  6 | .hljs {
  7 |   display: block;
  8 |   overflow-x: auto;
  9 |   padding: 0.5em;
 10 |   background: #1E1E1E;
 11 |   color: #DCDCDC;
 12 | }
 13 | 
 14 | .hljs-keyword,
 15 | .hljs-literal,
 16 | .hljs-symbol,
 17 | .hljs-name {
 18 |   color: #569CD6;
 19 | }
 20 | .hljs-link {
 21 |   color: #569CD6;
 22 |   text-decoration: underline;
 23 | }
 24 | 
 25 | .hljs-built_in,
 26 | .hljs-type {
 27 |   color: #4EC9B0;
 28 | }
 29 | 
 30 | .hljs-number,
 31 | .hljs-class {
 32 |   color: #B8D7A3;
 33 | }
 34 | 
 35 | .hljs-string,
 36 | .hljs-meta-string {
 37 |   color: #D69D85;
 38 | }
 39 | 
 40 | .hljs-regexp,
 41 | .hljs-template-tag {
 42 |   color: #9A5334;
 43 | }
 44 | 
 45 | .hljs-subst,
 46 | .hljs-function,
 47 | .hljs-title,
 48 | .hljs-params,
 49 | .hljs-formula {
 50 |   color: #DCDCDC;
 51 | }
 52 | 
 53 | .hljs-comment,
 54 | .hljs-quote {
 55 |   color: #57A64A;
 56 |   font-style: italic;
 57 | }
 58 | 
 59 | .hljs-doctag {
 60 |   color: #608B4E;
 61 | }
 62 | 
 63 | .hljs-meta,
 64 | .hljs-meta-keyword,
 65 | .hljs-tag {
 66 |   color: #9B9B9B;
 67 | }
 68 | 
 69 | .hljs-variable,
 70 | .hljs-template-variable {
 71 |   color: #BD63C5;
 72 | }
 73 | 
 74 | .hljs-attr,
 75 | .hljs-attribute,
 76 | .hljs-builtin-name {
 77 |   color: #9CDCFE;
 78 | }
 79 | 
 80 | .hljs-section {
 81 |   color: gold;
 82 | }
 83 | 
 84 | .hljs-emphasis {
 85 |   font-style: italic;
 86 | }
 87 | 
 88 | .hljs-strong {
 89 |   font-weight: bold;
 90 | }
 91 | 
 92 | /*.hljs-code {
 93 |   font-family:'Monospace';
 94 | }*/
 95 | 
 96 | .hljs-bullet,
 97 | .hljs-selector-tag,
 98 | .hljs-selector-id,
 99 | .hljs-selector-class,
100 | .hljs-selector-attr,
101 | .hljs-selector-pseudo {
102 |   color: #D7BA7D;
103 | }
104 | 
105 | .hljs-addition {
106 |   background-color: #144212;
107 |   display: inline-block;
108 |   width: 100%;
109 | }
110 | 
111 | .hljs-deletion {
112 |   background-color: #600;
113 |   display: inline-block;
114 |   width: 100%;
115 | }
116 | 


--------------------------------------------------------------------------------
/themes/default/static/vs2015.css:
--------------------------------------------------------------------------------
  1 | /*
  2 |  * Visual Studio 2015 dark style
  3 |  * Author: Nicolas LLOBERA 
  4 |  */
  5 | 
  6 | .hljs {
  7 |   display: block;
  8 |   overflow-x: auto;
  9 |   padding: 0.5em;
 10 |   background: #1E1E1E;
 11 |   color: #DCDCDC;
 12 | }
 13 | 
 14 | .hljs-keyword,
 15 | .hljs-literal,
 16 | .hljs-symbol,
 17 | .hljs-name {
 18 |   color: #569CD6;
 19 | }
 20 | .hljs-link {
 21 |   color: #569CD6;
 22 |   text-decoration: underline;
 23 | }
 24 | 
 25 | .hljs-built_in,
 26 | .hljs-type {
 27 |   color: #4EC9B0;
 28 | }
 29 | 
 30 | .hljs-number,
 31 | .hljs-class {
 32 |   color: #B8D7A3;
 33 | }
 34 | 
 35 | .hljs-string,
 36 | .hljs-meta-string {
 37 |   color: #D69D85;
 38 | }
 39 | 
 40 | .hljs-regexp,
 41 | .hljs-template-tag {
 42 |   color: #9A5334;
 43 | }
 44 | 
 45 | .hljs-subst,
 46 | .hljs-function,
 47 | .hljs-title,
 48 | .hljs-params,
 49 | .hljs-formula {
 50 |   color: #DCDCDC;
 51 | }
 52 | 
 53 | .hljs-comment,
 54 | .hljs-quote {
 55 |   color: #57A64A;
 56 |   font-style: italic;
 57 | }
 58 | 
 59 | .hljs-doctag {
 60 |   color: #608B4E;
 61 | }
 62 | 
 63 | .hljs-meta,
 64 | .hljs-meta-keyword,
 65 | .hljs-tag {
 66 |   color: #9B9B9B;
 67 | }
 68 | 
 69 | .hljs-variable,
 70 | .hljs-template-variable {
 71 |   color: #BD63C5;
 72 | }
 73 | 
 74 | .hljs-attr,
 75 | .hljs-attribute,
 76 | .hljs-builtin-name {
 77 |   color: #9CDCFE;
 78 | }
 79 | 
 80 | .hljs-section {
 81 |   color: gold;
 82 | }
 83 | 
 84 | .hljs-emphasis {
 85 |   font-style: italic;
 86 | }
 87 | 
 88 | .hljs-strong {
 89 |   font-weight: bold;
 90 | }
 91 | 
 92 | /*.hljs-code {
 93 |   font-family:'Monospace';
 94 | }*/
 95 | 
 96 | .hljs-bullet,
 97 | .hljs-selector-tag,
 98 | .hljs-selector-id,
 99 | .hljs-selector-class,
100 | .hljs-selector-attr,
101 | .hljs-selector-pseudo {
102 |   color: #D7BA7D;
103 | }
104 | 
105 | .hljs-addition {
106 |   background-color: #144212;
107 |   display: inline-block;
108 |   width: 100%;
109 | }
110 | 
111 | .hljs-deletion {
112 |   background-color: #600;
113 |   display: inline-block;
114 |   width: 100%;
115 | }
116 | 


--------------------------------------------------------------------------------
/themes/default/static/xcode.css:
--------------------------------------------------------------------------------
  1 | /*
  2 | 
  3 | XCode style (c) Angel Garcia 
  4 | 
  5 | */
  6 | 
  7 | .hljs {
  8 |   display: block;
  9 |   overflow-x: auto;
 10 |   padding: 0.5em;
 11 |   background: #fff;
 12 |   color: black;
 13 | }
 14 | 
 15 | /* Gray DOCTYPE selectors like WebKit */
 16 | .xml .hljs-meta {
 17 |   color: #c0c0c0;
 18 | }
 19 | 
 20 | .hljs-comment,
 21 | .hljs-quote {
 22 |   color: #007400;
 23 | }
 24 | 
 25 | .hljs-tag,
 26 | .hljs-attribute,
 27 | .hljs-keyword,
 28 | .hljs-selector-tag,
 29 | .hljs-literal,
 30 | .hljs-name {
 31 |   color: #aa0d91;
 32 | }
 33 | 
 34 | .hljs-variable,
 35 | .hljs-template-variable {
 36 |   color: #3F6E74;
 37 | }
 38 | 
 39 | .hljs-code,
 40 | .hljs-string,
 41 | .hljs-meta-string {
 42 |   color: #c41a16;
 43 | }
 44 | 
 45 | .hljs-regexp,
 46 | .hljs-link {
 47 |   color: #0E0EFF;
 48 | }
 49 | 
 50 | .hljs-title,
 51 | .hljs-symbol,
 52 | .hljs-bullet,
 53 | .hljs-number {
 54 |   color: #1c00cf;
 55 | }
 56 | 
 57 | .hljs-section,
 58 | .hljs-meta {
 59 |   color: #643820;
 60 | }
 61 | 
 62 | 
 63 | .hljs-class .hljs-title,
 64 | .hljs-type,
 65 | .hljs-built_in,
 66 | .hljs-builtin-name,
 67 | .hljs-params {
 68 |   color: #5c2699;
 69 | }
 70 | 
 71 | .hljs-attr {
 72 |   color: #836C28;
 73 | }
 74 | 
 75 | .hljs-subst {
 76 |   color: #000;
 77 | }
 78 | 
 79 | .hljs-formula {
 80 |   background-color: #eee;
 81 |   font-style: italic;
 82 | }
 83 | 
 84 | .hljs-addition {
 85 |   background-color: #baeeba;
 86 | }
 87 | 
 88 | .hljs-deletion {
 89 |   background-color: #ffc8bd;
 90 | }
 91 | 
 92 | .hljs-selector-id,
 93 | .hljs-selector-class {
 94 |   color: #9b703f;
 95 | }
 96 | 
 97 | .hljs-doctag,
 98 | .hljs-strong {
 99 |   font-weight: bold;
100 | }
101 | 
102 | .hljs-emphasis {
103 |   font-style: italic;
104 | }
105 | 


--------------------------------------------------------------------------------
/themes/default/templates/action.tmpl:
--------------------------------------------------------------------------------
 1 | {/*
 2 | This is the action template.
 3 | It determines how the formatting actions are rendered.
 4 | */}
 5 | 
 6 | {{define "section"}}
 7 |   {{.FormattedNumber}} {{.Title}}
 8 |   {{range .Elem}}{{elem $.Template .}}{{end}}
 9 | {{end}}
10 | 
11 | {{define "list"}}
12 |   
    13 | {{range .Bullet}} 14 |
  • {{style .}}
  • 15 | {{end}} 16 |
17 | {{end}} 18 | 19 | {{define "text"}} 20 | {{if .Pre}} 21 |
{{range .Lines}}{{.}}{{end}}
22 | {{else}} 23 |

24 | {{range $i, $l := .Lines}}{{if $i}}{{template "newline"}} 25 | {{end}}{{style $l}}{{end}} 26 |

27 | {{end}} 28 | {{end}} 29 | 30 | {{define "code"}} 31 |
{{.Text}}
32 | {{end}} 33 | 34 | {{define "monaco"}} 35 |
36 | {{end}} 37 | 38 | {{define "image"}} 39 |
40 | 41 |
42 | {{end}} 43 | 44 | {{define "video"}} 45 |
46 | 49 |
50 | {{end}} 51 | 52 | {{define "background"}} 53 |
54 | 55 |
56 | {{end}} 57 | 58 | {{define "iframe"}} 59 | 60 | {{end}} 61 | 62 | {{define "link"}}{{end}} 63 | 64 | {{define "html"}}{{.HTML}}{{end}} 65 | 66 | {{define "inlinehtml"}}{{.HTML}}{{end}} 67 | 68 | {{define "caption"}}
{{style .Text}}
{{end}} 69 | -------------------------------------------------------------------------------- /themes/default/templates/article.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the article template. It defines how articles are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 10 | 27 | 28 | 29 | 30 |
31 |
32 |
{{.Title}} 33 | {{with .Subtitle}}{{.}}{{end}} 34 | {{if .Authors}} 35 | {{range .Authors}} 36 |
37 | {{range .Elem}}{{elem $.Template .}}{{end}} 38 |
39 | {{end}} 40 | {{end}} 41 |
42 |
43 |
44 |
45 |
46 | {{with .Sections}} 47 |
48 |
Contents
49 | {{template "TOC" .}} 50 |
51 | {{end}} 52 | 53 | {{range .Sections}} 54 | {{elem $.Template .}} 55 | {{end}}{{/* of Section block */}} 56 | 57 |
58 |
59 | 60 | {{if .PlayEnabled}} 61 | 62 | {{end}} 63 | 64 | 74 | 75 | 76 | {{end}} 77 | 78 | {{define "TOC"}} 79 |
    80 | {{range .}} 81 |
  • {{.Title}}
  • 82 | {{with .Sections}}{{template "TOC-Inner" .}}{{end}} 83 | {{end}} 84 |
85 | {{end}} 86 | 87 | {{define "TOC-Inner"}} 88 |
    89 | {{range .}} 90 |
  • {{.Title}}
  • 91 | {{with .Sections}}{{template "TOC-Inner" .}}{{end}} 92 | {{end}} 93 |
94 | {{end}} 95 | 96 | {{define "newline"}} 97 | {{/* No automatic line break. Paragraphs are free-form. */}} 98 | {{end}} 99 | -------------------------------------------------------------------------------- /themes/default/templates/dir.tmpl: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Talks - The Go Programming Language 6 | 7 | 8 | 25 | 26 | 27 | 28 |
29 | 30 |
31 | 39 | 40 |
41 | 42 |
43 | 44 |
45 | 46 |

Go talks

47 | 48 | {{with .Path}}

{{.}}

{{end}} 49 | 50 | {{with .Articles}} 51 |

Articles:

52 |
53 | {{range .}} 54 |
{{.Name}}: {{.Title}}
55 | {{end}} 56 |
57 | {{end}} 58 | 59 | {{with .Slides}} 60 |

Slide decks:

61 |
62 | {{range .}} 63 |
{{.Name}}: {{.Title}}
64 | {{end}} 65 |
66 | {{end}} 67 | 68 | {{with .Other}} 69 |

Files:

70 |
71 | {{range .}} 72 |
{{.Name}}
73 | {{end}} 74 |
75 | {{end}} 76 | 77 | {{with .Dirs}} 78 |

Sub-directories:

79 |
80 | {{range .}} 81 |
{{.Name}}
82 | {{end}} 83 |
84 | {{end}} 85 | 86 |
87 | 88 | 96 | 97 | 107 | 108 | 109 | -------------------------------------------------------------------------------- /themes/default/templates/slides.tmpl: -------------------------------------------------------------------------------- 1 | {/* This is the slide template. It defines how presentations are formatted. */} 2 | 3 | {{define "root"}} 4 | 5 | 6 | 7 | {{.Title}} 8 | 9 | 12 | 14 | 15 | 17 | 19 | 20 | 21 | 22 | {{if .NotesEnabled}} 23 | 27 | 28 | {{end}} 29 | 30 | 31 | 32 | 33 | 34 | 35 | 40 | 41 | 42 | 43 | 44 |
45 | 46 |
47 |

{{.Title}}

48 | {{with .Subtitle}}

{{.}}

{{end}} 49 | {{if not .Time.IsZero}}

{{.Time.Format "2 January 2006"}}

{{end}} 50 | {{range .Authors}} 51 |
52 | {{range .TextElem}}{{elem $.Template .}}{{end}} 53 |
54 | {{end}} 55 | 56 |
57 | 58 | {{range $i, $s := .Sections}} 59 | 60 |
61 | {{if $s.Elem}} 62 |

{{$s.Title}}

63 | {{range $s.Elem}}{{elem $.Template .}}{{end}} 64 | {{else}} 65 |

{{$s.Title}}

66 | {{end}} 67 | {{pagenum $s 1}} 68 | 69 |
70 | 71 | {{end}}{{/* of Slide block */}} 72 | 73 |
74 | 75 |
76 | Use the left and right arrow keys or click the left and right 77 | edges of the page to navigate between slides.
78 | (Press 'H' or navigate to hide this message.) 79 |
80 | 81 | 91 | 92 | 93 | {{end}} 94 | 95 | {{define "newline"}} 96 |
97 | {{end}} 98 | --------------------------------------------------------------------------------