├── Web _Tech_Slides ├── slideImages │ ├── url-structure.jpg │ ├── webArchitecture.jpg │ └── high-level-browser.png ├── css │ ├── style.css │ ├── github.css │ ├── 3D-rotations.css │ ├── impress-common.css │ ├── presentation.css │ ├── classic-slides.css │ └── impress-demo.css ├── README.md ├── Week1.html └── js │ ├── highlight.pack.js │ └── markdown.js └── README.md /Web _Tech_Slides/slideImages/url-structure.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeoverdoze/cs-web-tech-legon/HEAD/Web _Tech_Slides/slideImages/url-structure.jpg -------------------------------------------------------------------------------- /Web _Tech_Slides/slideImages/webArchitecture.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeoverdoze/cs-web-tech-legon/HEAD/Web _Tech_Slides/slideImages/webArchitecture.jpg -------------------------------------------------------------------------------- /Web _Tech_Slides/slideImages/high-level-browser.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/codeoverdoze/cs-web-tech-legon/HEAD/Web _Tech_Slides/slideImages/high-level-browser.png -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # cs-web-tech-legon 2 | This repo contains the teaching and study material for the CSCD311 (Web Technologies & Development) course at the University of Ghana, Legon - Department of Computer Science 3 | -------------------------------------------------------------------------------- /Web _Tech_Slides/css/style.css: -------------------------------------------------------------------------------- 1 | h1,h2,h3{ 2 | font-size: 125%; 3 | } 4 | .git-commands { 5 | overflow-x: auto; 6 | margin: 1.5em 0 3em; 7 | padding: 20px; 8 | max-width: 100%; 9 | color: #1b1b32; 10 | font-size: 1.4rem; 11 | line-height: 1.5em; 12 | background: #ececf1; 13 | } 14 | -------------------------------------------------------------------------------- /Web _Tech_Slides/README.md: -------------------------------------------------------------------------------- 1 | # cs-web-tech-legon 2 | <<<<<<< HEAD 3 | This repo contains the teaching and study material for the CSCD311 (Web Design and Development) course at the University of Ghana, Legon - Department of Computer Science 4 | ======= 5 | This repo contains the teaching and study material for the CSCD311 (Web Technologies & Development) course at the University of Ghana, Legon - Department of Computer Science 6 | >>>>>>> 4edc2faa096ae5f76480f6ea17e219bb09d3eced 7 | -------------------------------------------------------------------------------- /Web _Tech_Slides/css/github.css: -------------------------------------------------------------------------------- 1 | /* 2 | 3 | github.com style (c) Vasily Polovnyov 4 | 5 | */ 6 | 7 | .hljs { 8 | display: block; 9 | overflow-x: auto; 10 | padding: 0.5em; 11 | color: #333; 12 | background: #f8f8f8; 13 | } 14 | 15 | .hljs-comment, 16 | .hljs-quote { 17 | color: #998; 18 | font-style: italic; 19 | } 20 | 21 | .hljs-keyword, 22 | .hljs-selector-tag, 23 | .hljs-subst { 24 | color: #333; 25 | font-weight: bold; 26 | } 27 | 28 | .hljs-number, 29 | .hljs-literal, 30 | .hljs-variable, 31 | .hljs-template-variable, 32 | .hljs-tag .hljs-attr { 33 | color: #008080; 34 | } 35 | 36 | .hljs-string, 37 | .hljs-doctag { 38 | color: #d14; 39 | } 40 | 41 | .hljs-title, 42 | .hljs-section, 43 | .hljs-selector-id { 44 | color: #900; 45 | font-weight: bold; 46 | } 47 | 48 | .hljs-subst { 49 | font-weight: normal; 50 | } 51 | 52 | .hljs-type, 53 | .hljs-class .hljs-title { 54 | color: #458; 55 | font-weight: bold; 56 | } 57 | 58 | .hljs-tag, 59 | .hljs-name, 60 | .hljs-attribute { 61 | color: #000080; 62 | font-weight: normal; 63 | } 64 | 65 | .hljs-regexp, 66 | .hljs-link { 67 | color: #009926; 68 | } 69 | 70 | .hljs-symbol, 71 | .hljs-bullet { 72 | color: #990073; 73 | } 74 | 75 | .hljs-built_in, 76 | .hljs-builtin-name { 77 | color: #0086b3; 78 | } 79 | 80 | .hljs-meta { 81 | color: #999; 82 | font-weight: bold; 83 | } 84 | 85 | .hljs-deletion { 86 | background: #fdd; 87 | } 88 | 89 | .hljs-addition { 90 | background: #dfd; 91 | } 92 | 93 | .hljs-emphasis { 94 | font-style: italic; 95 | } 96 | 97 | .hljs-strong { 98 | font-weight: bold; 99 | } 100 | -------------------------------------------------------------------------------- /Web _Tech_Slides/css/3D-rotations.css: -------------------------------------------------------------------------------- 1 | @import url(fonts.css); 2 | 3 | 4 | 5 | /* Fallback message */ 6 | 7 | .fallback-message { 8 | font-family: sans-serif; 9 | line-height: 1.3; 10 | 11 | width: 780px; 12 | padding: 10px 10px 0; 13 | margin: 20px auto; 14 | 15 | border: 1px solid #E4C652; 16 | border-radius: 10px; 17 | background: #EEDC94; 18 | } 19 | 20 | .fallback-message p { 21 | margin-bottom: 10px; 22 | } 23 | 24 | .impress-supported .fallback-message { 25 | display: none; 26 | } 27 | 28 | 29 | /* Body & steps */ 30 | body { 31 | font-family: 'PT Sans', sans-serif; 32 | min-height: 740px; 33 | 34 | background: #00000f; 35 | color: rgb(102, 102, 102); 36 | } 37 | 38 | .step { 39 | position: relative; 40 | width: 700px; 41 | height: 700px; 42 | padding: 40px 60px; 43 | margin: 20px auto; 44 | 45 | box-sizing: border-box; 46 | 47 | line-height: 1.5; 48 | 49 | background-color: white; 50 | border-radius: 10px; 51 | box-shadow: 0 2px 6px rgba(0, 0, 0, .1); 52 | 53 | text-shadow: 0 2px 2px rgba(0, 0, 0, .1); 54 | 55 | font-family: 'Open Sans', Arial, sans-serif; 56 | font-size: 40pt; 57 | letter-spacing: -1px; 58 | 59 | } 60 | 61 | /* Overview step has no background or border */ 62 | 63 | .overview { 64 | background-color: transparent; 65 | border: none; 66 | box-shadow: none; 67 | pointer-events: none; 68 | display: none; 69 | } 70 | .overview.active { 71 | display: block; 72 | pointer-events: auto; 73 | } 74 | 75 | /* 76 | Make inactive steps a little bit transparent. 77 | */ 78 | .impress-enabled .step { 79 | margin: 0; 80 | opacity: 0.1; 81 | transition: opacity 1s; 82 | } 83 | 84 | .impress-enabled .step.active { opacity: 1 } 85 | 86 | 87 | /* Content */ 88 | 89 | h1, 90 | h2, 91 | h3 { 92 | margin-bottom: 0.5em; 93 | margin-top: 0.5em; 94 | text-align: center; 95 | } 96 | 97 | p { 98 | margin: 0.7em; 99 | } 100 | 101 | li { 102 | margin: 0.2em; 103 | } 104 | 105 | /* Highlight.js used for coloring pre > code blocks. */ 106 | pre > code { 107 | font-size: 14px; 108 | text-shadow: 0 0 0 rgba(0, 0, 0, 0); 109 | } 110 | 111 | /* Inline code, no Highlight.js */ 112 | code { 113 | font-family: "Cutive mono","Courier New", monospace; 114 | } 115 | 116 | 117 | a { 118 | color: inherit; 119 | text-decoration: none; 120 | padding: 0 0.1em; 121 | background: rgba(200,200,200,0.2); 122 | text-shadow: -1px 1px 2px rgba(100,100,100,0.9); 123 | border-radius: 0.2em; 124 | border-bottom: 1px solid rgba(100,100,100,0.2); 125 | border-left: 1px solid rgba(100,100,100,0.2); 126 | 127 | transition: 0.5s; 128 | } 129 | a:hover, 130 | a:focus { 131 | background: rgba(200,200,200,1); 132 | text-shadow: -1px 1px 2px rgba(100,100,100,0.5); 133 | } 134 | 135 | blockquote { 136 | font-family: 'PT Serif'; 137 | font-style: italic; 138 | font-weight: 400; 139 | } 140 | 141 | em { 142 | text-shadow: 0 2px 2px rgba(0, 0, 0, .3); 143 | } 144 | 145 | strong { 146 | text-shadow: -1px 1px 2px rgba(100,100,100,0.5); 147 | } 148 | 149 | q { 150 | font-family: 'PT Serif'; 151 | font-style: italic; 152 | font-weight: 400; 153 | text-shadow: 0 2px 2px rgba(0, 0, 0, .3); 154 | } 155 | 156 | strike { 157 | opacity: 0.7; 158 | } 159 | 160 | small { 161 | font-size: 0.4em; 162 | } 163 | 164 | /* Styles specific to each step */ 165 | 166 | #overview2 { 167 | font-size: 20pt; 168 | padding-left: 200px; 169 | text-align: right; 170 | } -------------------------------------------------------------------------------- /Web _Tech_Slides/css/impress-common.css: -------------------------------------------------------------------------------- 1 | /* impress.js doesn't require any particular CSS file. 2 | Each author should create their own, to achieve the visual style they want. 3 | Yet in practice many plugins will not do anything useful without CSS. (See for example mouse-timeout plugin.) 4 | This file contains sample CSS that you may want to use in your presentation. 5 | It is focused on plugin functionality, not the visual style of your presentation. */ 6 | 7 | /* Using the substep plugin, hide bullet points at first, then show them one by one. */ 8 | #impress .step .substep { 9 | opacity: 0; 10 | } 11 | 12 | #impress .step .substep.substep-visible { 13 | opacity: 1; 14 | transition: opacity 1s; 15 | } 16 | /* 17 | Speaker notes allow you to write comments within the steps, that will not 18 | be displayed as part of the presentation. However, they will be picked up 19 | and displayed by impressConsole.js when you press P. 20 | */ 21 | .notes { 22 | display: none; 23 | } 24 | 25 | /* Toolbar plugin */ 26 | .impress-enabled div#impress-toolbar { 27 | position: fixed; 28 | right: 1px; 29 | bottom: 1px; 30 | opacity: 0.6; 31 | z-index: 10; 32 | } 33 | .impress-enabled div#impress-toolbar > span { 34 | margin-right: 10px; 35 | } 36 | .impress-enabled div#impress-toolbar.impress-toolbar-show { 37 | display: block; 38 | } 39 | .impress-enabled div#impress-toolbar.impress-toolbar-hide { 40 | display: none; 41 | } 42 | 43 | /* Progress bar */ 44 | .impress-progress { 45 | position: absolute; 46 | left: 59px; 47 | bottom: 1px; 48 | text-align: left; 49 | font-size: 10pt; 50 | opacity: 0.6; 51 | } 52 | .impress-enabled .impress-progressbar { 53 | position: absolute; 54 | right: 318px; 55 | bottom: 1px; 56 | left: 118px; 57 | border-radius: 7px; 58 | border: 2px solid rgba(100, 100, 100, 0.2); 59 | } 60 | .impress-progressbar { 61 | right: 118px; 62 | } 63 | .impress-progressbar DIV { 64 | width: 0; 65 | height: 2px; 66 | border-radius: 5px; 67 | background: rgba(75, 75, 75, 0.4); 68 | transition: width 1s linear; 69 | } 70 | .impress-enabled .impress-progress { 71 | position: absolute; 72 | left: 59px; 73 | bottom: 1px; 74 | text-align: left; 75 | opacity: 0.6; 76 | } 77 | .impress-enabled #impress-help { 78 | background: none repeat scroll 0 0 rgba(0, 0, 0, 0.5); 79 | color: #EEEEEE; 80 | font-size: 80%; 81 | position: fixed; 82 | left: 2em; 83 | bottom: 2em; 84 | width: 24em; 85 | border-radius: 1em; 86 | padding: 1em; 87 | text-align: center; 88 | z-index: 100; 89 | font-family: Verdana, Arial, Sans; 90 | } 91 | .impress-enabled #impress-help td { 92 | padding-left: 1em; 93 | padding-right: 1em; 94 | } 95 | 96 | /* 97 | With help from the mouse-timeout plugin, we can hide the toolbar and 98 | have it show only when you move/click/touch the mouse. 99 | */ 100 | body.impress-mouse-timeout div#impress-toolbar { 101 | display: none; 102 | } 103 | 104 | /* 105 | In fact, we can hide the mouse cursor itself too, when mouse isn't used. 106 | */ 107 | body.impress-mouse-timeout { 108 | cursor: none; 109 | } 110 | 111 | 112 | /* 113 | And as the last thing there is a workaround for quite strange bug. 114 | It happens a lot in Chrome. I don't remember if I've seen it in Firefox. 115 | 116 | Sometimes the element positioned in 3D (especially when it's moved back 117 | along Z axis) is not clickable, because it falls 'behind' the 118 | element. 119 | 120 | To prevent this, I decided to make non clickable by setting 121 | pointer-events property to `none` value. 122 | Value if this property is inherited, so to make everything else clickable 123 | I bring it back on the #impress element. 124 | 125 | If you want to know more about `pointer-events` here are some docs: 126 | https://developer.mozilla.org/en/CSS/pointer-events 127 | 128 | There is one very important thing to notice about this workaround - it makes 129 | everything 'unclickable' except what's in #impress element. 130 | 131 | So use it wisely ... or don't use at all. 132 | */ 133 | 134 | .impress-enabled { pointer-events: none } 135 | .impress-enabled #impress { pointer-events: auto } 136 | 137 | /*If you disable pointer-events, you need to re-enable them for the toolbar. 138 | And the speaker console while at it.*/ 139 | 140 | .impress-enabled #impress-toolbar { pointer-events: auto } 141 | .impress-enabled #impress-console-button { pointer-events: auto } 142 | 143 | 144 | /* 145 | There is one funny thing I just realized. 146 | 147 | Thanks to this workaround above everything except #impress element is invisible 148 | for click events. That means that the hint element is also not clickable. 149 | So basically all of this transforms and delayed transitions trickery was probably 150 | not needed at all... 151 | 152 | But it was fun to learn about it, wasn't it? 153 | */ 154 | 155 | 156 | -------------------------------------------------------------------------------- /Web _Tech_Slides/css/presentation.css: -------------------------------------------------------------------------------- 1 | /* 2 | A common approach is to use googleapis.com to generate css for the webfonts you want to use. 3 | The downside of this approach is that you have to be online. So below I have simply saved 4 | the output of the googleapis url into a file. Then you of course also have to make sure 5 | the webfonts are locally installed to make offline usage work. For Ubuntu (or Debian) I 6 | successfully used the script from here to do that: 7 | http://www.webupd8.org/2011/01/automatically-install-all-google-web.html 8 | */ 9 | 10 | /* @import url(http://fonts.googleapis.com/css?family=Open+Sans:regular,semibold,italic,italicsemibold|PT+Sans:400,700,400italic,700italic|PT+Serif:400,700,400italic,700italic|Cutive+Mono); */ 11 | @import url(fonts.css); 12 | 13 | 14 | 15 | /* 16 | We display a fallback message for users with browsers that don't support 17 | all the features required by it. All of the content will be still fully 18 | accessible for them, but some more advanced effects would be missing. 19 | When impress.js detects that browser supports all necessary CSS3 features, 20 | the fallback-message style is hidden. 21 | */ 22 | 23 | .fallback-message { 24 | font-family: sans-serif; 25 | line-height: 1.3; 26 | 27 | width: 780px; 28 | padding: 10px 10px 0; 29 | margin: 20px auto; 30 | 31 | border: 1px solid #E4C652; 32 | border-radius: 10px; 33 | background: #EEDC94; 34 | } 35 | 36 | .fallback-message p { 37 | margin-bottom: 10px; 38 | } 39 | 40 | .impress-supported .fallback-message { 41 | display: none; 42 | } 43 | 44 | 45 | /* 46 | The body background is the bacgkround of "everything". Many 47 | impress.js tools call it the "surface". It could also be a 48 | picture or pattern, but we leave it as light gray. 49 | */ 50 | 51 | body { 52 | font-family: 'PT Sans', sans-serif; 53 | min-height: 740px; 54 | 55 | background: #aaccbb; 56 | color: #ff4466; 57 | } 58 | 59 | /* 60 | Now let's style the presentation steps. 61 | */ 62 | 63 | .step { 64 | position: relative; 65 | display: block; 66 | 67 | width: 900px; 68 | height: 700px; 69 | margin: 20px auto; 70 | padding: 40px 60px; 71 | 72 | text-shadow: 0 2px 2px rgba(0, 10, 0, .5); 73 | 74 | font-family: 'Open Sans', Arial, sans-serif; 75 | font-size: 30px; 76 | letter-spacing: -1px; 77 | 78 | } 79 | /* 80 | Make inactive steps a little bit transparent. 81 | */ 82 | .impress-enabled .step { 83 | margin: 0; 84 | opacity: 0.3; 85 | transition: opacity 1s; 86 | } 87 | 88 | .impress-enabled .step.active { opacity: 1 } 89 | 90 | h1, 91 | h2, 92 | h3 { 93 | margin-bottom: 0.5em; 94 | margin-top: 0.5em; 95 | text-align: center; 96 | } 97 | 98 | p { 99 | text-align: center; 100 | margin: 0.7em; 101 | } 102 | 103 | li { 104 | margin: 0.2em; 105 | } 106 | 107 | /* Highlight.js used for coloring pre > code blocks. */ 108 | pre > code { 109 | font-size: 14px; 110 | text-shadow: 0 0 0 rgba(0, 0, 0, 0); 111 | } 112 | 113 | /* Inline code, no Highlight.js */ 114 | code { 115 | font-family: "Cutive mono","Courier New", monospace; 116 | } 117 | 118 | 119 | a { 120 | color: inherit; 121 | text-decoration: none; 122 | padding: 0 0.1em; 123 | background: rgba(200,200,200,0.3); 124 | text-shadow: -1px 1px 2px rgba(100,100,100,0.9); 125 | border-radius: 0.2em; 126 | border-bottom: 1px solid rgba(100,100,100,0.4); 127 | border-left: 1px solid rgba(100,100,100,0.4); 128 | 129 | transition: 0.5s; 130 | } 131 | a:hover, 132 | a:focus { 133 | background: rgba(200,200,200,1); 134 | text-shadow: -1px 1px 2px rgba(100,100,100,0.5); 135 | } 136 | 137 | blockquote { 138 | font-family: 'PT Serif'; 139 | font-style: italic; 140 | font-weight: 400; 141 | } 142 | 143 | em { 144 | text-shadow: 0 2px 2px rgba(0, 0, 0, .3); 145 | } 146 | 147 | strong { 148 | text-shadow: -1px 1px 2px rgba(100,100,100,0.5); 149 | } 150 | 151 | q { 152 | font-family: 'PT Serif'; 153 | font-style: italic; 154 | font-weight: 400; 155 | text-shadow: 0 2px 2px rgba(0, 0, 0, .3); 156 | } 157 | 158 | strike { 159 | opacity: 0.7; 160 | } 161 | 162 | small { 163 | font-size: 0.4em; 164 | } 165 | 166 | img { 167 | width: 300px 168 | } 169 | 170 | /****************** Background images **********************************************/ 171 | 172 | 173 | img.bg { 174 | position: fixed; 175 | z-index: -100; 176 | opacity: 0; 177 | height: 50%; 178 | width: auto; 179 | transition: opacity 2s; 180 | } 181 | 182 | #applepie-image { 183 | left: 0px; 184 | bottom: 0px; 185 | } 186 | 187 | body.impress-on-applepie #applepie-image, 188 | body.impress-on-applepie-pro #applepie-image, 189 | body.impress-on-applepie-con #applepie-image, 190 | body.impress-on-conclusion #applepie-image, 191 | body.impress-on-overview #applepie-image { 192 | opacity: 0.7; 193 | transition: opacity 2s; 194 | } 195 | 196 | #icecream-image { 197 | right: 0px; 198 | top: 0px; 199 | } 200 | 201 | body.impress-on-icecream #icecream-image, 202 | body.impress-on-icecream-pro #icecream-image, 203 | body.impress-on-icecream-con #icecream-image, 204 | body.impress-on-conclusion #icecream-image, 205 | body.impress-on-overview #icecream-image { 206 | opacity: 0.7; 207 | transition: opacity 2s; 208 | } 209 | 210 | #crisps-image { 211 | right: 0px; 212 | bottom: 0px; 213 | } 214 | 215 | body.impress-on-crisps #crisps-image, 216 | body.impress-on-crisps-pro #crisps-image, 217 | body.impress-on-crisps-con #crisps-image, 218 | body.impress-on-conclusion #crisps-image, 219 | body.impress-on-overview #crisps-image { 220 | opacity: 0.7; 221 | transition: opacity 2s; 222 | } 223 | 224 | 225 | /*************** Slide specific things ****************************/ 226 | 227 | #image-credits { 228 | color: #779988; 229 | } -------------------------------------------------------------------------------- /Web _Tech_Slides/css/classic-slides.css: -------------------------------------------------------------------------------- 1 | /* 2 | A common approach is to use googleapis.com to generate css for the webfonts you want to use. 3 | The downside of this approach is that you have to be online. So below I have simply saved 4 | the output of the googleapis url into a file. Then you of course also have to make sure 5 | the webfonts are locally installed to make offline usage work. For Ubuntu (or Debian) I 6 | successfully used the script from here to do that: 7 | http://www.webupd8.org/2011/01/automatically-install-all-google-web.html 8 | */ 9 | 10 | /* @import url(https://fonts.googleapis.com/css?family=Open+Sans:regular,semibold,italic,italicsemibold|PT+Sans:400,700,400italic,700italic|PT+Serif:400,700,400italic,700italic|Cutive+Mono); */ 11 | @import url(fonts.css); 12 | 13 | 14 | 15 | /* 16 | We display a fallback message for users with browsers that don't support 17 | all the features required by it. All of the content will be still fully 18 | accessible for them, but some more advanced effects would be missing. 19 | When impress.js detects that browser supports all necessary CSS3 features, 20 | the fallback-message style is hidden. 21 | */ 22 | 23 | .fallback-message { 24 | font-family: sans-serif; 25 | line-height: 1.3; 26 | 27 | width: 780px; 28 | padding: 10px 10px 0; 29 | margin: 20px auto; 30 | 31 | border: 1px solid #E4C652; 32 | border-radius: 10px; 33 | background: #EEDC94; 34 | } 35 | 36 | .fallback-message p { 37 | margin-bottom: 10px; 38 | } 39 | 40 | .impress-supported .fallback-message { 41 | display: none; 42 | } 43 | 44 | 45 | /* 46 | The body background is the bacgkround of "everything". Many 47 | impress.js tools call it the "surface". It could also be a 48 | picture or pattern, but we leave it as light gray. 49 | */ 50 | 51 | body { 52 | font-family: 'PT Sans', sans-serif; 53 | min-height: 740px; 54 | 55 | background: rgb(215, 215, 215); 56 | color: rgb(70, 70, 70); 57 | } 58 | 59 | /* 60 | Now let's style the presentation steps. 61 | */ 62 | 63 | .step { 64 | position: relative; 65 | width: 1800px; 66 | padding: 60px; 67 | margin: 60px auto; 68 | 69 | box-sizing: border-box; 70 | 71 | font-family: 'PT Serif', georgia, serif; 72 | font-size: 60px; 73 | line-height: 1.5; 74 | } 75 | /* 76 | Make inactive steps a little bit transparent. 77 | */ 78 | .impress-enabled .step { 79 | margin: 0; 80 | opacity: 0.3; 81 | transition: opacity 1s; 82 | } 83 | 84 | .impress-enabled .step.active { opacity: 1 } 85 | 86 | /* 87 | These 'slide' step styles were heavily inspired by HTML5 Slides: 88 | http://html5slides.googlecode.com/svn/trunk/styles.css 89 | 90 | Note that we also use a background image, again just to facilitate a common 91 | feature from PowerPoint and LibreOffice worlds. In this case the background 92 | image is just the impress.js favicon - as if it were a company logo or something. 93 | 94 | */ 95 | .slide { 96 | display: block; 97 | 98 | width: 1850px; 99 | height: 1000px; 100 | padding: 40px 60px; 101 | 102 | background-image: url(../images/background.png); 103 | background-color: white; 104 | border: 2px solid rgba(0, 0, 0, .3); 105 | border-radius: 30px; 106 | box-shadow: 0 4px 8px rgba(0, 0, 0, .1); 107 | 108 | text-shadow: 0 3px 3px rgba(0, 0, 0, .2); 109 | 110 | font-family: 'Open Sans', Arial, sans-serif; 111 | font-size: 45px; 112 | letter-spacing: -2px; 113 | } 114 | 115 | 116 | .slide h1, 117 | .slide h2, 118 | .slide h3 { 119 | margin-bottom: 0.5em; 120 | margin-top: 0.5em; 121 | text-align: center; 122 | } 123 | 124 | .slide p { 125 | text-align: center; 126 | margin: 0.7em; 127 | } 128 | 129 | .slide li { 130 | margin-top: 0.2em; 131 | margin-bottom: 0.2em; 132 | margin-left: 3em; 133 | margin-right: 3em; 134 | } 135 | 136 | /* Highlight.js used for coloring pre > code blocks. */ 137 | .slide pre > code { 138 | font-size: 30px; 139 | text-shadow: 0 0 0 rgba(0, 0, 0, 0); 140 | } 141 | 142 | .slide input { 143 | font-size: 1em; 144 | } 145 | 146 | /* Inline code, no Highlight.js */ 147 | code { 148 | font-family: "Cutive mono","Courier New", monospace; 149 | } 150 | 151 | 152 | a { 153 | color: inherit; 154 | text-decoration: none; 155 | padding: 0 0.1em; 156 | background: rgba(200,200,200,0.2); 157 | text-shadow: -2px 2px 4px rgba(100,100,100,0.9); 158 | border-radius: 0.2em; 159 | border-bottom: 3px solid rgba(100,100,100,0.2); 160 | border-left: 3px solid rgba(100,100,100,0.2); 161 | 162 | transition: 0.5s; 163 | } 164 | a:hover, 165 | a:focus { 166 | background: rgba(200,200,200,1); 167 | text-shadow: -2px 2px 3px rgba(100,100,100,0.5); 168 | } 169 | 170 | blockquote { 171 | font-family: 'PT Serif'; 172 | font-style: italic; 173 | font-weight: 400; 174 | } 175 | 176 | em { 177 | text-shadow: 0 6px 6px rgba(0, 0, 0, .3); 178 | } 179 | 180 | strong { 181 | text-shadow: -3px 3px 6px rgba(100,100,100,0.5); 182 | } 183 | 184 | q { 185 | font-family: 'PT Serif'; 186 | font-style: italic; 187 | font-weight: 400; 188 | text-shadow: 0 6px 6px rgba(0, 0, 0, .3); 189 | } 190 | 191 | strike { 192 | opacity: 0.7; 193 | } 194 | 195 | small { 196 | font-size: 0.4em; 197 | } 198 | 199 | img { 200 | width: 600px 201 | } 202 | 203 | td { 204 | padding: 0.2em; 205 | } 206 | 207 | .slide .right { 208 | float: right; 209 | margin-left: 60px; 210 | margin-right: 0px; 211 | margin-top: 40px; 212 | margin-bottom: 40px; 213 | } 214 | .slide .left { 215 | float: left; 216 | margin-right: 60px; 217 | margin-left: 0px; 218 | margin-top: 40px; 219 | margin-bottom: 40px; 220 | } 221 | .slide .top { 222 | position: absolute; 223 | top: 40px; 224 | margin-bottom: 40px; 225 | margin-top: 0px; 226 | } 227 | .slide .bottom { 228 | position: absolute; 229 | bottom: 40px; 230 | margin-bottom: 0px; 231 | margin-top: 40px; 232 | } 233 | 234 | /* 235 | Specific styles for: .title slides 236 | */ 237 | 238 | .title { 239 | background-image: url(../images/background-title.png); 240 | } 241 | 242 | .title h1, 243 | .title h2, 244 | .title h3 { 245 | position: absolute; 246 | left: 90px; /* slide width is 1800px, so this is like a 5% margin on both sides */ 247 | width: 90%; 248 | text-align: center; 249 | } 250 | .title h1 { top: 50px; } 251 | .title h2 { top: 600px; } 252 | .title h3 { top: 800px; } 253 | 254 | 255 | 256 | /* Styles for animating the contents of a slide, such as a img, p, li or span element. ********/ 257 | 258 | /* 259 | fly-in class starts from a position outside the slide, then flies into it's correct position. 260 | */ 261 | .future .fly-in { 262 | transform: translateY(-2100px); 263 | opacity: 0.0; /* Make it invisible, just so it doesn't clutter some other slide that might be in the position where we moved it */ 264 | } 265 | .present .fly-in { 266 | transform: translateY(0px); 267 | opacity: 1.0; 268 | transition: 2s; 269 | } 270 | .past .fly-out { 271 | transform: translateY(2100px); 272 | opacity: 0.0; 273 | transition: 2s; 274 | } 275 | 276 | /* 277 | Fade-in/out is a straightforward fade. Give it enough seconds that all browsers render it clearly. 278 | */ 279 | .future .fade-in { 280 | opacity: 0.0; 281 | } 282 | .present .fade-in { 283 | opacity: 1.0; 284 | transition: 3s; 285 | } 286 | .past .fade-out { 287 | opacity: 0.0; 288 | transition: 3s; 289 | } 290 | /* 291 | Zoom-in. 292 | */ 293 | .future .zoom-in { 294 | transform: scale(10); 295 | opacity: 0.0; 296 | } 297 | .present .zoom-in { 298 | transform: scale(1); 299 | opacity: 1.0; 300 | transition: 3s; 301 | } 302 | .past .zoom-out { 303 | transform: scale(10); 304 | opacity: 0.0; 305 | } 306 | 307 | /* 308 | Styles for specific slides. 309 | */ 310 | 311 | /* The bar graph for Acme Inc profits */ 312 | 313 | #acme-graph-bottom { 314 | position: absolute; 315 | bottom: 100px; 316 | right: 200px; 317 | background-color: black; 318 | width: 900px; 319 | height: 3px; 320 | } 321 | 322 | /* height: is set from javascript */ 323 | #acme-graph-q1, 324 | #acme-graph-q2, 325 | #acme-graph-q3, 326 | #acme-graph-q4 { 327 | border: solid 1px black; 328 | width: 140px; 329 | margin-left: 30px; 330 | position: absolute; 331 | bottom: 100px; 332 | } 333 | 334 | #acme-graph-q1 { 335 | background-color: red; 336 | right: 900px; 337 | } 338 | 339 | #acme-graph-q2 { 340 | background-color: blue; 341 | right: 700px; 342 | } 343 | 344 | #acme-graph-q3 { 345 | background-color: green; 346 | right: 500px; 347 | } 348 | 349 | #acme-graph-q4 { 350 | background-color: purple; 351 | left: 750px; 352 | right: 300px; 353 | } 354 | 355 | /* 356 | And as the last thing there is a workaround for quite strange bug. 357 | It happens a lot in Chrome. I don't remember if I've seen it in Firefox. 358 | 359 | Sometimes the element positioned in 3D (especially when it's moved back 360 | along Z axis) is not clickable, because it falls 'behind' the 361 | element. 362 | 363 | To prevent this, I decided to make non clickable by setting 364 | pointer-events property to `none` value. 365 | Value if this property is inherited, so to make everything else clickable 366 | I bring it back on the #impress element. 367 | 368 | If you want to know more about `pointer-events` here are some docs: 369 | https://developer.mozilla.org/en/CSS/pointer-events 370 | 371 | There is one very important thing to notice about this workaround - it makes 372 | everything 'unclickable' except what's in #impress element. 373 | 374 | So use it wisely ... or don't use at all. 375 | */ 376 | .impress-enabled { pointer-events: none } 377 | .impress-enabled #impress { pointer-events: auto } 378 | .impress-enabled #impress-toolbar { pointer-events: auto } 379 | .impress-enabled #impress-console-button { pointer-events: auto } 380 | -------------------------------------------------------------------------------- /Web _Tech_Slides/css/impress-demo.css: -------------------------------------------------------------------------------- 1 | /* 2 | So you like the style of impress.js demo? 3 | Or maybe you are just curious how it was done? 4 | 5 | You couldn't find a better place to find out! 6 | 7 | Welcome to the stylesheet impress.js demo presentation. 8 | 9 | Please remember that it is not meant to be a part of impress.js and is 10 | not required by impress.js. 11 | I expect that anyone creating a presentation for impress.js would create 12 | their own set of styles. 13 | 14 | But feel free to read through it and learn how to get the most of what 15 | impress.js provides. 16 | 17 | And let me be your guide. 18 | 19 | Shall we begin? 20 | */ 21 | 22 | 23 | /* 24 | We start with a good ol' reset. 25 | That's the one by Eric Meyer http://meyerweb.com/eric/tools/css/reset/ 26 | 27 | You can probably argue if it is needed here, or not, but for sure it 28 | doesn't do any harm and gives us a fresh start. 29 | */ 30 | 31 | html, body, div, span, applet, object, iframe, 32 | h1, h2, h3, h4, h5, h6, p, blockquote, pre, 33 | a, abbr, acronym, address, big, cite, code, 34 | del, dfn, em, img, ins, kbd, q, s, samp, 35 | small, strike, strong, sub, sup, tt, var, 36 | b, u, i, center, 37 | dl, dt, dd, ol, ul, li, 38 | fieldset, form, label, legend, 39 | table, caption, tbody, tfoot, thead, tr, th, td, 40 | article, aside, canvas, details, embed, 41 | figure, figcaption, footer, header, hgroup, 42 | menu, nav, output, ruby, section, summary, 43 | time, mark, audio, video { 44 | margin: 0; 45 | padding: 0; 46 | border: 0; 47 | font-size: 100%; 48 | font: inherit; 49 | vertical-align: baseline; 50 | } 51 | 52 | /* HTML5 display-role reset for older browsers */ 53 | article, aside, details, figcaption, figure, 54 | footer, header, hgroup, menu, nav, section { 55 | display: block; 56 | } 57 | body { 58 | line-height: 1; 59 | } 60 | ol, ul { 61 | list-style: none; 62 | } 63 | blockquote, q { 64 | quotes: none; 65 | } 66 | blockquote:before, blockquote:after, 67 | q:before, q:after { 68 | content: ''; 69 | content: none; 70 | } 71 | 72 | table { 73 | border-collapse: collapse; 74 | border-spacing: 0; 75 | } 76 | 77 | /* 78 | Now here is when interesting things start to appear. 79 | 80 | We set up styles with default font and nice gradient in the background. 81 | And yes, there is a lot of repetition there because of -prefixes but we don't 82 | want to leave anybody behind. 83 | */ 84 | body { 85 | font-family: 'PT Sans', sans-serif; 86 | min-height: 740px; 87 | 88 | background: rgb(215, 215, 215); 89 | background: -webkit-gradient(radial, 50% 50%, 0, 50% 50%, 500, from(rgb(240, 240, 240)), to(rgb(190, 190, 190))); 90 | background: -webkit-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 91 | background: -moz-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 92 | background: -ms-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 93 | background: -o-radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 94 | background: radial-gradient(rgb(240, 240, 240), rgb(190, 190, 190)); 95 | } 96 | 97 | /* 98 | Now let's bring some text styles back ... 99 | */ 100 | b, strong { font-weight: bold } 101 | i, em { font-style: italic } 102 | 103 | /* 104 | ... and give links a nice look. 105 | */ 106 | a { 107 | color: inherit; 108 | text-decoration: none; 109 | padding: 0 0.1em; 110 | background: rgba(255,255,255,0.5); 111 | text-shadow: -1px -1px 2px rgba(100,100,100,0.9); 112 | border-radius: 0.2em; 113 | 114 | -webkit-transition: 0.5s; 115 | -moz-transition: 0.5s; 116 | -ms-transition: 0.5s; 117 | -o-transition: 0.5s; 118 | transition: 0.5s; 119 | } 120 | 121 | a:hover, 122 | a:focus { 123 | background: rgba(255,255,255,1); 124 | text-shadow: -1px -1px 2px rgba(100,100,100,0.5); 125 | } 126 | 127 | /* 128 | Because the main point behind the impress.js demo is to demo impress.js 129 | we display a fallback message for users with browsers that don't support 130 | all the features required by it. 131 | 132 | All of the content will be still fully accessible for them, but I want 133 | them to know that they are missing something - that's what the demo is 134 | about, isn't it? 135 | 136 | And then we hide the message, when support is detected in the browser. 137 | */ 138 | 139 | .fallback-message { 140 | font-family: sans-serif; 141 | line-height: 1.3; 142 | 143 | width: 780px; 144 | padding: 10px 10px 0; 145 | margin: 20px auto; 146 | 147 | border: 1px solid #E4C652; 148 | border-radius: 10px; 149 | background: #EEDC94; 150 | } 151 | 152 | .fallback-message p { 153 | margin-bottom: 10px; 154 | } 155 | 156 | .impress-supported .fallback-message { 157 | display: none; 158 | } 159 | 160 | /* 161 | Now let's style the presentation steps. 162 | 163 | We start with basics to make sure it displays correctly in everywhere ... 164 | */ 165 | 166 | .step { 167 | position: relative; 168 | width: 900px; 169 | padding: 40px; 170 | margin: 20px auto; 171 | 172 | -webkit-box-sizing: border-box; 173 | -moz-box-sizing: border-box; 174 | -ms-box-sizing: border-box; 175 | -o-box-sizing: border-box; 176 | box-sizing: border-box; 177 | 178 | font-family: 'PT Serif', georgia, serif; 179 | font-size: 48px; 180 | line-height: 1.5; 181 | } 182 | 183 | /* 184 | ... and we enhance the styles for impress.js. 185 | 186 | Basically we remove the margin and make inactive steps a little bit transparent. 187 | */ 188 | .impress-enabled .step { 189 | margin: 0; 190 | opacity: 0.3; 191 | 192 | -webkit-transition: opacity 1s; 193 | -moz-transition: opacity 1s; 194 | -ms-transition: opacity 1s; 195 | -o-transition: opacity 1s; 196 | transition: opacity 1s; 197 | } 198 | 199 | .impress-enabled .step.active { opacity: 1 } 200 | 201 | /* 202 | These 'slide' step styles were heavily inspired by HTML5 Slides: 203 | http://html5slides.googlecode.com/svn/trunk/styles.css 204 | 205 | ;) 206 | 207 | They cover everything what you see on first three steps of the demo. 208 | 209 | All impress.js steps are wrapped inside a div element of 0 size! This means that relative 210 | values for width and height (example: `width: 100%`) will not work. You need to use pixel 211 | values. The pixel values used here correspond to the data-width and data-height given to the 212 | #impress root element. When the presentation is viewed on a larger or smaller screen, impress.js 213 | will automatically scale the steps to fit the screen. 214 | */ 215 | .slide { 216 | display: block; 217 | 218 | width: 900px; 219 | height: 700px; 220 | padding: 40px 60px; 221 | 222 | background-color: white; 223 | border: 1px solid rgba(0, 0, 0, .3); 224 | border-radius: 10px; 225 | box-shadow: 0 2px 6px rgba(0, 0, 0, .1); 226 | 227 | color: rgb(102, 102, 102); 228 | text-shadow: 0 2px 2px rgba(0, 0, 0, .1); 229 | 230 | font-family: 'Open Sans', Arial, sans-serif; 231 | font-size: 30px; 232 | line-height: 36px; 233 | letter-spacing: -1px; 234 | } 235 | 236 | .slide q { 237 | display: block; 238 | font-size: 50px; 239 | line-height: 72px; 240 | 241 | margin-top: 100px; 242 | } 243 | 244 | .slide q strong { 245 | white-space: nowrap; 246 | } 247 | 248 | /* 249 | And now we start to style each step separately. 250 | 251 | I agree that this may be not the most efficient, object-oriented and 252 | scalable way of styling, but most of steps have quite a custom look 253 | and typography tricks here and there, so they had to be styled separately. 254 | 255 | First is the title step with a big

(no room for padding) and some 256 | 3D positioning along Z axis. 257 | */ 258 | 259 | #title { 260 | padding: 0; 261 | } 262 | 263 | #title .try { 264 | font-size: 64px; 265 | position: absolute; 266 | top: -0.5em; 267 | left: 1.5em; 268 | 269 | -webkit-transform: translateZ(20px); 270 | -moz-transform: translateZ(20px); 271 | -ms-transform: translateZ(20px); 272 | -o-transform: translateZ(20px); 273 | transform: translateZ(20px); 274 | } 275 | 276 | #title h1 { 277 | font-size: 180px; 278 | 279 | -webkit-transform: translateZ(50px); 280 | -moz-transform: translateZ(50px); 281 | -ms-transform: translateZ(50px); 282 | -o-transform: translateZ(50px); 283 | transform: translateZ(50px); 284 | } 285 | 286 | #title .footnote { 287 | font-size: 32px; 288 | } 289 | 290 | /* 291 | Second step is nothing special, just a text with a link, so it doesn't need 292 | any special styling. 293 | 294 | Let's move to 'big thoughts' with centered text and custom font sizes. 295 | */ 296 | #big { 297 | width: 600px; 298 | text-align: center; 299 | font-size: 60px; 300 | line-height: 1; 301 | } 302 | 303 | #big strong, 304 | #big b { 305 | display: block; 306 | font-size: 250px; 307 | line-height: 250px; 308 | } 309 | 310 | #big .thoughts { 311 | font-size: 90px; 312 | line-height: 150px; 313 | } 314 | 315 | /* 316 | 'Tiny ideas' just need some tiny styling. 317 | */ 318 | #tiny { 319 | width: 500px; 320 | text-align: center; 321 | } 322 | 323 | /* 324 | This step has some animated text ... 325 | */ 326 | #ing { width: 500px } 327 | 328 | /* 329 | ... so we define display to `inline-block` to enable transforms and 330 | transition duration to 0.5s ... 331 | */ 332 | #ing b { 333 | display: inline-block; 334 | -webkit-transition: 0.5s; 335 | -moz-transition: 0.5s; 336 | -ms-transition: 0.5s; 337 | -o-transition: 0.5s; 338 | transition: 0.5s; 339 | } 340 | 341 | /* 342 | ... and we want 'positioning` word to move up a bit when the step gets 343 | `present` class ... 344 | */ 345 | #ing.present .positioning { 346 | -webkit-transform: translateY(-10px); 347 | -moz-transform: translateY(-10px); 348 | -ms-transform: translateY(-10px); 349 | -o-transform: translateY(-10px); 350 | transform: translateY(-10px); 351 | } 352 | 353 | /* 354 | ... 'rotating' to rotate a quarter of a second later ... 355 | */ 356 | #ing.present .rotating { 357 | -webkit-transform: rotate(-10deg); 358 | -moz-transform: rotate(-10deg); 359 | -ms-transform: rotate(-10deg); 360 | -o-transform: rotate(-10deg); 361 | transform: rotate(-10deg); 362 | 363 | -webkit-transition-delay: 0.25s; 364 | -moz-transition-delay: 0.25s; 365 | -ms-transition-delay: 0.25s; 366 | -o-transition-delay: 0.25s; 367 | transition-delay: 0.25s; 368 | } 369 | 370 | /* 371 | ... and 'scaling' to scale down after another quarter of a second. 372 | */ 373 | #ing.present .scaling { 374 | -webkit-transform: scale(0.7); 375 | -moz-transform: scale(0.7); 376 | -ms-transform: scale(0.7); 377 | -o-transform: scale(0.7); 378 | transform: scale(0.7); 379 | 380 | -webkit-transition-delay: 0.5s; 381 | -moz-transition-delay: 0.5s; 382 | -ms-transition-delay: 0.5s; 383 | -o-transition-delay: 0.5s; 384 | transition-delay: 0.5s; 385 | } 386 | 387 | /* 388 | The 'imagination' step is again some boring font-sizing. 389 | */ 390 | 391 | #imagination { 392 | width: 600px; 393 | } 394 | 395 | #imagination .imagination { 396 | font-size: 78px; 397 | } 398 | 399 | /* 400 | There is nothing really special about 'use the source, Luke' step, too, 401 | except maybe of the Yoda background. 402 | 403 | As you can see below I've 'hard-coded' it in data URL. 404 | That's not the best way to serve images, but because that's just this one 405 | I decided it will be OK to have it this way. 406 | 407 | Just make sure you don't blindly copy this approach. 408 | */ 409 | #source { 410 | width: 700px; 411 | padding-bottom: 300px; 412 | 413 | /* Yoda Icon :: Pixel Art from Star Wars http://www.pixeljoint.com/pixelart/1423.htm */ 414 | background-image: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAARgAAAEYCAMAAACwUBm+AAAAAXNSR0IArs4c6QAAAKtQTFRFsAAAvbWSLUUrLEQqY1s8UYJMqJ1vNTEgOiIdIzYhjIFVLhsXZ6lgSEIsP2U8JhcCVzMsSXZEgXdOO145XJdWOl03LzAYMk4vSXNExr+hwcuxRTs1Qmk+RW9Am49eFRANQz4pUoNMQWc+OSMDTz0wLBsCNVMxa2NBOyUDUoNNSnlEWo9VRGxAVzYFl6tXCggHbLNmMUIcHhwTXkk5f3VNRT8wUT8xAAAACQocRBWFFwAAAAF0Uk5TAEDm2GYAAAPCSURBVHja7d3JctNAFIZRMwRCCGEmzPM8z/D+T8bu/ptbXXJFdij5fMt2Wuo+2UgqxVmtttq5WVotLzBgwIABAwYMGDCn0qVqbo69psPqVpWx+1XG5iaavF8wYMCAAQMGDBgwi4DJ6Y6qkxB1HNlcN3a92gbR5P2CAQMGDBgwYMCAWSxMlrU+UY5yu2l9okfV4bAxUVbf7TJnAwMGDBgwYMCAAbMLMHeqbGR82Zy+VR1Ht81nVca6R+UdTLaU24Ruzd3qM/e4yjnAgAEDBgwYMGDA7AJMd1l/3NRdVGcj3eX/2WEhCmDGxnM7yqygu8XIPjJj8iN/MGDAgAEDBgwYMAuDGb8q0RGlLCHLv1t9qDKWn3vdNHVuEI6HPaxO9Jo3GDBgwIABAwYMmIXBdC9ShGgMk+XnkXUeuGcsP/e1+lhNnZsL/G5Vs3OAAQMGDBgwYMCAWSxMR3SzOmraG5atdy9wZKzb+vg16qyqe2FltbnAgAEDBgwYMGDALAxmTJSuN3WA76rnVca6GTnemGN1WoEBAwYMGDBgwIBZGMxUomy4+xO899V4LAg5Xnc2MGDAgAEDBgwYMGA218Wq+2K1LDqvY9xZu8zN8fICdM6btYABAwYMGDBgwIABMzfH0+pGU5afze2tXebmeAfVz+p8BQYMGDBgwIABAwbMPBzZ+oWmfJrln1273FhkbHzee9WWbw7AgAEDBgwYMGDALAKm43hcdctKgblcPamOhuXnXlY5Xs6bsW4FGyQCAwYMGDBgwIABswiYMceZKgvMo+h8mrHLTdn676rj+FEFoTtHd8MwOxEYMGDAgAEDBgyYRcBM5UhXqiymW3R3c9ARhWO/OmjqfjVZy+xEYMCAAQMGDBgwYBYG073OnCV0RFNhMhaOa9WfKmOB6XjHMN1tQmaAAQMGDBgwYMCA2VWY7vXjz1U4croAzgPztwIDBgwYMGDAgAEDZhswh035NBw59Dww3RgYMGDAgAEDBgwYMJuD6f4tXT7NUqfCdBvZLkxXdgQGDBgwYMCAAQNmt2DGj8WzwAfV/w7T/aq7mxwwYMCAAQMGDBgwuwqTOo7uTwTngflSzQ3TdaJvAwEDBgwYMGDAgAED5gSvgbyo5oHZ4Pc+gwEDBgwYMGDAgAEzhOm+5G0qTGaAAQMGDBgwYMCAAXNaMOcnls3tNwWm+zRzp54NDBgwYMCAAQMGDJh5YNL36k1TLuGvVq+qnKMbS5n7tulT9asCAwYMGDBgwIABA2ZumKuztLnjgQEDBgwYMGDAgNl5mH/4/ltKA6vBNAAAAABJRU5ErkJggg==); 415 | background-position: bottom right; 416 | background-repeat: no-repeat; 417 | } 418 | 419 | #source q { 420 | font-size: 60px; 421 | } 422 | 423 | /* 424 | And the "it's in 3D" step again brings some 3D typography - just for fun. 425 | 426 | Because we want to position elements in 3D we set transform-style to 427 | `preserve-3d` on the paragraph. 428 | It is not needed by webkit browsers, but it is in Firefox. It's hard to say 429 | which behaviour is correct as 3D transforms spec is not very clear about it. 430 | */ 431 | #its-in-3d p { 432 | -webkit-transform-style: preserve-3d; 433 | -moz-transform-style: preserve-3d; /* Y U need this Firefox?! */ 434 | -ms-transform-style: preserve-3d; 435 | -o-transform-style: preserve-3d; 436 | transform-style: preserve-3d; 437 | } 438 | 439 | /* 440 | Below we position each word separately along Z axis and we want it to transition 441 | to default position in 0.5s when the step gets `present` class. 442 | 443 | Quite a simple idea, but lot's of styles and prefixes. 444 | */ 445 | #its-in-3d span, 446 | #its-in-3d b { 447 | display: inline-block; 448 | -webkit-transform: translateZ(40px); 449 | -moz-transform: translateZ(40px); 450 | -ms-transform: translateZ(40px); 451 | -o-transform: translateZ(40px); 452 | transform: translateZ(40px); 453 | 454 | -webkit-transition: 0.5s; 455 | -moz-transition: 0.5s; 456 | -ms-transition: 0.5s; 457 | -o-transition: 0.5s; 458 | transition: 0.5s; 459 | } 460 | 461 | #its-in-3d .have { 462 | -webkit-transform: translateZ(-40px); 463 | -moz-transform: translateZ(-40px); 464 | -ms-transform: translateZ(-40px); 465 | -o-transform: translateZ(-40px); 466 | transform: translateZ(-40px); 467 | } 468 | 469 | #its-in-3d .you { 470 | -webkit-transform: translateZ(20px); 471 | -moz-transform: translateZ(20px); 472 | -ms-transform: translateZ(20px); 473 | -o-transform: translateZ(20px); 474 | transform: translateZ(20px); 475 | } 476 | 477 | #its-in-3d .noticed { 478 | -webkit-transform: translateZ(-40px); 479 | -moz-transform: translateZ(-40px); 480 | -ms-transform: translateZ(-40px); 481 | -o-transform: translateZ(-40px); 482 | transform: translateZ(-40px); 483 | } 484 | 485 | #its-in-3d .its { 486 | -webkit-transform: translateZ(60px); 487 | -moz-transform: translateZ(60px); 488 | -ms-transform: translateZ(60px); 489 | -o-transform: translateZ(60px); 490 | transform: translateZ(60px); 491 | } 492 | 493 | #its-in-3d .in { 494 | -webkit-transform: translateZ(-10px); 495 | -moz-transform: translateZ(-10px); 496 | -ms-transform: translateZ(-10px); 497 | -o-transform: translateZ(-10px); 498 | transform: translateZ(-10px); 499 | } 500 | 501 | #its-in-3d .footnote { 502 | font-size: 32px; 503 | 504 | -webkit-transform: translateZ(-10px); 505 | -moz-transform: translateZ(-10px); 506 | -ms-transform: translateZ(-10px); 507 | -o-transform: translateZ(-10px); 508 | transform: translateZ(-10px); 509 | } 510 | 511 | #its-in-3d.present span, 512 | #its-in-3d.present b { 513 | -webkit-transform: translateZ(0px); 514 | -moz-transform: translateZ(0px); 515 | -ms-transform: translateZ(0px); 516 | -o-transform: translateZ(0px); 517 | transform: translateZ(0px); 518 | } 519 | 520 | /* 521 | The last step is an overview. 522 | There is no content in it, so we make sure it's not visible because we want 523 | to be able to click on other steps. 524 | 525 | */ 526 | #overview { display: none } 527 | 528 | /* 529 | We also make other steps visible and give them a pointer cursor using the 530 | `impress-on-` class. 531 | */ 532 | .impress-on-overview .step { 533 | opacity: 1; 534 | cursor: pointer; 535 | } 536 | 537 | /* 538 | Now, when we have all the steps styled let's give users a hint how to navigate 539 | around the presentation. 540 | 541 | The best way to do this would be to use JavaScript, show a delayed hint for a 542 | first time users, then hide it and store a status in cookie or localStorage... 543 | 544 | But I wanted to have some CSS fun and avoid additional scripting... 545 | 546 | Let me explain it first, so maybe the transition magic will be more readable 547 | when you read the code. 548 | 549 | First of all I wanted the hint to appear only when user is idle for a while. 550 | You can't detect the 'idle' state in CSS, but I delayed a appearing of the 551 | hint by 5s using transition-delay. 552 | 553 | You also can't detect in CSS if the user is a first-time visitor, so I had to 554 | make an assumption that I'll only show the hint on the first step. And when 555 | the step is changed hide the hint, because I can assume that user already 556 | knows how to navigate. 557 | 558 | To summarize it - hint is shown when the user is on the first step for longer 559 | than 5 seconds. 560 | 561 | The other problem I had was caused by the fact that I wanted the hint to fade 562 | in and out. It can be easily achieved by transitioning the opacity property. 563 | But that also meant that the hint was always on the screen, even if totally 564 | transparent. It covered part of the screen and you couldn't correctly clicked 565 | through it. 566 | Unfortunately you cannot transition between display `block` and `none` in pure 567 | CSS, so I needed a way to not only fade out the hint but also move it out of 568 | the screen. 569 | 570 | I solved this problem by positioning the hint below the bottom of the screen 571 | with CSS transform and moving it up to show it. But I also didn't want this move 572 | to be visible. I wanted the hint only to fade in and out visually, so I delayed 573 | the fade in transition, so it starts when the hint is already in its correct 574 | position on the screen. 575 | 576 | I know, it sounds complicated ... maybe it would be easier with the code? 577 | */ 578 | 579 | .hint { 580 | /* 581 | We hide the hint until presentation is started and from browsers not supporting 582 | impress.js, as they will have a linear scrollable view ... 583 | */ 584 | display: none; 585 | 586 | /* 587 | ... and give it some fixed position and nice styles. 588 | */ 589 | position: fixed; 590 | left: 0; 591 | right: 0; 592 | bottom: 200px; 593 | 594 | background: rgba(0,0,0,0.5); 595 | color: #EEE; 596 | text-align: center; 597 | 598 | font-size: 50px; 599 | padding: 20px; 600 | 601 | z-index: 100; 602 | 603 | /* 604 | By default we don't want the hint to be visible, so we make it transparent ... 605 | */ 606 | opacity: 0; 607 | 608 | /* 609 | ... and position it below the bottom of the screen (relative to it's fixed position) 610 | */ 611 | -webkit-transform: translateY(400px); 612 | -moz-transform: translateY(400px); 613 | -ms-transform: translateY(400px); 614 | -o-transform: translateY(400px); 615 | transform: translateY(400px); 616 | 617 | /* 618 | Now let's imagine that the hint is visible and we want to fade it out and move out 619 | of the screen. 620 | 621 | So we define the transition on the opacity property with 1s duration and another 622 | transition on transform property delayed by 1s so it will happen after the fade out 623 | on opacity finished. 624 | 625 | This way user will not see the hint moving down. 626 | */ 627 | -webkit-transition: opacity 1s, -webkit-transform 0.5s 1s; 628 | -moz-transition: opacity 1s, -moz-transform 0.5s 1s; 629 | -ms-transition: opacity 1s, -ms-transform 0.5s 1s; 630 | -o-transition: opacity 1s, -o-transform 0.5s 1s; 631 | transition: opacity 1s, transform 0.5s 1s; 632 | } 633 | 634 | /* 635 | Now we 'enable' the hint when presentation is initialized ... 636 | */ 637 | .impress-enabled .hint { display: block } 638 | 639 | /* 640 | ... and we will show it when the first step (with id 'bored') is active. 641 | */ 642 | .impress-on-bored .hint { 643 | /* 644 | We remove the transparency and position the hint in its default fixed 645 | position. 646 | */ 647 | opacity: 1; 648 | 649 | -webkit-transform: translateY(0px); 650 | -moz-transform: translateY(0px); 651 | -ms-transform: translateY(0px); 652 | -o-transform: translateY(0px); 653 | transform: translateY(0px); 654 | 655 | /* 656 | Now for fade in transition we have the oposite situation from the one 657 | above. 658 | 659 | First after 4.5s delay we animate the transform property to move the hint 660 | into its correct position and after that we fade it in with opacity 661 | transition. 662 | */ 663 | -webkit-transition: opacity 1s 5s, -webkit-transform 0.5s 4.5s; 664 | -moz-transition: opacity 1s 5s, -moz-transform 0.5s 4.5s; 665 | -ms-transition: opacity 1s 5s, -ms-transform 0.5s 4.5s; 666 | -o-transition: opacity 1s 5s, -o-transform 0.5s 4.5s; 667 | transition: opacity 1s 5s, transform 0.5s 4.5s; 668 | } 669 | 670 | /* 671 | That's all I have for you in this file. 672 | Thanks for reading. I hope you enjoyed it at least as much as I enjoyed writing it 673 | for you. 674 | */ 675 | -------------------------------------------------------------------------------- /Web _Tech_Slides/Week1.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Week 1 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Your browser doesn't support the features required by impress.js, so you are presented with a simplified version of this presentation.

17 |

For the best experience please use the latest Chrome, Safari or Firefox browser.

18 |
19 | 20 |
28 |
29 |
30 |

WEEK 1


31 |

Foundations of Web Applications

32 |
33 |
34 |
35 |

In this session we will take a look at these topics

36 |
    37 |
  • Understanding How Web Applications Work
  • 38 |
  • Understanding Rest APIs
  • 39 |
  • Understanding Version Control Using Git
  • 40 |
  • Understanding HTML5
  • 41 |
  • Understanding CSS3
  • 42 |
  • Understanding how web browsers work
  • 43 |
44 |
45 |
46 |

What is a Web Application?


47 |
    48 |
  • A Web Application is any piece of software that can be accessed from a web browser
  • 49 |
  • Web Apps are classified as either static or dynamic
  • 50 |
  • A Web Application can be colloquially referred to as a Web Server although the two are not exactly the same
  • 51 |
  • Typically, web apps consist of two parts: 52 |
      53 |
    • Server side
    • 54 |
    • Client side
    • 55 |
  • 56 |
57 |
58 |
59 |

Server Side

60 |
61 |
    62 |
  • The Server-side of a web application generally refers to a computer(server) and the software or program that computer contains that hosts or runs a web application
  • 63 |
  • It is also sometimes known as the Backend of the application
  • 64 |
  • Most of the processing involved in the web application happen on the server
  • 65 |
  • Popular web servers include APACHE and NGINX
  • 66 |
  • The Backend receives requests from the client side through the browser, performs some operations on them and returns some results to the browser
  • 67 |
  • Communication between the client-side and server is via web protocols
  • 68 |
  • Examples of such protocols is HTTP, FTP and Web Socket
  • 69 |
70 |
71 |
72 |
73 |

Client Side

74 |
    75 |
  • The Client-side refers to the part of the application that the user or client interacts with
  • 76 |
  • It what the browser renders to the user
  • 77 |
  • The client-side is also sometimes known as the frontend of the application
  • 78 |
  • Requests are made on front the client-side of the application and sent to the server-side for processing
  • 79 |
  • Some processing and operations do however happen on the frontend
  • 80 |
  • The frontend is built using technologies like HTML, CSS and Javascript. These will be explored further in the course
  • 81 |
82 |
83 |
84 |

Web Resources

85 |
    86 |
  • These are identifiable documents that are hosted by a web server and can be accessed by the client
  • 87 |
  • Such resource documents can be in the form of a HTML, XML, pdf or json files among others
  • 88 |
  • A web resource is either static or dynamic
  • 89 |
  • A static web resource does not change and the web server passes into the client as it in stored on the server after it has been requested
  • 90 |
  • A dynamic web resource on the other hand is generated on the fly when the request for the resource is made
  • 91 |
  • Resources are uniquely identified by a Uniform Resource Locator(URL)
  • 92 |
93 |
94 |
95 |

What is a Uniform Resource Locator?

96 |
    97 |
  • Also referred to as a web address
  • 98 |
  • It is a is a reference to a web resource that specifies its location on a computer network and a mechanism for retrieving it
  • 99 |
  • . A URL is a specific type of Uniform Resource Identifier (URI),[2][3] although many people use the two terms interchangeably
  • 100 |
  • A typical URL consists of a protocol, host name and a file name
  • 101 |
102 |
103 |
104 |

URL contd

105 |
106 | 107 |

Detailed Components of a URL

108 |
109 |
110 |
111 |

Client-Server Relationship

112 |
113 |
    114 |
  • As mentioned earlier, the client-side and server-side perform individual functions that come together to form the application architecture
  • 115 |
  • The Client(browser) makes request to the server via a web protocol, say HTTP
  • 116 |
  • This request contains details of what the client wants like the intended resource and the path to that resource
  • 117 |
  • The server receives this request, processes it and sends a response back over the HTTP to the client
  • 118 |
  • The Browser then takes this response and renders it to the user in a way the user can understand
  • 119 |
  • The server can respond with an error message if the requested resource is not available.
  • 120 |
121 |
122 |
123 |
124 |

Client-Server Relationship contd



125 |
126 | 127 |

Web Application Architecture

128 |
129 |
130 |
131 |
132 |

UNDERSTANDING REST API CONCEPTS

133 |
134 |
135 |
136 |

API Concepts

137 |

Introduction

138 |
    139 |
  • API stands for Application Programming Interface
  • 140 |
  • It is an intermediary between two software applications that allows them to talk to each other.
  • 141 |
142 |
    143 |
  • For example, when using a weather app, the application utilises the API of a third party institution that collects weather data
  • 144 |
  • Another example is a ride hailing app like Uber using Google Maps API to generate routes
  • 145 |
146 |
147 |
148 |

REST API

149 |
    150 |
  • It is an acronym for Representational State Transfer
  • 151 |
  • In general, REST is a software architectural style which defines a set of rules and constraints that are used for creating web services, in this case APIs
  • 152 |
  • RESTful Web services allow the requesting systems to access and manipulate textual representations of Web resources by using a uniform and predefined set of stateless operations
  • 153 |
  • An API call usually consists of the sever name, followed by the requested resource and then some parameters
  • 154 |
155 |
156 |
157 |
158 |

Version Control Basics


159 |

Using GIT

160 |
161 |
162 |
163 |

VERSION CONTROL

164 |
    165 |
  • A Control System is simply a tool that tracks and stores content
  • 166 |
  • Version Control System then is a system for keeping track of code and the changes that have been made to it
  • 167 |
  • Git is a distributed version control system that developers worldwide use to maintain a history of changes made to their code
  • 168 |
  • A distributed version control system is one where the code is stored on the developer's computer as well as on a remote server. It is stored on what is called a repository
  • 169 |
  • Basically a repository is is like a folder for your project. Your project's repository contains all of your project's files and stores each file's revision history
  • 170 |
171 |
172 |
173 |

FEATURES OF GIT

174 |
    175 |
  • Distributed System: 176 | Distributed systems are those which allow the users to perform work on a project from all over the world. Having a distributed system, Git allows the users to work simultaneously on the same project, without interfering with others’ work. 177 | When a particular user gets done with their part of the code, they push the changes to the repository and these changes get updated in the local copy of every other remote user which pulls the latest copy of the project.
  • 178 |
  • Compatibility: 179 | Git is compatible with all the Operating Systems that are being used these days. Git repositories can also access the repositories of other Version Control Systems like SVN, CVK, etc. 180 | Git can directly access the remote repositories created by these SVNs.
  • 181 |
  • Non-linear Development: 182 | Git allows users from all over the world to perform operations on a project remotely. A user can pick up any part of the project and do the required operation and then further update the project. 183 | This can be done by the Non-linear development behavior of the Git.
  • 184 |
185 |
186 |
187 |

FEATURES OF GIT contd

188 |
    189 |
  • Branching: 190 | Git allows its users to work on a line that runs parallel to the main project files. These lines are called branches. Branches in Git provide a feature to make changes in the project without affecting the original version. 191 | The master branch of a version will always contain the production quality code. 192 | Any new feature can be tested and worked upon on the branches and further, it can be merged with the master branch.
  • 193 |
  • Lightwieght: 194 | Git stores all the data from the central repository on to the local repository while cloning is done. There might be hundreds of users working on the same project and hence the data in the central repository might be very huge. 195 | Git follows the criteria of lossless compression that compresses the data and stores it in the local repository occupying very minimal space. 196 | Whenever there is a need for this data, it follows the reverse technique and saves a lot of memory space.
  • 197 |
198 |
199 |
200 |

ADVANTAGES OF GIT

201 |
    202 |
  • Performance: Git provides the best performance when it comes to version control systems.
  • 203 |
  • Security: Git handles your security with cryptographic method SHA-1. The algorithm manages your versions, files, and directory securely so that your work is not corrupted.
  • 204 |
  • Branching Model: Git branching model lets you have multiple local branches which are independent of each other.
  • 205 |
  • Staging Area: Git has an intermediate stage called “index” or “staging area” where commits can be formatted and modified before completing the commit..
  • 206 |
  • Open Source: Being open source invites the developers from all over the world to contribute to the software and make it more and more powerful through features and additional plugins.
  • 207 |
208 |
209 |
210 |

USING GIT

211 |
212 |

Download Git

213 |

This link has details on how to install Git in multiple operating systems:

214 |
https://git-scm.com/book/en/v2/Getting-Started-Installing-Git
215 |

Verify if Git is installed by using the following command in the terminal:

216 |
git --version
217 |

Create your local Git repository:

218 | In your computer, create a folder for your project. Let’s call the project folder git-demo. 219 | Go into your project folder and add a local Git repository to the project using the following commands: 220 |
cd git-demo
git init
221 |
222 |
223 |
224 |

USING GIT contd

225 |
226 |
    227 |
  • Create a file named "demo.txt" (For demo purposes hence it will not contain actual code) and add the following text 228 |
    This is a random sentence
  • 229 |
  • Basic Git Commands 230 |
      231 |
    • Staging: This command is used to stage the file 232 |
      git add demo.txt
    • 233 |
    • Committing: This command is used to commit the file 234 |
      git commit -m "Initial commit
      The -m flag indicates a message that describes the changes that have been made to the file, in this case "Initial Commit". 235 |
    • 236 |
    237 |
  • 238 |
239 |
240 |
241 |
242 |

Basic Git Commands contd

243 |
244 |
    245 |
  • Status: This command is used to find out information regarding what files are modified and what files are there in the staging area as well as other information 246 |
    git status
  • 247 |
  • Log: This command is used to print out all the commits which have been done up till now 248 |
    git log
    The log shows the author of each commit, the date of the commit, and the commit message.
  • 249 |
250 |
251 |
252 |
253 |

Basic Git Commands contd

254 |

Working WIth Branches

255 |
256 |
    257 |
  • Create a New Branch in Local: Here you'll create a new branch called let's say 'demobranch' 258 |
    git branch demoBranch 
  • 259 |
  • To switch from the master branch to 'demoBranch' use 260 |
    git checkout demobranch
    261 |
  • You can list out all the branches in local using the following command: 262 |
    git branch
    263 |
264 |
265 |
266 |
267 |

Basic Git Commands contd

268 |

Working WIth Branches(Merging)

269 |
270 |
    271 |
  • First go back to master branch 272 |
    git checkout master 
  • 273 |
  • Then run the merge command 274 |
    git merge demoBranch
    275 |
  • You can list out all the branches in local using the following command: 276 |
    git branch
    277 |
278 |
279 |
280 |
281 |

Git vs Github

282 |
    283 |
  • Github is basically a git repository hosting service
  • 284 |
  • It is an online database that allows you to keep track of and share your Git version control projects outside of your local computer/server.
  • 285 |
  • To differentiate between Git and Github in simple terms, Git is a version control system that lets you manage and keep track of your source code history whereas GitHub is a cloud-based hosting service that lets you manage Git repositories. 286 |
287 |
288 |
289 |
290 |

Understanding How Web Browsers Work


291 |
292 |
293 |
294 |

WHAT IS A WEB BROWSER?

295 |
296 |
    297 |
  • A browser is a software application used to locate, retrieve and display content on the World Wide Web, including Web pages, images, video and other files.
  • 298 |
  • In a Client/Server Relationship, the browser is the client running on a computer that makes requests to the web server and displays results for the user.
  • 299 |
  • Modern day browsers are fully functional sutites that can interpret and display various forms of web resources like HTML Web pages, applications, JavaScript, AJAX and other content hosted on Web servers.
  • 300 |
  • Many browsers offer plug-ins which extend the capabilities of the software
  • 301 |
  • Examples of browsers are Google Chrome, Mozilla Firefox, Safari, Opera, Internet Explorer etc.
  • 302 |
303 |
304 |
305 |

ARCHITECTURE OF BROWSERS

306 |

High Level Architecture


307 |
308 | 309 |

High Level Browser Architecture

310 |
311 |
312 |
313 |

High Level Architecturecontd

314 |
315 |
    316 |
  • The User Interface: The user interface is the space where User interacts with the browser. 317 | It includes the address bar, back and next buttons, home button, refresh and stop, bookmark option, etc.
  • 318 |
  • The Browser Engine: The browser engine works as a bridge between the User interface and the rendering engine. 319 | According to the inputs from various user interfaces, it queries and manipulates the rendering engine.
  • 320 |
  • The Rendering Engine: The rendering engine, as the name suggests is responsible for rendering the requested web page on the browser screen. 321 | The rendering engine interprets the HTML, XML documents and images that are formatted using CSS and generates the layout that is displayed in the User Interface.
  • 322 |
  • Networking: Component of the browser which retrieves the URLs using the common internet protocols of HTTP or FTP. The networking component handles all aspects of Internet communication and security.
  • 323 |
324 |
325 |
326 |
327 |

High Level Architecturecontd

328 |
329 |
    330 |
  • JavaScript Interpreter: It is the component of the browser which interprets and executes the javascript code embedded in a website. 331 | The interpreted results are sent to the rendering engine for display.
  • 332 |
  • UI Backend: UI backend is used for drawing basic widgets like combo boxes and windows. This backend exposes a generic interface that is not platform specific. 333 | It underneath uses operating system user interface methods.
  • 334 |
  • Data Persistence/Storage: This is a persistence layer. Browsers support storage mechanisms such as localStorage, IndexedDB, WebSQL and FileSystem. It is a small database created on the local drive of the computer where the browser is installed. 335 | It manages user data such as cache, cookies, bookmarks and preferences.
  • 336 |
337 |
338 |
339 |
340 |

Rendering Engine

341 |
342 |
    343 |
  • The networking layer will start sending the contents of the requested documents to the rendering engine in chunks of 8KBs.
  • 344 |
  • The rendering engine parses the chunks of HTML document and convert the elements to DOM nodes in a tree called the “content tree” or the “DOM tree”.
  • 345 |
  • It also parses both the external CSS files as well in style elements.
  • 346 |
  • While the DOM tree is being constructed, the browser constructs another tree, the render tree. It is the visual representation of the document.
  • 347 |
  • The purpose of this tree is to enable painting the contents in their correct order.
  • 348 |
349 |
350 |
351 |
352 |

Rendering Engine contd

353 |
354 |
    355 |
  • After the construction of the render tree, it goes through a “layout process” of the render tree.
  • 356 |
  • When the renderer is created and added to the tree, it does not have a position and size. The process of calculating these values is called layout or reflow.
  • 357 |
  • All renderers have a “layout” or “reflow” method, each renderer invokes the layout method of its children that need layout.
  • 358 |
  • The next stage is painting.
  • 359 |
  • In the painting stage, the render tree is traversed and the renderer’s “paint()” method is called to display content on the screen. Painting uses the UI backend layer.
  • 360 |
361 |
362 |
363 |
364 |

Rendering Engine contd

365 |
366 |
    367 |
  • The rendering engine always tries to display the contents on the screen as soon as possible for better user experience.
  • 368 |
  • It does not wait for the HTML parsing to complete before starting to build and layout the render tree.
  • 369 |
  • It parses and displays the content it has received from the network, while rest of the contents stills keeps coming from the network.
  • 370 |
371 |
372 |
373 |
374 |
375 |

HTML
&
CSS

376 |
377 |
378 |
379 |

HTML

380 |
381 |
    382 |
  • HTML stands for HyperText Markup Language
  • 383 |
  • It is a format that tells a computer how to display a web page.
  • 384 |
  • The documents themselves are plain text files with special "tags" or codes that a web browser uses to interpret and display information on your computer screen.
  • 385 |
  • An HTML file must have a .htm or .html extension
  • 386 | 387 |
388 |
389 |
390 |
391 |

Structure of an HTML Document

392 |
393 |

394 |             <!Doctype html>
395 |             <html>
396 |             <head>
397 |                 <title>
398 |                 .
399 |             </head>
400 |             <body>
401 |                 .
402 |                 .
403 |                 .
404 |                 .
405 |                 .
406 |             </body>
407 |             </html>
408 |             
409 |

Basic Structure of An HTML Document

410 |
411 | 412 |
413 |
414 |

Structure of an HTML Document contd

415 |

The previous slide shows a skeleton html document. This is the minimum required information for a web document and all web documents should contain these basic components.

416 |
    417 |
  • <!doctype html>: This tells the browser what kind of document to expect
  • 418 |
  • <html>: This indicates the start of the html document.The last tag in your document is </html> which tells the browser that this is the end of the html document.
  • 419 |
  • <header></header>: The text between these tags is header information. Header information is not displayed in the browser window. 420 |
    • <title></title>: The text written within these tags is the title of the webpage that is displayed inside the browser tab
    421 |
  • 422 |
423 |
424 |
425 |

Structure of an HTML Document contd

426 |
    427 |
  • <body></body>: This contains the text, images, audio and other forms of media that will be displayed within the browser window. There are several tags that can be used here to achieve different purposes. 428 | Some examples are below; 429 |
      430 |
    • <h1></h1>: This is used to indicate the most important or highest level text on a page
    • 431 |
    • <p></p>: This represents a paragraph
    • 432 |
    • <div></div>: This defines a division or section of the page
    • 433 |
    • <img></img>: This is used to embed an image on the page/li> 434 |
    • <br>: This defines a line break. It used to move content to the next line
    • 435 |
    436 |
  • 437 |
438 |
439 |
440 |

HTML Tag vs HTML Element

441 |
    442 |
  • HTML tags are surrounded by the two characters < and >
  • 443 |
  • The tags normally come in pairs like <b> and </b>
  • 444 |
  • The first tag in a pair is the start tag, the second tag is the end tag
  • 445 |
  • An HTML element however is a tag that has some content in it
  • 446 |
  • The content can be text or some other tags
  • 447 |
  • Below is an example of an html element
    <p>This is an element</p>
  • 448 |
449 |
450 |
451 |

CSS

452 |
    453 |
  • CSS stands for Cascading Stylesheets
  • 454 |
  • CSS allows you to create rules that specify how the content of an element should appear.
  • 455 |
  • CSS works by associating rules with HTML elements.
  • 456 |
  • A CSS rule contains two parts: a selector and a declaration.
  • 457 |
  • For example: 458 |
    459 |                 p{ font-family: Arial; }
    460 |             
    461 |
  • 462 |
  • p is the selector and font-family: Arial is a declaration
  • 463 |
464 |
465 |
466 |

CSS contd

467 |
    468 |
  • The CSS rule in the previous slide indicates that all <p> elements should be shown in the arial typeface
  • 469 |
  • Selectors: indicate which element the rule applies to. The same rule can apply to more than one element if you separate the element names with commas.
  • 470 |
  • Declaration: indicate how the elements referred to in the selector should be styled. Declarations are split into two parts (a property and a value), and are separated by a colon.
  • 471 |
  • CSS rules can be
      472 |
    1. Written in the opening tag of an html element
    2. 473 |
    3. Written in the <head> tag
    4. 474 |
    5. Written in a different file and the file then linked to the hmtl document
    6. 475 |
  • 476 |
477 |
478 |
479 |
480 | 481 |
482 |
483 | 484 |
485 | 486 | 487 | 488 | 489 | 490 | 491 | 492 | 493 | 494 | -------------------------------------------------------------------------------- /Web _Tech_Slides/js/highlight.pack.js: -------------------------------------------------------------------------------- 1 | /*! highlight.js v9.3.0 | 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(e){function n(e){return e.replace(/&/gm,"&").replace(//gm,">")}function t(e){return e.nodeName.toLowerCase()}function r(e,n){var t=e&&e.exec(n);return t&&0==t.index}function a(e){return/^(no-?highlight|plain|text)$/i.test(e)}function i(e){var n,t,r,i=e.className+" ";if(i+=e.parentNode?e.parentNode.className:"",t=/\blang(?:uage)?-([\w-]+)\b/i.exec(i))return w(t[1])?t[1]:"no-highlight";for(i=i.split(/\s+/),n=0,r=i.length;r>n;n++)if(w(i[n])||a(i[n]))return i[n]}function o(e,n){var t,r={};for(t in e)r[t]=e[t];if(n)for(t in n)r[t]=n[t];return r}function u(e){var n=[];return function r(e,a){for(var i=e.firstChild;i;i=i.nextSibling)3==i.nodeType?a+=i.nodeValue.length:1==i.nodeType&&(n.push({event:"start",offset:a,node:i}),a=r(i,a),t(i).match(/br|hr|img|input/)||n.push({event:"stop",offset:a,node:i}));return a}(e,0),n}function c(e,r,a){function i(){return e.length&&r.length?e[0].offset!=r[0].offset?e[0].offset"}function u(e){f+=""}function c(e){("start"==e.event?o:u)(e.node)}for(var s=0,f="",l=[];e.length||r.length;){var g=i();if(f+=n(a.substr(s,g[0].offset-s)),s=g[0].offset,g==e){l.reverse().forEach(u);do c(g.splice(0,1)[0]),g=i();while(g==e&&g.length&&g[0].offset==s);l.reverse().forEach(o)}else"start"==g[0].event?l.push(g[0].node):l.pop(),c(g.splice(0,1)[0])}return f+n(a.substr(s))}function s(e){function n(e){return e&&e.source||e}function t(t,r){return new RegExp(n(t),"m"+(e.cI?"i":"")+(r?"g":""))}function r(a,i){if(!a.compiled){if(a.compiled=!0,a.k=a.k||a.bK,a.k){var u={},c=function(n,t){e.cI&&(t=t.toLowerCase()),t.split(" ").forEach(function(e){var t=e.split("|");u[t[0]]=[n,t[1]?Number(t[1]):1]})};"string"==typeof a.k?c("keyword",a.k):Object.keys(a.k).forEach(function(e){c(e,a.k[e])}),a.k=u}a.lR=t(a.l||/\w+/,!0),i&&(a.bK&&(a.b="\\b("+a.bK.split(" ").join("|")+")\\b"),a.b||(a.b=/\B|\b/),a.bR=t(a.b),a.e||a.eW||(a.e=/\B|\b/),a.e&&(a.eR=t(a.e)),a.tE=n(a.e)||"",a.eW&&i.tE&&(a.tE+=(a.e?"|":"")+i.tE)),a.i&&(a.iR=t(a.i)),void 0===a.r&&(a.r=1),a.c||(a.c=[]);var s=[];a.c.forEach(function(e){e.v?e.v.forEach(function(n){s.push(o(e,n))}):s.push("self"==e?a:e)}),a.c=s,a.c.forEach(function(e){r(e,a)}),a.starts&&r(a.starts,i);var f=a.c.map(function(e){return e.bK?"\\.?("+e.b+")\\.?":e.b}).concat([a.tE,a.i]).map(n).filter(Boolean);a.t=f.length?t(f.join("|"),!0):{exec:function(){return null}}}}r(e)}function f(e,t,a,i){function o(e,n){for(var t=0;t";return i+=e+'">',i+n+o}function h(){if(!k.k)return n(M);var e="",t=0;k.lR.lastIndex=0;for(var r=k.lR.exec(M);r;){e+=n(M.substr(t,r.index-t));var a=g(k,r);a?(B+=a[1],e+=p(a[0],n(r[0]))):e+=n(r[0]),t=k.lR.lastIndex,r=k.lR.exec(M)}return e+n(M.substr(t))}function d(){var e="string"==typeof k.sL;if(e&&!R[k.sL])return n(M);var t=e?f(k.sL,M,!0,y[k.sL]):l(M,k.sL.length?k.sL:void 0);return k.r>0&&(B+=t.r),e&&(y[k.sL]=t.top),p(t.language,t.value,!1,!0)}function b(){L+=void 0!==k.sL?d():h(),M=""}function v(e,n){L+=e.cN?p(e.cN,"",!0):"",k=Object.create(e,{parent:{value:k}})}function m(e,n){if(M+=e,void 0===n)return b(),0;var t=o(n,k);if(t)return t.skip?M+=n:(t.eB&&(M+=n),b(),t.rB||t.eB||(M=n)),v(t,n),t.rB?0:n.length;var r=u(k,n);if(r){var a=k;a.skip?M+=n:(a.rE||a.eE||(M+=n),b(),a.eE&&(M=n));do k.cN&&(L+="
"),k.skip||(B+=k.r),k=k.parent;while(k!=r.parent);return r.starts&&v(r.starts,""),a.rE?0:n.length}if(c(n,k))throw new Error('Illegal lexeme "'+n+'" for mode "'+(k.cN||"")+'"');return M+=n,n.length||1}var N=w(e);if(!N)throw new Error('Unknown language: "'+e+'"');s(N);var x,k=i||N,y={},L="";for(x=k;x!=N;x=x.parent)x.cN&&(L=p(x.cN,"",!0)+L);var M="",B=0;try{for(var C,j,I=0;;){if(k.t.lastIndex=I,C=k.t.exec(t),!C)break;j=m(t.substr(I,C.index-I),C[0]),I=C.index+j}for(m(t.substr(I)),x=k;x.parent;x=x.parent)x.cN&&(L+="");return{r:B,value:L,language:e,top:k}}catch(O){if(-1!=O.message.indexOf("Illegal"))return{r:0,value:n(t)};throw O}}function l(e,t){t=t||E.languages||Object.keys(R);var r={r:0,value:n(e)},a=r;return t.filter(w).forEach(function(n){var t=f(n,e,!1);t.language=n,t.r>a.r&&(a=t),t.r>r.r&&(a=r,r=t)}),a.language&&(r.second_best=a),r}function g(e){return E.tabReplace&&(e=e.replace(/^((<[^>]+>|\t)+)/gm,function(e,n){return n.replace(/\t/g,E.tabReplace)})),E.useBR&&(e=e.replace(/\n/g,"
")),e}function p(e,n,t){var r=n?x[n]:t,a=[e.trim()];return e.match(/\bhljs\b/)||a.push("hljs"),-1===e.indexOf(r)&&a.push(r),a.join(" ").trim()}function h(e){var n=i(e);if(!a(n)){var t;E.useBR?(t=document.createElementNS("http://www.w3.org/1999/xhtml","div"),t.innerHTML=e.innerHTML.replace(/\n/g,"").replace(//g,"\n")):t=e;var r=t.textContent,o=n?f(n,r,!0):l(r),s=u(t);if(s.length){var h=document.createElementNS("http://www.w3.org/1999/xhtml","div");h.innerHTML=o.value,o.value=c(s,u(h),r)}o.value=g(o.value),e.innerHTML=o.value,e.className=p(e.className,n,o.language),e.result={language:o.language,re:o.r},o.second_best&&(e.second_best={language:o.second_best.language,re:o.second_best.r})}}function d(e){E=o(E,e)}function b(){if(!b.called){b.called=!0;var e=document.querySelectorAll("pre code");Array.prototype.forEach.call(e,h)}}function v(){addEventListener("DOMContentLoaded",b,!1),addEventListener("load",b,!1)}function m(n,t){var r=R[n]=t(e);r.aliases&&r.aliases.forEach(function(e){x[e]=n})}function N(){return Object.keys(R)}function w(e){return e=(e||"").toLowerCase(),R[e]||R[x[e]]}var E={classPrefix:"hljs-",tabReplace:null,useBR:!1,languages:void 0},R={},x={};return e.highlight=f,e.highlightAuto=l,e.fixMarkup=g,e.highlightBlock=h,e.configure=d,e.initHighlighting=b,e.initHighlightingOnLoad=v,e.registerLanguage=m,e.listLanguages=N,e.getLanguage=w,e.inherit=o,e.IR="[a-zA-Z]\\w*",e.UIR="[a-zA-Z_]\\w*",e.NR="\\b\\d+(\\.\\d+)?",e.CNR="(-?)(\\b0[xX][a-fA-F0-9]+|(\\b\\d+(\\.\\d*)?|\\.\\d+)([eE][-+]?\\d+)?)",e.BNR="\\b(0b[01]+)",e.RSR="!|!=|!==|%|%=|&|&&|&=|\\*|\\*=|\\+|\\+=|,|-|-=|/=|/|:|;|<<|<<=|<=|<|===|==|=|>>>=|>>=|>=|>>>|>>|>|\\?|\\[|\\{|\\(|\\^|\\^=|\\||\\|=|\\|\\||~",e.BE={b:"\\\\[\\s\\S]",r:0},e.ASM={cN:"string",b:"'",e:"'",i:"\\n",c:[e.BE]},e.QSM={cN:"string",b:'"',e:'"',i:"\\n",c:[e.BE]},e.PWM={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|like)\b/},e.C=function(n,t,r){var a=e.inherit({cN:"comment",b:n,e:t,c:[]},r||{});return a.c.push(e.PWM),a.c.push({cN:"doctag",b:"(?:TODO|FIXME|NOTE|BUG|XXX):",r:0}),a},e.CLCM=e.C("//","$"),e.CBCM=e.C("/\\*","\\*/"),e.HCM=e.C("#","$"),e.NM={cN:"number",b:e.NR,r:0},e.CNM={cN:"number",b:e.CNR,r:0},e.BNM={cN:"number",b:e.BNR,r:0},e.CSSNM={cN:"number",b:e.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},e.RM={cN:"regexp",b:/\//,e:/\/[gimuy]*/,i:/\n/,c:[e.BE,{b:/\[/,e:/\]/,r:0,c:[e.BE]}]},e.TM={cN:"title",b:e.IR,r:0},e.UTM={cN:"title",b:e.UIR,r:0},e.METHOD_GUARD={b:"\\.\\s*"+e.UIR,r:0},e});hljs.registerLanguage("perl",function(e){var t="getpwent getservent quotemeta msgrcv scalar kill dbmclose undef lc ma syswrite tr send umask sysopen shmwrite vec qx utime local oct semctl localtime readpipe do return format read sprintf dbmopen pop getpgrp not getpwnam rewinddir qqfileno qw endprotoent wait sethostent bless s|0 opendir continue each sleep endgrent shutdown dump chomp connect getsockname die socketpair close flock exists index shmgetsub for endpwent redo lstat msgctl setpgrp abs exit select print ref gethostbyaddr unshift fcntl syscall goto getnetbyaddr join gmtime symlink semget splice x|0 getpeername recv log setsockopt cos last reverse gethostbyname getgrnam study formline endhostent times chop length gethostent getnetent pack getprotoent getservbyname rand mkdir pos chmod y|0 substr endnetent printf next open msgsnd readdir use unlink getsockopt getpriority rindex wantarray hex system getservbyport endservent int chr untie rmdir prototype tell listen fork shmread ucfirst setprotoent else sysseek link getgrgid shmctl waitpid unpack getnetbyname reset chdir grep split require caller lcfirst until warn while values shift telldir getpwuid my getprotobynumber delete and sort uc defined srand accept package seekdir getprotobyname semop our rename seek if q|0 chroot sysread setpwent no crypt getc chown sqrt write setnetent setpriority foreach tie sin msgget map stat getlogin unless elsif truncate exec keys glob tied closedirioctl socket readlink eval xor readline binmode setservent eof ord bind alarm pipe atan2 getgrent exp time push setgrent gt lt or ne m|0 break given say state when",r={cN:"subst",b:"[$@]\\{",e:"\\}",k:t},s={b:"->{",e:"}"},n={v:[{b:/\$\d/},{b:/[\$%@](\^\w\b|#\w+(::\w+)*|{\w+}|\w+(::\w*)*)/},{b:/[\$%@][^\s\w{]/,r:0}]},i=[e.BE,r,n],o=[n,e.HCM,e.C("^\\=\\w","\\=cut",{eW:!0}),s,{cN:"string",c:i,v:[{b:"q[qwxr]?\\s*\\(",e:"\\)",r:5},{b:"q[qwxr]?\\s*\\[",e:"\\]",r:5},{b:"q[qwxr]?\\s*\\{",e:"\\}",r:5},{b:"q[qwxr]?\\s*\\|",e:"\\|",r:5},{b:"q[qwxr]?\\s*\\<",e:"\\>",r:5},{b:"qw\\s+q",e:"q",r:5},{b:"'",e:"'",c:[e.BE]},{b:'"',e:'"'},{b:"`",e:"`",c:[e.BE]},{b:"{\\w+}",c:[],r:0},{b:"-?\\w+\\s*\\=\\>",c:[],r:0}]},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\/\\/|"+e.RSR+"|\\b(split|return|print|reverse|grep)\\b)\\s*",k:"split return print reverse grep",r:0,c:[e.HCM,{cN:"regexp",b:"(s|tr|y)/(\\\\.|[^/])*/(\\\\.|[^/])*/[a-z]*",r:10},{cN:"regexp",b:"(m|qr)?/",e:"/[a-z]*",c:[e.BE],r:0}]},{cN:"function",bK:"sub",e:"(\\s*\\(.*?\\))?[;{]",eE:!0,r:5,c:[e.TM]},{b:"-\\w\\b",r:0},{b:"^__DATA__$",e:"^__END__$",sL:"mojolicious",c:[{b:"^@@.*",e:"$",cN:"comment"}]}];return r.c=o,s.c=o,{aliases:["pl","pm"],l:/[\w\.]+/,k:t,c:o}});hljs.registerLanguage("java",function(e){var t=e.UIR+"(<"+e.UIR+"(\\s*,\\s*"+e.UIR+")*>)?",a="false synchronized int abstract float private char boolean static null if const for true while long strictfp finally protected import native final void enum else break transient catch instanceof byte super volatile case assert short package default double public try this switch continue throws protected public private module requires exports",r="\\b(0[bB]([01]+[01_]+[01]+|[01]+)|0[xX]([a-fA-F0-9]+[a-fA-F0-9_]+[a-fA-F0-9]+|[a-fA-F0-9]+)|(([\\d]+[\\d_]+[\\d]+|[\\d]+)(\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))?|\\.([\\d]+[\\d_]+[\\d]+|[\\d]+))([eE][-+]?\\d+)?)[lLfF]?",s={cN:"number",b:r,r:0};return{aliases:["jsp"],k:a,i:/<\/|#/,c:[e.C("/\\*\\*","\\*/",{r:0,c:[{b:/\w+@/,r:0},{cN:"doctag",b:"@[A-Za-z]+"}]}),e.CLCM,e.CBCM,e.ASM,e.QSM,{cN:"class",bK:"class interface",e:/[{;=]/,eE:!0,k:"class interface",i:/[:"\[\]]/,c:[{bK:"extends implements"},e.UTM]},{bK:"new throw return else",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.UIR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:a,c:[{b:e.UIR+"\\s*\\(",rB:!0,r:0,c:[e.UTM]},{cN:"params",b:/\(/,e:/\)/,k:a,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]},s,{cN:"meta",b:"@[A-Za-z]+"}]}});hljs.registerLanguage("json",function(e){var i={literal:"true false null"},n=[e.QSM,e.CNM],r={e:",",eW:!0,eE:!0,c:n,k:i},t={b:"{",e:"}",c:[{cN:"attr",b:/"/,e:/"/,c:[e.BE],i:"\\n"},e.inherit(r,{b:/:/})],i:"\\S"},c={b:"\\[",e:"\\]",c:[e.inherit(r)],i:"\\S"};return n.splice(n.length,0,t,c),{c:n,k:i,i:"\\S"}});hljs.registerLanguage("javascript",function(e){return{aliases:["js","jsx"],k:{keyword:"in of if for while finally var new function do return void else break catch instanceof with throw case default try this switch continue typeof delete let yield const export super debugger as async await static import from as",literal:"true false null undefined NaN Infinity",built_in:"eval isFinite isNaN parseFloat parseInt decodeURI decodeURIComponent encodeURI encodeURIComponent escape unescape Object Function Boolean Error EvalError InternalError RangeError ReferenceError StopIteration SyntaxError TypeError URIError Number Math Date String RegExp Array Float32Array Float64Array Int16Array Int32Array Int8Array Uint16Array Uint32Array Uint8Array Uint8ClampedArray ArrayBuffer DataView JSON Intl arguments require module console window document Symbol Set Map WeakSet WeakMap Proxy Reflect Promise"},c:[{cN:"meta",r:10,b:/^\s*['"]use (strict|asm)['"]/},{cN:"meta",b:/^#!/,e:/$/},e.ASM,e.QSM,{cN:"string",b:"`",e:"`",c:[e.BE,{cN:"subst",b:"\\$\\{",e:"\\}"}]},e.CLCM,e.CBCM,{cN:"number",v:[{b:"\\b(0[bB][01]+)"},{b:"\\b(0[oO][0-7]+)"},{b:e.CNR}],r:0},{b:"("+e.RSR+"|\\b(case|return|throw)\\b)\\s*",k:"return throw case",c:[e.CLCM,e.CBCM,e.RM,{b://,sL:"xml",c:[{b:/<\w+\s*\/>/,skip:!0},{b:/<\w+/,e:/(\/\w+|\w+\/)>/,skip:!0,c:["self"]}]}],r:0},{cN:"function",bK:"function",e:/\{/,eE:!0,c:[e.inherit(e.TM,{b:/[A-Za-z$_][0-9A-Za-z$_]*/}),{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,c:[e.CLCM,e.CBCM]}],i:/\[|%/},{b:/\$[(.]/},e.METHOD_GUARD,{cN:"class",bK:"class",e:/[{;=]/,eE:!0,i:/[:"\[\]]/,c:[{bK:"extends"},e.UTM]},{bK:"constructor",e:/\{/,eE:!0}],i:/#(?!!)/}});hljs.registerLanguage("php",function(e){var c={b:"\\$+[a-zA-Z_-ÿ][a-zA-Z0-9_-ÿ]*"},a={cN:"meta",b:/<\?(php)?|\?>/},i={cN:"string",c:[e.BE,a],v:[{b:'b"',e:'"'},{b:"b'",e:"'"},e.inherit(e.ASM,{i:null}),e.inherit(e.QSM,{i:null})]},t={v:[e.BNM,e.CNM]};return{aliases:["php3","php4","php5","php6"],cI:!0,k:"and include_once list abstract global private echo interface as static endswitch array null if endwhile or const for endforeach self var while isset public protected exit foreach throw elseif include __FILE__ empty require_once do xor return parent clone use __CLASS__ __LINE__ else break print eval new catch __METHOD__ case exception default die require __FUNCTION__ enddeclare final try switch continue endfor endif declare unset true false trait goto instanceof insteadof __DIR__ __NAMESPACE__ yield finally",c:[e.HCM,e.C("//","$",{c:[a]}),e.C("/\\*","\\*/",{c:[{cN:"doctag",b:"@[A-Za-z]+"}]}),e.C("__halt_compiler.+?;",!1,{eW:!0,k:"__halt_compiler",l:e.UIR}),{cN:"string",b:/<<<['"]?\w+['"]?$/,e:/^\w+;?$/,c:[e.BE,{cN:"subst",v:[{b:/\$\w+/},{b:/\{\$/,e:/\}/}]}]},a,c,{b:/(::|->)+[a-zA-Z_\x7f-\xff][a-zA-Z0-9_\x7f-\xff]*/},{cN:"function",bK:"function",e:/[;{]/,eE:!0,i:"\\$|\\[|%",c:[e.UTM,{cN:"params",b:"\\(",e:"\\)",c:["self",c,e.CBCM,i,t]}]},{cN:"class",bK:"class interface",e:"{",eE:!0,i:/[:\(\$"]/,c:[{bK:"extends implements"},e.UTM]},{bK:"namespace",e:";",i:/[\.']/,c:[e.UTM]},{bK:"use",e:";",c:[e.UTM]},{b:"=>"},i,t]}});hljs.registerLanguage("ruby",function(e){var r="[a-zA-Z_]\\w*[!?=]?|[-+~]\\@|<<|>>|=~|===?|<=>|[<>]=?|\\*\\*|[-/+%^&*~`|]|\\[\\]=?",b={keyword:"and then defined module in return redo if BEGIN retry end for self when next until do begin unless END rescue else break undef not super class case require yield alias while ensure elsif or include attr_reader attr_writer attr_accessor",literal:"true false nil"},c={cN:"doctag",b:"@[A-Za-z]+"},a={b:"#<",e:">"},s=[e.C("#","$",{c:[c]}),e.C("^\\=begin","^\\=end",{c:[c],r:10}),e.C("^__END__","\\n$")],n={cN:"subst",b:"#\\{",e:"}",k:b},t={cN:"string",c:[e.BE,n],v:[{b:/'/,e:/'/},{b:/"/,e:/"/},{b:/`/,e:/`/},{b:"%[qQwWx]?\\(",e:"\\)"},{b:"%[qQwWx]?\\[",e:"\\]"},{b:"%[qQwWx]?{",e:"}"},{b:"%[qQwWx]?<",e:">"},{b:"%[qQwWx]?/",e:"/"},{b:"%[qQwWx]?%",e:"%"},{b:"%[qQwWx]?-",e:"-"},{b:"%[qQwWx]?\\|",e:"\\|"},{b:/\B\?(\\\d{1,3}|\\x[A-Fa-f0-9]{1,2}|\\u[A-Fa-f0-9]{4}|\\?\S)\b/}]},i={cN:"params",b:"\\(",e:"\\)",endsParent:!0,k:b},d=[t,a,{cN:"class",bK:"class module",e:"$|;",i:/=/,c:[e.inherit(e.TM,{b:"[A-Za-z_]\\w*(::\\w+)*(\\?|\\!)?"}),{b:"<\\s*",c:[{b:"("+e.IR+"::)?"+e.IR}]}].concat(s)},{cN:"function",bK:"def",e:"$|;",c:[e.inherit(e.TM,{b:r}),i].concat(s)},{b:e.IR+"::"},{cN:"symbol",b:e.UIR+"(\\!|\\?)?:",r:0},{cN:"symbol",b:":(?!\\s)",c:[t,{b:r}],r:0},{cN:"number",b:"(\\b0[0-7_]+)|(\\b0x[0-9a-fA-F_]+)|(\\b[1-9][0-9_]*(\\.[0-9_]+)?)|[0_]\\b",r:0},{b:"(\\$\\W)|((\\$|\\@\\@?)(\\w+))"},{cN:"params",b:/\|/,e:/\|/,k:b},{b:"("+e.RSR+")\\s*",c:[a,{cN:"regexp",c:[e.BE,n],i:/\n/,v:[{b:"/",e:"/[a-z]*"},{b:"%r{",e:"}[a-z]*"},{b:"%r\\(",e:"\\)[a-z]*"},{b:"%r!",e:"![a-z]*"},{b:"%r\\[",e:"\\][a-z]*"}]}].concat(s),r:0}].concat(s);n.c=d,i.c=d;var l="[>?]>",o="[\\w#]+\\(\\w+\\):\\d+:\\d+>",u="(\\w+-)?\\d+\\.\\d+\\.\\d(p\\d+)?[^>]+>",w=[{b:/^\s*=>/,starts:{e:"$",c:d}},{cN:"meta",b:"^("+l+"|"+o+"|"+u+")",starts:{e:"$",c:d}}];return{aliases:["rb","gemspec","podspec","thor","irb"],k:b,i:/\/\*/,c:s.concat(w).concat(d)}});hljs.registerLanguage("makefile",function(e){var a={cN:"variable",b:/\$\(/,e:/\)/,c:[e.BE]};return{aliases:["mk","mak"],c:[e.HCM,{b:/^\w+\s*\W*=/,rB:!0,r:0,starts:{e:/\s*\W*=/,eE:!0,starts:{e:/$/,r:0,c:[a]}}},{cN:"section",b:/^[\w]+:\s*$/},{cN:"meta",b:/^\.PHONY:/,e:/$/,k:{"meta-keyword":".PHONY"},l:/[\.\w]+/},{b:/^\t+/,e:/$/,r:0,c:[e.QSM,a]}]}});hljs.registerLanguage("cpp",function(t){var e={cN:"keyword",b:"\\b[a-z\\d_]*_t\\b"},r={cN:"string",v:[t.inherit(t.QSM,{b:'((u8?|U)|L)?"'}),{b:'(u8?|U)?R"',e:'"',c:[t.BE]},{b:"'\\\\?.",e:"'",i:"."}]},i={cN:"number",v:[{b:"\\b(\\d+(\\.\\d*)?|\\.\\d+)(u|U|l|L|ul|UL|f|F)"},{b:t.CNR}],r:0},s={cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line pragma ifdef ifndef"},c:[{b:/\\\n/,r:0},{bK:"include",e:"$",k:{"meta-keyword":"include"},c:[t.inherit(r,{cN:"meta-string"}),{cN:"meta-string",b:"<",e:">",i:"\\n"}]},r,t.CLCM,t.CBCM]},a=t.IR+"\\s*\\(",c={keyword:"int float while private char catch export virtual operator sizeof dynamic_cast|10 typedef const_cast|10 const struct 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 class 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",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,i,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:/\)/,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,i]},t.CLCM,t.CBCM,s]}])}});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]}]},a={cN:"string",b:/'/,e:/'/};return{aliases:["sh","zsh"],l:/-?[a-z\.]+/,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,a,t]}});hljs.registerLanguage("apache",function(e){var r={cN:"number",b:"[\\$%]\\d+"};return{aliases:["apacheconf"],cI:!0,c:[e.HCM,{cN:"section",b:""},{cN:"attribute",b:/\w+/,r:0,k:{nomarkup:"order deny allow setenv rewriterule rewriteengine rewritecond documentroot sethandler errordocument loadmodule options header listen serverroot servername"},starts:{e:/$/,r:0,k:{literal:"on off all"},c:[{cN:"meta",b:"\\s\\[",e:"\\]$"},{cN:"variable",b:"[\\$%]\\{",e:"\\}",c:["self",r]},r,e.QSM]}}],i:/\S/}});hljs.registerLanguage("nginx",function(e){var r={cN:"variable",v:[{b:/\$\d+/},{b:/\$\{/,e:/}/},{b:"[\\$\\@]"+e.UIR}]},b={eW:!0,l:"[a-z/_]+",k:{literal:"on off yes no true false none blocked debug info notice warn error crit select break last permanent redirect kqueue rtsig epoll poll /dev/poll"},r:0,i:"=>",c:[e.HCM,{cN:"string",c:[e.BE,r],v:[{b:/"/,e:/"/},{b:/'/,e:/'/}]},{b:"([a-z]+):/",e:"\\s",eW:!0,eE:!0,c:[r]},{cN:"regexp",c:[e.BE,r],v:[{b:"\\s\\^",e:"\\s|{|;",rE:!0},{b:"~\\*?\\s+",e:"\\s|{|;",rE:!0},{b:"\\*(\\.[a-z\\-]+)+"},{b:"([a-z\\-]+\\.)+\\*"}]},{cN:"number",b:"\\b\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}(:\\d{1,5})?\\b"},{cN:"number",b:"\\b\\d+[kKmMgGdshdwy]*\\b",r:0},r]};return{aliases:["nginxconf"],c:[e.HCM,{b:e.UIR+"\\s+{",rB:!0,e:"{",c:[{cN:"section",b:e.UIR}],r:0},{b:e.UIR+"\\s",e:";|{",rB:!0,c:[{cN:"attribute",b:e.UIR,starts:b}],r:0}],i:"[^\\s\\}]"}});hljs.registerLanguage("coffeescript",function(e){var c={keyword:"in if for while finally new do return else break catch instanceof throw try this switch continue typeof delete debugger super then unless until loop of by when and or is isnt not",literal:"true false null undefined yes no on off",built_in:"npm require console print module global window document"},n="[A-Za-z$_][0-9A-Za-z$_]*",r={cN:"subst",b:/#\{/,e:/}/,k:c},s=[e.BNM,e.inherit(e.CNM,{starts:{e:"(\\s*/)?",r:0}}),{cN:"string",v:[{b:/'''/,e:/'''/,c:[e.BE]},{b:/'/,e:/'/,c:[e.BE]},{b:/"""/,e:/"""/,c:[e.BE,r]},{b:/"/,e:/"/,c:[e.BE,r]}]},{cN:"regexp",v:[{b:"///",e:"///",c:[r,e.HCM]},{b:"//[gim]*",r:0},{b:/\/(?![ *])(\\\/|.)*?\/[gim]*(?=\W|$)/}]},{b:"@"+n},{b:"`",e:"`",eB:!0,eE:!0,sL:"javascript"}];r.c=s;var i=e.inherit(e.TM,{b:n}),t="(\\(.*\\))?\\s*\\B[-=]>",o={cN:"params",b:"\\([^\\(]",rB:!0,c:[{b:/\(/,e:/\)/,k:c,c:["self"].concat(s)}]};return{aliases:["coffee","cson","iced"],k:c,i:/\/\*/,c:s.concat([e.C("###","###"),e.HCM,{cN:"function",b:"^\\s*"+n+"\\s*=\\s*"+t,e:"[-=]>",rB:!0,c:[i,o]},{b:/[:\(,=]\s*/,r:0,c:[{cN:"function",b:t,e:"[-=]>",rB:!0,c:[o]}]},{cN:"class",bK:"class",e:"$",i:/[:="\[\]]/,c:[{bK:"extends",eW:!0,i:/[:="\[\]]/,c:[i]},i]},{b:n+":",e:":",rB:!0,rE:!0,r:0}])}});hljs.registerLanguage("css",function(e){var c="[a-zA-Z-][a-zA-Z0-9_-]*",t={b:/[A-Z\_\.\-]+\s*:/,rB:!0,e:";",eW:!0,c:[{cN:"attribute",b:/\S/,e:":",eE:!0,starts:{eW:!0,eE:!0,c:[{b:/[\w-]+\(/,rB:!0,c:[{cN:"built_in",b:/[\w-]+/},{b:/\(/,e:/\)/,c:[e.ASM,e.QSM]}]},e.CSSNM,e.QSM,e.ASM,e.CBCM,{cN:"number",b:"#[0-9A-Fa-f]+"},{cN:"meta",b:"!important"}]}}]};return{cI:!0,i:/[=\/|'\$]/,c:[e.CBCM,{cN:"selector-id",b:/#[A-Za-z0-9_-]+/},{cN:"selector-class",b:/\.[A-Za-z0-9_-]+/},{cN:"selector-attr",b:/\[/,e:/\]/,i:"$"},{cN:"selector-pseudo",b:/:(:)?[a-zA-Z0-9\_\-\+\(\)"'.]+/},{b:"@(font-face|page)",l:"[a-z-]+",k:"font-face page"},{b:"@",e:"[{;]",i:/:/,c:[{cN:"keyword",b:/\w+/},{b:/\s/,eW:!0,eE:!0,r:0,c:[e.ASM,e.QSM,e.CSSNM]}]},{cN:"selector-tag",b:c,r:0},{b:"{",e:"}",i:/\S/,c:[e.CBCM,t]}]}});hljs.registerLanguage("xml",function(s){var e="[A-Za-z0-9\\._:-]+",t={eW:!0,i:/`]+/}]}]}]};return{aliases:["html","xhtml","rss","atom","xsl","plist"],cI:!0,c:[{cN:"meta",b:"",r:10,c:[{b:"\\[",e:"\\]"}]},s.C("",{r:10}),{b:"<\\!\\[CDATA\\[",e:"\\]\\]>",r:10},{b:/<\?(php)?/,e:/\?>/,sL:"php",c:[{b:"/\\*",e:"\\*/",skip:!0}]},{cN:"tag",b:"|$)",e:">",k:{name:"style"},c:[t],starts:{e:"",rE:!0,sL:["css","xml"]}},{cN:"tag",b:"|$)",e:">",k:{name:"script"},c:[t],starts:{e:"",rE:!0,sL:["actionscript","javascript","handlebars","xml"]}},{cN:"meta",v:[{b:/<\?xml/,e:/\?>/,r:10},{b:/<\?\w+/,e:/\?>/}]},{cN:"tag",b:"",c:[{cN:"name",b:/[^\/><\s]+/,r:0},t]}]}});hljs.registerLanguage("cs",function(e){var r={keyword:"abstract as base bool break byte case catch char checked const continue decimal dynamic default delegate do double else enum event explicit extern finally fixed float for foreach goto if implicit in int interface internal is lock long when object operator out override params private protected public readonly ref sbyte sealed short sizeof stackalloc static string struct switch this try typeof uint ulong unchecked unsafe ushort using virtual volatile void while async protected public private internal ascending descending from get group into join let orderby partial select set value var where yield",literal:"null false true"},t=e.IR+"(<"+e.IR+">)?(\\[\\])?";return{aliases:["csharp"],k:r,i:/::/,c:[e.C("///","$",{rB:!0,c:[{cN:"doctag",v:[{b:"///",r:0},{b:""},{b:""}]}]}),e.CLCM,e.CBCM,{cN:"meta",b:"#",e:"$",k:{"meta-keyword":"if else elif endif define undef warning error line region endregion pragma checksum"}},{cN:"string",b:'@"',e:'"',c:[{b:'""'}]},e.ASM,e.QSM,e.CNM,{bK:"class interface",e:/[{;=]/,i:/[^\s:]/,c:[e.TM,e.CLCM,e.CBCM]},{bK:"namespace",e:/[{;=]/,i:/[^\s:]/,c:[e.inherit(e.TM,{b:"[a-zA-Z](\\.?\\w)*"}),e.CLCM,e.CBCM]},{bK:"new return throw await",r:0},{cN:"function",b:"("+t+"\\s+)+"+e.IR+"\\s*\\(",rB:!0,e:/[{;=]/,eE:!0,k:r,c:[{b:e.IR+"\\s*\\(",rB:!0,c:[e.TM],r:0},{cN:"params",b:/\(/,e:/\)/,eB:!0,eE:!0,k:r,r:0,c:[e.ASM,e.QSM,e.CNM,e.CBCM]},e.CLCM,e.CBCM]}]}});hljs.registerLanguage("python",function(e){var r={cN:"meta",b:/^(>>>|\.\.\.) /},b={cN:"string",c:[e.BE],v:[{b:/(u|b)?r?'''/,e:/'''/,c:[r],r:10},{b:/(u|b)?r?"""/,e:/"""/,c:[r],r:10},{b:/(u|r|ur)'/,e:/'/,r:10},{b:/(u|r|ur)"/,e:/"/,r:10},{b:/(b|br)'/,e:/'/},{b:/(b|br)"/,e:/"/},e.ASM,e.QSM]},a={cN:"number",r:0,v:[{b:e.BNR+"[lLjJ]?"},{b:"\\b(0o[0-7]+)[lLjJ]?"},{b:e.CNR+"[lLjJ]?"}]},l={cN:"params",b:/\(/,e:/\)/,c:["self",r,a,b]};return{aliases:["py","gyp"],k:{keyword:"and elif is global as in if from raise for except finally print import pass return exec else break not with class assert yield try while continue del or def lambda async await nonlocal|10 None True False",built_in:"Ellipsis NotImplemented"},i:/(<\/|->|\?)/,c:[r,a,b,e.HCM,{v:[{cN:"function",bK:"def",r:10},{cN:"class",bK:"class"}],e:/:/,i:/[${=;\n,]/,c:[e.UTM,l,{b:/->/,eW:!0,k:"None"}]},{cN:"meta",b:/^[\t ]*@/,e:/$/},{b:/\b(print|exec)\(/}]}});hljs.registerLanguage("ini",function(e){var b={cN:"string",c:[e.BE],v:[{b:"'''",e:"'''",r:10},{b:'"""',e:'"""',r:10},{b:'"',e:'"'},{b:"'",e:"'"}]};return{aliases:["toml"],cI:!0,i:/\S/,c:[e.C(";","$"),e.HCM,{cN:"section",b:/^\s*\[+/,e:/\]+/},{b:/^[a-z0-9\[\]_-]+\s*=\s*/,e:"$",rB:!0,c:[{cN:"attr",b:/[a-z0-9\[\]_-]+/},{b:/=/,eW:!0,r:0,c:[{cN:"literal",b:/\bon|off|true|false|yes|no\b/},{cN:"variable",v:[{b:/\$[\w\d"][\w\d_]*/},{b:/\$\{(.*?)}/}]},b,{cN:"number",b:/([\+\-]+)?[\d]+_[\d_]+/},e.NM]}]}]}});hljs.registerLanguage("sql",function(e){var t=e.C("--","$");return{cI:!0,i:/[<>{}*#]/,c:[{bK:"begin end start commit rollback savepoint lock alter create drop rename call delete do handler insert load replace select truncate update set show pragma grant merge describe use explain help declare prepare execute deallocate release unlock purge reset change stop analyze cache flush optimize repair kill install uninstall checksum restore check backup revoke",e:/;/,eW:!0,l:/[\w\.]+/,k:{keyword:"abort abs absolute acc acce accep accept access accessed accessible account acos action activate add addtime admin administer advanced advise aes_decrypt aes_encrypt after agent aggregate ali alia alias allocate allow alter always analyze ancillary and any anydata anydataset anyschema anytype apply archive archived archivelog are as asc ascii asin assembly assertion associate asynchronous at atan atn2 attr attri attrib attribu attribut attribute attributes audit authenticated authentication authid authors auto autoallocate autodblink autoextend automatic availability avg backup badfile basicfile before begin beginning benchmark between bfile bfile_base big bigfile bin binary_double binary_float binlog bit_and bit_count bit_length bit_or bit_xor bitmap blob_base block blocksize body both bound buffer_cache buffer_pool build bulk by byte byteordermark bytes cache caching call calling cancel capacity cascade cascaded case cast catalog category ceil ceiling chain change changed char_base char_length character_length characters characterset charindex charset charsetform charsetid check checksum checksum_agg child choose chr chunk class cleanup clear client clob clob_base clone close cluster_id cluster_probability cluster_set clustering coalesce coercibility col collate collation collect colu colum column column_value columns columns_updated comment commit compact compatibility compiled complete composite_limit compound compress compute concat concat_ws concurrent confirm conn connec connect connect_by_iscycle connect_by_isleaf connect_by_root connect_time connection consider consistent constant constraint constraints constructor container content contents context contributors controlfile conv convert convert_tz corr corr_k corr_s corresponding corruption cos cost count count_big counted covar_pop covar_samp cpu_per_call cpu_per_session crc32 create creation critical cross cube cume_dist curdate current current_date current_time current_timestamp current_user cursor curtime customdatum cycle data database databases datafile datafiles datalength date_add date_cache date_format date_sub dateadd datediff datefromparts datename datepart datetime2fromparts day day_to_second dayname dayofmonth dayofweek dayofyear days db_role_change dbtimezone ddl deallocate declare decode decompose decrement decrypt deduplicate def defa defau defaul default defaults deferred defi defin define degrees delayed delegate delete delete_all delimited demand dense_rank depth dequeue des_decrypt des_encrypt des_key_file desc descr descri describ describe descriptor deterministic diagnostics difference dimension direct_load directory disable disable_all disallow disassociate discardfile disconnect diskgroup distinct distinctrow distribute distributed div do document domain dotnet double downgrade drop dumpfile duplicate duration each edition editionable editions element ellipsis else elsif elt empty enable enable_all enclosed encode encoding encrypt end end-exec endian enforced engine engines enqueue enterprise entityescaping eomonth error errors escaped evalname evaluate event eventdata events except exception exceptions exchange exclude excluding execu execut execute exempt exists exit exp expire explain export export_set extended extent external external_1 external_2 externally extract failed failed_login_attempts failover failure far fast feature_set feature_value fetch field fields file file_name_convert filesystem_like_logging final finish first first_value fixed flash_cache flashback floor flush following follows for forall force form forma format found found_rows freelist freelists freepools fresh from from_base64 from_days ftp full function general generated get get_format get_lock getdate getutcdate global global_name globally go goto grant grants greatest group group_concat group_id grouping grouping_id groups gtid_subtract guarantee guard handler hash hashkeys having hea head headi headin heading heap help hex hierarchy high high_priority hosts hour http id ident_current ident_incr ident_seed identified identity idle_time if ifnull ignore iif ilike ilm immediate import in include including increment index indexes indexing indextype indicator indices inet6_aton inet6_ntoa inet_aton inet_ntoa infile initial initialized initially initrans inmemory inner innodb input insert install instance instantiable instr interface interleaved intersect into invalidate invisible is is_free_lock is_ipv4 is_ipv4_compat is_not is_not_null is_used_lock isdate isnull isolation iterate java join json json_exists keep keep_duplicates key keys kill language large last last_day last_insert_id last_value lax lcase lead leading least leaves left len lenght length less level levels library like like2 like4 likec limit lines link list listagg little ln load load_file lob lobs local localtime localtimestamp locate locator lock locked log log10 log2 logfile logfiles logging logical logical_reads_per_call logoff logon logs long loop low low_priority lower lpad lrtrim ltrim main make_set makedate maketime managed management manual map mapping mask master master_pos_wait match matched materialized max maxextents maximize maxinstances maxlen maxlogfiles maxloghistory maxlogmembers maxsize maxtrans md5 measures median medium member memcompress memory merge microsecond mid migration min minextents minimum mining minus minute minvalue missing mod mode model modification modify module monitoring month months mount move movement multiset mutex name name_const names nan national native natural nav nchar nclob nested never new newline next nextval no no_write_to_binlog noarchivelog noaudit nobadfile nocheck nocompress nocopy nocycle nodelay nodiscardfile noentityescaping noguarantee nokeep nologfile nomapping nomaxvalue nominimize nominvalue nomonitoring none noneditionable nonschema noorder nopr nopro noprom nopromp noprompt norely noresetlogs noreverse normal norowdependencies noschemacheck noswitch not nothing notice notrim novalidate now nowait nth_value nullif nulls num numb numbe nvarchar nvarchar2 object ocicoll ocidate ocidatetime ociduration ociinterval ociloblocator ocinumber ociref ocirefcursor ocirowid ocistring ocitype oct octet_length of off offline offset oid oidindex old on online only opaque open operations operator optimal optimize option optionally or oracle oracle_date oradata ord ordaudio orddicom orddoc order ordimage ordinality ordvideo organization orlany orlvary out outer outfile outline output over overflow overriding package pad parallel parallel_enable parameters parent parse partial partition partitions pascal passing password password_grace_time password_lock_time password_reuse_max password_reuse_time password_verify_function patch path patindex pctincrease pctthreshold pctused pctversion percent percent_rank percentile_cont percentile_disc performance period period_add period_diff permanent physical pi pipe pipelined pivot pluggable plugin policy position post_transaction pow power pragma prebuilt precedes preceding precision prediction prediction_cost prediction_details prediction_probability prediction_set prepare present preserve prior priority private private_sga privileges procedural procedure procedure_analyze processlist profiles project prompt protection public publishingservername purge quarter query quick quiesce quota quotename radians raise rand range rank raw read reads readsize rebuild record records recover recovery recursive recycle redo reduced ref reference referenced references referencing refresh regexp_like register regr_avgx regr_avgy regr_count regr_intercept regr_r2 regr_slope regr_sxx regr_sxy reject rekey relational relative relaylog release release_lock relies_on relocate rely rem remainder rename repair repeat replace replicate replication required reset resetlogs resize resource respect restore restricted result result_cache resumable resume retention return returning returns reuse reverse revoke right rlike role roles rollback rolling rollup round row row_count rowdependencies rowid rownum rows rtrim rules safe salt sample save savepoint sb1 sb2 sb4 scan schema schemacheck scn scope scroll sdo_georaster sdo_topo_geometry search sec_to_time second section securefile security seed segment select self sequence sequential serializable server servererror session session_user sessions_per_user set sets settings sha sha1 sha2 share shared shared_pool short show shrink shutdown si_averagecolor si_colorhistogram si_featurelist si_positionalcolor si_stillimage si_texture siblings sid sign sin size size_t sizes skip slave sleep smalldatetimefromparts smallfile snapshot some soname sort soundex source space sparse spfile split sql sql_big_result sql_buffer_result sql_cache sql_calc_found_rows sql_small_result sql_variant_property sqlcode sqldata sqlerror sqlname sqlstate sqrt square standalone standby start starting startup statement static statistics stats_binomial_test stats_crosstab stats_ks_test stats_mode stats_mw_test stats_one_way_anova stats_t_test_ stats_t_test_indep stats_t_test_one stats_t_test_paired stats_wsr_test status std stddev stddev_pop stddev_samp stdev stop storage store stored str str_to_date straight_join strcmp strict string struct stuff style subdate subpartition subpartitions substitutable substr substring subtime subtring_index subtype success sum suspend switch switchoffset switchover sync synchronous synonym sys sys_xmlagg sysasm sysaux sysdate sysdatetimeoffset sysdba sysoper system system_user sysutcdatetime table tables tablespace tan tdo template temporary terminated tertiary_weights test than then thread through tier ties time time_format time_zone timediff timefromparts timeout timestamp timestampadd timestampdiff timezone_abbr timezone_minute timezone_region to to_base64 to_date to_days to_seconds todatetimeoffset trace tracking transaction transactional translate translation treat trigger trigger_nestlevel triggers trim truncate try_cast try_convert try_parse type ub1 ub2 ub4 ucase unarchived unbounded uncompress under undo unhex unicode uniform uninstall union unique unix_timestamp unknown unlimited unlock unpivot unrecoverable unsafe unsigned until untrusted unusable unused update updated upgrade upped upper upsert url urowid usable usage use use_stored_outlines user user_data user_resources users using utc_date utc_timestamp uuid uuid_short validate validate_password_strength validation valist value values var var_samp varcharc vari varia variab variabl variable variables variance varp varraw varrawc varray verify version versions view virtual visible void wait wallet warning warnings week weekday weekofyear wellformed when whene whenev wheneve whenever where while whitespace with within without work wrapped xdb xml xmlagg xmlattributes xmlcast xmlcolattval xmlelement xmlexists xmlforest xmlindex xmlnamespaces xmlpi xmlquery xmlroot xmlschema xmlserialize xmltable xmltype xor year year_to_month years yearweek",literal:"true false null",built_in:"array bigint binary bit blob boolean char character date dec decimal float int int8 integer interval number numeric real record serial serial8 smallint text varchar varying void"},c:[{cN:"string",b:"'",e:"'",c:[e.BE,{b:"''"}]},{cN:"string",b:'"',e:'"',c:[e.BE,{b:'""'}]},{cN:"string",b:"`",e:"`",c:[e.BE]},e.CNM,e.CBCM,t]},e.CBCM,t]}});hljs.registerLanguage("http",function(e){var t="HTTP/[0-9\\.]+";return{aliases:["https"],i:"\\S",c:[{b:"^"+t,e:"$",c:[{cN:"number",b:"\\b\\d{3}\\b"}]},{b:"^[A-Z]+ (.*?) "+t+"$",rB:!0,e:"$",c:[{cN:"string",b:" ",e:" ",eB:!0,eE:!0},{b:t},{cN:"keyword",b:"[A-Z]+"}]},{cN:"attribute",b:"^\\w",e:": ",eE:!0,i:"\\n|\\s|=",starts:{e:"$",r:0}},{b:"\\n\\n",starts:{sL:[],eW:!0}}]}});hljs.registerLanguage("diff",function(e){return{aliases:["patch"],c:[{cN:"meta",r:10,v:[{b:/^@@ +\-\d+,\d+ +\+\d+,\d+ +@@$/},{b:/^\*\*\* +\d+,\d+ +\*\*\*\*$/},{b:/^\-\-\- +\d+,\d+ +\-\-\-\-$/}]},{cN:"comment",v:[{b:/Index: /,e:/$/},{b:/=====/,e:/=====$/},{b:/^\-\-\-/,e:/$/},{b:/^\*{3} /,e:/$/},{b:/^\+\+\+/,e:/$/},{b:/\*{5}/,e:/\*{5}$/}]},{cN:"addition",b:"^\\+",e:"$"},{cN:"deletion",b:"^\\-",e:"$"},{cN:"addition",b:"^\\!",e:"$"}]}});hljs.registerLanguage("objectivec",function(e){var t={cN:"built_in",b:"(AV|CA|CF|CG|CI|MK|MP|NS|UI|XC)\\w+"},i={keyword:"int float while char export sizeof typedef const struct for union unsigned long volatile static bool mutable if do return goto void enum else break extern asm case short default double register explicit signed typename this switch continue wchar_t inline readonly assign readwrite self @synchronized id typeof nonatomic super unichar IBOutlet IBAction strong weak copy in out inout bycopy byref oneway __strong __weak __block __autoreleasing @private @protected @public @try @property @end @throw @catch @finally @autoreleasepool @synthesize @dynamic @selector @optional @required",literal:"false true FALSE TRUE nil YES NO NULL",built_in:"BOOL dispatch_once_t dispatch_queue_t dispatch_sync dispatch_async dispatch_once"},n=/[a-zA-Z@][a-zA-Z0-9_]*/,o="@interface @class @protocol @implementation";return{aliases:["mm","objc","obj-c"],k:i,l:n,i:""}]}]},{cN:"class",b:"("+o.split(" ").join("|")+")\\b",e:"({|$)",eE:!0,k:o,l:n,c:[e.UTM]},{b:"\\."+e.UIR,r:0}]}});hljs.registerLanguage("markdown",function(e){return{aliases:["md","mkdown","mkd"],c:[{cN:"section",v:[{b:"^#{1,6}",e:"$"},{b:"^.+?\\n[=-]{2,}$"}]},{b:"<",e:">",sL:"xml",r:0},{cN:"bullet",b:"^([*+-]|(\\d+\\.))\\s+"},{cN:"strong",b:"[*_]{2}.+?[*_]{2}"},{cN:"emphasis",v:[{b:"\\*.+?\\*"},{b:"_.+?_",r:0}]},{cN:"quote",b:"^>\\s+",e:"$"},{cN:"code",v:[{b:"^```w*s*$",e:"^```s*$"},{b:"`.+?`"},{b:"^( {4}| )",e:"$",r:0}]},{b:"^[-\\*]{3,}",e:"$"},{b:"\\[.+?\\][\\(\\[].*?[\\)\\]]",rB:!0,c:[{cN:"string",b:"\\[",e:"\\]",eB:!0,rE:!0,r:0},{cN:"link",b:"\\]\\(",e:"\\)",eB:!0,eE:!0},{cN:"symbol",b:"\\]\\[",e:"\\]",eB:!0,eE:!0}],r:10},{b:"^\\[.+\\]:",rB:!0,c:[{cN:"symbol",b:"\\[",e:"\\]:",eB:!0,eE:!0,starts:{cN:"link",e:"$"}}]}]}}); -------------------------------------------------------------------------------- /Web _Tech_Slides/js/markdown.js: -------------------------------------------------------------------------------- 1 | // Released under MIT license 2 | // Copyright (c) 2009-2010 Dominic Baggott 3 | // Copyright (c) 2009-2010 Ash Berlin 4 | // Copyright (c) 2011 Christoph Dorn (http://www.christophdorn.com) 5 | // Date: 2013-09-15T16:12Z 6 | 7 | (function(expose) { 8 | 9 | 10 | 11 | 12 | var MarkdownHelpers = {}; 13 | 14 | // For Spidermonkey based engines 15 | function mk_block_toSource() { 16 | return "Markdown.mk_block( " + 17 | uneval(this.toString()) + 18 | ", " + 19 | uneval(this.trailing) + 20 | ", " + 21 | uneval(this.lineNumber) + 22 | " )"; 23 | } 24 | 25 | // node 26 | function mk_block_inspect() { 27 | var util = require("util"); 28 | return "Markdown.mk_block( " + 29 | util.inspect(this.toString()) + 30 | ", " + 31 | util.inspect(this.trailing) + 32 | ", " + 33 | util.inspect(this.lineNumber) + 34 | " )"; 35 | 36 | } 37 | 38 | MarkdownHelpers.mk_block = function(block, trail, line) { 39 | // Be helpful for default case in tests. 40 | if ( arguments.length === 1 ) 41 | trail = "\n\n"; 42 | 43 | // We actually need a String object, not a string primitive 44 | /* jshint -W053 */ 45 | var s = new String(block); 46 | s.trailing = trail; 47 | // To make it clear its not just a string 48 | s.inspect = mk_block_inspect; 49 | s.toSource = mk_block_toSource; 50 | 51 | if ( line !== undefined ) 52 | s.lineNumber = line; 53 | 54 | return s; 55 | }; 56 | 57 | 58 | var isArray = MarkdownHelpers.isArray = Array.isArray || function(obj) { 59 | return Object.prototype.toString.call(obj) === "[object Array]"; 60 | }; 61 | 62 | // Don't mess with Array.prototype. Its not friendly 63 | if ( Array.prototype.forEach ) { 64 | MarkdownHelpers.forEach = function forEach( arr, cb, thisp ) { 65 | return arr.forEach( cb, thisp ); 66 | }; 67 | } 68 | else { 69 | MarkdownHelpers.forEach = function forEach(arr, cb, thisp) { 70 | for (var i = 0; i < arr.length; i++) 71 | cb.call(thisp || arr, arr[i], i, arr); 72 | }; 73 | } 74 | 75 | MarkdownHelpers.isEmpty = function isEmpty( obj ) { 76 | for ( var key in obj ) { 77 | if ( hasOwnProperty.call( obj, key ) ) 78 | return false; 79 | } 80 | return true; 81 | }; 82 | 83 | MarkdownHelpers.extract_attr = function extract_attr( jsonml ) { 84 | return isArray(jsonml) 85 | && jsonml.length > 1 86 | && typeof jsonml[ 1 ] === "object" 87 | && !( isArray(jsonml[ 1 ]) ) 88 | ? jsonml[ 1 ] 89 | : undefined; 90 | }; 91 | 92 | 93 | 94 | 95 | /** 96 | * class Markdown 97 | * 98 | * Markdown processing in Javascript done right. We have very particular views 99 | * on what constitutes 'right' which include: 100 | * 101 | * - produces well-formed HTML (this means that em and strong nesting is 102 | * important) 103 | * 104 | * - has an intermediate representation to allow processing of parsed data (We 105 | * in fact have two, both as [JsonML]: a markdown tree and an HTML tree). 106 | * 107 | * - is easily extensible to add new dialects without having to rewrite the 108 | * entire parsing mechanics 109 | * 110 | * - has a good test suite 111 | * 112 | * This implementation fulfills all of these (except that the test suite could 113 | * do with expanding to automatically run all the fixtures from other Markdown 114 | * implementations.) 115 | * 116 | * ##### Intermediate Representation 117 | * 118 | * *TODO* Talk about this :) Its JsonML, but document the node names we use. 119 | * 120 | * [JsonML]: http://jsonml.org/ "JSON Markup Language" 121 | **/ 122 | var Markdown = function(dialect) { 123 | switch (typeof dialect) { 124 | case "undefined": 125 | this.dialect = Markdown.dialects.Gruber; 126 | break; 127 | case "object": 128 | this.dialect = dialect; 129 | break; 130 | default: 131 | if ( dialect in Markdown.dialects ) 132 | this.dialect = Markdown.dialects[dialect]; 133 | else 134 | throw new Error("Unknown Markdown dialect '" + String(dialect) + "'"); 135 | break; 136 | } 137 | this.em_state = []; 138 | this.strong_state = []; 139 | this.debug_indent = ""; 140 | }; 141 | 142 | /** 143 | * Markdown.dialects 144 | * 145 | * Namespace of built-in dialects. 146 | **/ 147 | Markdown.dialects = {}; 148 | 149 | 150 | 151 | 152 | // Imported functions 153 | var mk_block = Markdown.mk_block = MarkdownHelpers.mk_block, 154 | isArray = MarkdownHelpers.isArray; 155 | 156 | /** 157 | * parse( markdown, [dialect] ) -> JsonML 158 | * - markdown (String): markdown string to parse 159 | * - dialect (String | Dialect): the dialect to use, defaults to gruber 160 | * 161 | * Parse `markdown` and return a markdown document as a Markdown.JsonML tree. 162 | **/ 163 | Markdown.parse = function( source, dialect ) { 164 | // dialect will default if undefined 165 | var md = new Markdown( dialect ); 166 | return md.toTree( source ); 167 | }; 168 | 169 | function count_lines( str ) { 170 | var n = 0, 171 | i = -1; 172 | while ( ( i = str.indexOf("\n", i + 1) ) !== -1 ) 173 | n++; 174 | return n; 175 | } 176 | 177 | // Internal - split source into rough blocks 178 | Markdown.prototype.split_blocks = function splitBlocks( input ) { 179 | input = input.replace(/(\r\n|\n|\r)/g, "\n"); 180 | // [\s\S] matches _anything_ (newline or space) 181 | // [^] is equivalent but doesn't work in IEs. 182 | var re = /([\s\S]+?)($|\n#|\n(?:\s*\n|$)+)/g, 183 | blocks = [], 184 | m; 185 | 186 | var line_no = 1; 187 | 188 | if ( ( m = /^(\s*\n)/.exec(input) ) !== null ) { 189 | // skip (but count) leading blank lines 190 | line_no += count_lines( m[0] ); 191 | re.lastIndex = m[0].length; 192 | } 193 | 194 | while ( ( m = re.exec(input) ) !== null ) { 195 | if (m[2] === "\n#") { 196 | m[2] = "\n"; 197 | re.lastIndex--; 198 | } 199 | blocks.push( mk_block( m[1], m[2], line_no ) ); 200 | line_no += count_lines( m[0] ); 201 | } 202 | 203 | return blocks; 204 | }; 205 | 206 | /** 207 | * Markdown#processBlock( block, next ) -> undefined | [ JsonML, ... ] 208 | * - block (String): the block to process 209 | * - next (Array): the following blocks 210 | * 211 | * Process `block` and return an array of JsonML nodes representing `block`. 212 | * 213 | * It does this by asking each block level function in the dialect to process 214 | * the block until one can. Succesful handling is indicated by returning an 215 | * array (with zero or more JsonML nodes), failure by a false value. 216 | * 217 | * Blocks handlers are responsible for calling [[Markdown#processInline]] 218 | * themselves as appropriate. 219 | * 220 | * If the blocks were split incorrectly or adjacent blocks need collapsing you 221 | * can adjust `next` in place using shift/splice etc. 222 | * 223 | * If any of this default behaviour is not right for the dialect, you can 224 | * define a `__call__` method on the dialect that will get invoked to handle 225 | * the block processing. 226 | */ 227 | Markdown.prototype.processBlock = function processBlock( block, next ) { 228 | var cbs = this.dialect.block, 229 | ord = cbs.__order__; 230 | 231 | if ( "__call__" in cbs ) 232 | return cbs.__call__.call(this, block, next); 233 | 234 | for ( var i = 0; i < ord.length; i++ ) { 235 | //D:this.debug( "Testing", ord[i] ); 236 | var res = cbs[ ord[i] ].call( this, block, next ); 237 | if ( res ) { 238 | //D:this.debug(" matched"); 239 | if ( !isArray(res) || ( res.length > 0 && !( isArray(res[0]) ) ) ) 240 | this.debug(ord[i], "didn't return a proper array"); 241 | //D:this.debug( "" ); 242 | return res; 243 | } 244 | } 245 | 246 | // Uhoh! no match! Should we throw an error? 247 | return []; 248 | }; 249 | 250 | Markdown.prototype.processInline = function processInline( block ) { 251 | return this.dialect.inline.__call__.call( this, String( block ) ); 252 | }; 253 | 254 | /** 255 | * Markdown#toTree( source ) -> JsonML 256 | * - source (String): markdown source to parse 257 | * 258 | * Parse `source` into a JsonML tree representing the markdown document. 259 | **/ 260 | // custom_tree means set this.tree to `custom_tree` and restore old value on return 261 | Markdown.prototype.toTree = function toTree( source, custom_root ) { 262 | var blocks = source instanceof Array ? source : this.split_blocks( source ); 263 | 264 | // Make tree a member variable so its easier to mess with in extensions 265 | var old_tree = this.tree; 266 | try { 267 | this.tree = custom_root || this.tree || [ "markdown" ]; 268 | 269 | blocks_loop: 270 | while ( blocks.length ) { 271 | var b = this.processBlock( blocks.shift(), blocks ); 272 | 273 | // Reference blocks and the like won't return any content 274 | if ( !b.length ) 275 | continue blocks_loop; 276 | 277 | this.tree.push.apply( this.tree, b ); 278 | } 279 | return this.tree; 280 | } 281 | finally { 282 | if ( custom_root ) 283 | this.tree = old_tree; 284 | } 285 | }; 286 | 287 | // Noop by default 288 | Markdown.prototype.debug = function () { 289 | var args = Array.prototype.slice.call( arguments); 290 | args.unshift(this.debug_indent); 291 | if ( typeof print !== "undefined" ) 292 | print.apply( print, args ); 293 | if ( typeof console !== "undefined" && typeof console.log !== "undefined" ) 294 | console.log.apply( null, args ); 295 | }; 296 | 297 | Markdown.prototype.loop_re_over_block = function( re, block, cb ) { 298 | // Dont use /g regexps with this 299 | var m, 300 | b = block.valueOf(); 301 | 302 | while ( b.length && (m = re.exec(b) ) !== null ) { 303 | b = b.substr( m[0].length ); 304 | cb.call(this, m); 305 | } 306 | return b; 307 | }; 308 | 309 | // Build default order from insertion order. 310 | Markdown.buildBlockOrder = function(d) { 311 | var ord = []; 312 | for ( var i in d ) { 313 | if ( i === "__order__" || i === "__call__" ) 314 | continue; 315 | ord.push( i ); 316 | } 317 | d.__order__ = ord; 318 | }; 319 | 320 | // Build patterns for inline matcher 321 | Markdown.buildInlinePatterns = function(d) { 322 | var patterns = []; 323 | 324 | for ( var i in d ) { 325 | // __foo__ is reserved and not a pattern 326 | if ( i.match( /^__.*__$/) ) 327 | continue; 328 | var l = i.replace( /([\\.*+?|()\[\]{}])/g, "\\$1" ) 329 | .replace( /\n/, "\\n" ); 330 | patterns.push( i.length === 1 ? l : "(?:" + l + ")" ); 331 | } 332 | 333 | patterns = patterns.join("|"); 334 | d.__patterns__ = patterns; 335 | //print("patterns:", uneval( patterns ) ); 336 | 337 | var fn = d.__call__; 338 | d.__call__ = function(text, pattern) { 339 | if ( pattern !== undefined ) 340 | return fn.call(this, text, pattern); 341 | else 342 | return fn.call(this, text, patterns); 343 | }; 344 | }; 345 | 346 | 347 | 348 | 349 | var extract_attr = MarkdownHelpers.extract_attr; 350 | 351 | /** 352 | * renderJsonML( jsonml[, options] ) -> String 353 | * - jsonml (Array): JsonML array to render to XML 354 | * - options (Object): options 355 | * 356 | * Converts the given JsonML into well-formed XML. 357 | * 358 | * The options currently understood are: 359 | * 360 | * - root (Boolean): wether or not the root node should be included in the 361 | * output, or just its children. The default `false` is to not include the 362 | * root itself. 363 | */ 364 | Markdown.renderJsonML = function( jsonml, options ) { 365 | options = options || {}; 366 | // include the root element in the rendered output? 367 | options.root = options.root || false; 368 | 369 | var content = []; 370 | 371 | if ( options.root ) { 372 | content.push( render_tree( jsonml ) ); 373 | } 374 | else { 375 | jsonml.shift(); // get rid of the tag 376 | if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) 377 | jsonml.shift(); // get rid of the attributes 378 | 379 | while ( jsonml.length ) 380 | content.push( render_tree( jsonml.shift() ) ); 381 | } 382 | 383 | return content.join( "\n\n" ); 384 | }; 385 | 386 | 387 | /** 388 | * toHTMLTree( markdown, [dialect] ) -> JsonML 389 | * toHTMLTree( md_tree ) -> JsonML 390 | * - markdown (String): markdown string to parse 391 | * - dialect (String | Dialect): the dialect to use, defaults to gruber 392 | * - md_tree (Markdown.JsonML): parsed markdown tree 393 | * 394 | * Turn markdown into HTML, represented as a JsonML tree. If a string is given 395 | * to this function, it is first parsed into a markdown tree by calling 396 | * [[parse]]. 397 | **/ 398 | Markdown.toHTMLTree = function toHTMLTree( input, dialect , options ) { 399 | 400 | // convert string input to an MD tree 401 | if ( typeof input === "string" ) 402 | input = this.parse( input, dialect ); 403 | 404 | // Now convert the MD tree to an HTML tree 405 | 406 | // remove references from the tree 407 | var attrs = extract_attr( input ), 408 | refs = {}; 409 | 410 | if ( attrs && attrs.references ) 411 | refs = attrs.references; 412 | 413 | var html = convert_tree_to_html( input, refs , options ); 414 | merge_text_nodes( html ); 415 | return html; 416 | }; 417 | 418 | /** 419 | * toHTML( markdown, [dialect] ) -> String 420 | * toHTML( md_tree ) -> String 421 | * - markdown (String): markdown string to parse 422 | * - md_tree (Markdown.JsonML): parsed markdown tree 423 | * 424 | * Take markdown (either as a string or as a JsonML tree) and run it through 425 | * [[toHTMLTree]] then turn it into a well-formated HTML fragment. 426 | **/ 427 | Markdown.toHTML = function toHTML( source , dialect , options ) { 428 | var input = this.toHTMLTree( source , dialect , options ); 429 | 430 | return this.renderJsonML( input ); 431 | }; 432 | 433 | 434 | function escapeHTML( text ) { 435 | return text.replace( /&/g, "&" ) 436 | .replace( //g, ">" ) 438 | .replace( /"/g, """ ) 439 | .replace( /'/g, "'" ); 440 | } 441 | 442 | function render_tree( jsonml ) { 443 | // basic case 444 | if ( typeof jsonml === "string" ) 445 | return escapeHTML( jsonml ); 446 | 447 | var tag = jsonml.shift(), 448 | attributes = {}, 449 | content = []; 450 | 451 | if ( jsonml.length && typeof jsonml[ 0 ] === "object" && !( jsonml[ 0 ] instanceof Array ) ) 452 | attributes = jsonml.shift(); 453 | 454 | while ( jsonml.length ) 455 | content.push( render_tree( jsonml.shift() ) ); 456 | 457 | var tag_attrs = ""; 458 | for ( var a in attributes ) 459 | tag_attrs += " " + a + '="' + escapeHTML( attributes[ a ] ) + '"'; 460 | 461 | // be careful about adding whitespace here for inline elements 462 | if ( tag === "img" || tag === "br" || tag === "hr" ) 463 | return "<"+ tag + tag_attrs + "/>"; 464 | else 465 | return "<"+ tag + tag_attrs + ">" + content.join( "" ) + ""; 466 | } 467 | 468 | function convert_tree_to_html( tree, references, options ) { 469 | var i; 470 | options = options || {}; 471 | 472 | // shallow clone 473 | var jsonml = tree.slice( 0 ); 474 | 475 | if ( typeof options.preprocessTreeNode === "function" ) 476 | jsonml = options.preprocessTreeNode(jsonml, references); 477 | 478 | // Clone attributes if they exist 479 | var attrs = extract_attr( jsonml ); 480 | if ( attrs ) { 481 | jsonml[ 1 ] = {}; 482 | for ( i in attrs ) { 483 | jsonml[ 1 ][ i ] = attrs[ i ]; 484 | } 485 | attrs = jsonml[ 1 ]; 486 | } 487 | 488 | // basic case 489 | if ( typeof jsonml === "string" ) 490 | return jsonml; 491 | 492 | // convert this node 493 | switch ( jsonml[ 0 ] ) { 494 | case "header": 495 | jsonml[ 0 ] = "h" + jsonml[ 1 ].level; 496 | delete jsonml[ 1 ].level; 497 | break; 498 | case "bulletlist": 499 | jsonml[ 0 ] = "ul"; 500 | break; 501 | case "numberlist": 502 | jsonml[ 0 ] = "ol"; 503 | break; 504 | case "listitem": 505 | jsonml[ 0 ] = "li"; 506 | break; 507 | case "para": 508 | jsonml[ 0 ] = "p"; 509 | break; 510 | case "markdown": 511 | jsonml[ 0 ] = "html"; 512 | if ( attrs ) 513 | delete attrs.references; 514 | break; 515 | case "code_block": 516 | jsonml[ 0 ] = "pre"; 517 | i = attrs ? 2 : 1; 518 | var code = [ "code" ]; 519 | code.push.apply( code, jsonml.splice( i, jsonml.length - i ) ); 520 | jsonml[ i ] = code; 521 | break; 522 | case "inlinecode": 523 | jsonml[ 0 ] = "code"; 524 | break; 525 | case "img": 526 | jsonml[ 1 ].src = jsonml[ 1 ].href; 527 | delete jsonml[ 1 ].href; 528 | break; 529 | case "linebreak": 530 | jsonml[ 0 ] = "br"; 531 | break; 532 | case "link": 533 | jsonml[ 0 ] = "a"; 534 | break; 535 | case "link_ref": 536 | jsonml[ 0 ] = "a"; 537 | 538 | // grab this ref and clean up the attribute node 539 | var ref = references[ attrs.ref ]; 540 | 541 | // if the reference exists, make the link 542 | if ( ref ) { 543 | delete attrs.ref; 544 | 545 | // add in the href and title, if present 546 | attrs.href = ref.href; 547 | if ( ref.title ) 548 | attrs.title = ref.title; 549 | 550 | // get rid of the unneeded original text 551 | delete attrs.original; 552 | } 553 | // the reference doesn't exist, so revert to plain text 554 | else { 555 | return attrs.original; 556 | } 557 | break; 558 | case "img_ref": 559 | jsonml[ 0 ] = "img"; 560 | 561 | // grab this ref and clean up the attribute node 562 | var ref = references[ attrs.ref ]; 563 | 564 | // if the reference exists, make the link 565 | if ( ref ) { 566 | delete attrs.ref; 567 | 568 | // add in the href and title, if present 569 | attrs.src = ref.href; 570 | if ( ref.title ) 571 | attrs.title = ref.title; 572 | 573 | // get rid of the unneeded original text 574 | delete attrs.original; 575 | } 576 | // the reference doesn't exist, so revert to plain text 577 | else { 578 | return attrs.original; 579 | } 580 | break; 581 | } 582 | 583 | // convert all the children 584 | i = 1; 585 | 586 | // deal with the attribute node, if it exists 587 | if ( attrs ) { 588 | // if there are keys, skip over it 589 | for ( var key in jsonml[ 1 ] ) { 590 | i = 2; 591 | break; 592 | } 593 | // if there aren't, remove it 594 | if ( i === 1 ) 595 | jsonml.splice( i, 1 ); 596 | } 597 | 598 | for ( ; i < jsonml.length; ++i ) { 599 | jsonml[ i ] = convert_tree_to_html( jsonml[ i ], references, options ); 600 | } 601 | 602 | return jsonml; 603 | } 604 | 605 | 606 | // merges adjacent text nodes into a single node 607 | function merge_text_nodes( jsonml ) { 608 | // skip the tag name and attribute hash 609 | var i = extract_attr( jsonml ) ? 2 : 1; 610 | 611 | while ( i < jsonml.length ) { 612 | // if it's a string check the next item too 613 | if ( typeof jsonml[ i ] === "string" ) { 614 | if ( i + 1 < jsonml.length && typeof jsonml[ i + 1 ] === "string" ) { 615 | // merge the second string into the first and remove it 616 | jsonml[ i ] += jsonml.splice( i + 1, 1 )[ 0 ]; 617 | } 618 | else { 619 | ++i; 620 | } 621 | } 622 | // if it's not a string recurse 623 | else { 624 | merge_text_nodes( jsonml[ i ] ); 625 | ++i; 626 | } 627 | } 628 | }; 629 | 630 | 631 | 632 | var DialectHelpers = {}; 633 | DialectHelpers.inline_until_char = function( text, want ) { 634 | var consumed = 0, 635 | nodes = []; 636 | 637 | while ( true ) { 638 | if ( text.charAt( consumed ) === want ) { 639 | // Found the character we were looking for 640 | consumed++; 641 | return [ consumed, nodes ]; 642 | } 643 | 644 | if ( consumed >= text.length ) { 645 | // No closing char found. Abort. 646 | return null; 647 | } 648 | 649 | var res = this.dialect.inline.__oneElement__.call(this, text.substr( consumed ) ); 650 | consumed += res[ 0 ]; 651 | // Add any returned nodes. 652 | nodes.push.apply( nodes, res.slice( 1 ) ); 653 | } 654 | }; 655 | 656 | // Helper function to make sub-classing a dialect easier 657 | DialectHelpers.subclassDialect = function( d ) { 658 | function Block() {} 659 | Block.prototype = d.block; 660 | function Inline() {} 661 | Inline.prototype = d.inline; 662 | 663 | return { block: new Block(), inline: new Inline() }; 664 | }; 665 | 666 | 667 | 668 | 669 | var forEach = MarkdownHelpers.forEach, 670 | extract_attr = MarkdownHelpers.extract_attr, 671 | mk_block = MarkdownHelpers.mk_block, 672 | isEmpty = MarkdownHelpers.isEmpty, 673 | inline_until_char = DialectHelpers.inline_until_char; 674 | 675 | /** 676 | * Gruber dialect 677 | * 678 | * The default dialect that follows the rules set out by John Gruber's 679 | * markdown.pl as closely as possible. Well actually we follow the behaviour of 680 | * that script which in some places is not exactly what the syntax web page 681 | * says. 682 | **/ 683 | var Gruber = { 684 | block: { 685 | atxHeader: function atxHeader( block, next ) { 686 | var m = block.match( /^(#{1,6})\s*(.*?)\s*#*\s*(?:\n|$)/ ); 687 | 688 | if ( !m ) 689 | return undefined; 690 | 691 | var header = [ "header", { level: m[ 1 ].length } ]; 692 | Array.prototype.push.apply(header, this.processInline(m[ 2 ])); 693 | 694 | if ( m[0].length < block.length ) 695 | next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) ); 696 | 697 | return [ header ]; 698 | }, 699 | 700 | setextHeader: function setextHeader( block, next ) { 701 | var m = block.match( /^(.*)\n([-=])\2\2+(?:\n|$)/ ); 702 | 703 | if ( !m ) 704 | return undefined; 705 | 706 | var level = ( m[ 2 ] === "=" ) ? 1 : 2, 707 | header = [ "header", { level : level }, m[ 1 ] ]; 708 | 709 | if ( m[0].length < block.length ) 710 | next.unshift( mk_block( block.substr( m[0].length ), block.trailing, block.lineNumber + 2 ) ); 711 | 712 | return [ header ]; 713 | }, 714 | 715 | code: function code( block, next ) { 716 | // | Foo 717 | // |bar 718 | // should be a code block followed by a paragraph. Fun 719 | // 720 | // There might also be adjacent code block to merge. 721 | 722 | var ret = [], 723 | re = /^(?: {0,3}\t| {4})(.*)\n?/; 724 | 725 | // 4 spaces + content 726 | if ( !block.match( re ) ) 727 | return undefined; 728 | 729 | block_search: 730 | do { 731 | // Now pull out the rest of the lines 732 | var b = this.loop_re_over_block( 733 | re, block.valueOf(), function( m ) { ret.push( m[1] ); } ); 734 | 735 | if ( b.length ) { 736 | // Case alluded to in first comment. push it back on as a new block 737 | next.unshift( mk_block(b, block.trailing) ); 738 | break block_search; 739 | } 740 | else if ( next.length ) { 741 | // Check the next block - it might be code too 742 | if ( !next[0].match( re ) ) 743 | break block_search; 744 | 745 | // Pull how how many blanks lines follow - minus two to account for .join 746 | ret.push ( block.trailing.replace(/[^\n]/g, "").substring(2) ); 747 | 748 | block = next.shift(); 749 | } 750 | else { 751 | break block_search; 752 | } 753 | } while ( true ); 754 | 755 | return [ [ "code_block", ret.join("\n") ] ]; 756 | }, 757 | 758 | horizRule: function horizRule( block, next ) { 759 | // this needs to find any hr in the block to handle abutting blocks 760 | var m = block.match( /^(?:([\s\S]*?)\n)?[ \t]*([-_*])(?:[ \t]*\2){2,}[ \t]*(?:\n([\s\S]*))?$/ ); 761 | 762 | if ( !m ) 763 | return undefined; 764 | 765 | var jsonml = [ [ "hr" ] ]; 766 | 767 | // if there's a leading abutting block, process it 768 | if ( m[ 1 ] ) { 769 | var contained = mk_block( m[ 1 ], "", block.lineNumber ); 770 | jsonml.unshift.apply( jsonml, this.toTree( contained, [] ) ); 771 | } 772 | 773 | // if there's a trailing abutting block, stick it into next 774 | if ( m[ 3 ] ) 775 | next.unshift( mk_block( m[ 3 ], block.trailing, block.lineNumber + 1 ) ); 776 | 777 | return jsonml; 778 | }, 779 | 780 | // There are two types of lists. Tight and loose. Tight lists have no whitespace 781 | // between the items (and result in text just in the
  • ) and loose lists, 782 | // which have an empty line between list items, resulting in (one or more) 783 | // paragraphs inside the
  • . 784 | // 785 | // There are all sorts weird edge cases about the original markdown.pl's 786 | // handling of lists: 787 | // 788 | // * Nested lists are supposed to be indented by four chars per level. But 789 | // if they aren't, you can get a nested list by indenting by less than 790 | // four so long as the indent doesn't match an indent of an existing list 791 | // item in the 'nest stack'. 792 | // 793 | // * The type of the list (bullet or number) is controlled just by the 794 | // first item at the indent. Subsequent changes are ignored unless they 795 | // are for nested lists 796 | // 797 | lists: (function( ) { 798 | // Use a closure to hide a few variables. 799 | var any_list = "[*+-]|\\d+\\.", 800 | bullet_list = /[*+-]/, 801 | // Capture leading indent as it matters for determining nested lists. 802 | is_list_re = new RegExp( "^( {0,3})(" + any_list + ")[ \t]+" ), 803 | indent_re = "(?: {0,3}\\t| {4})"; 804 | 805 | // TODO: Cache this regexp for certain depths. 806 | // Create a regexp suitable for matching an li for a given stack depth 807 | function regex_for_depth( depth ) { 808 | 809 | return new RegExp( 810 | // m[1] = indent, m[2] = list_type 811 | "(?:^(" + indent_re + "{0," + depth + "} {0,3})(" + any_list + ")\\s+)|" + 812 | // m[3] = cont 813 | "(^" + indent_re + "{0," + (depth-1) + "}[ ]{0,4})" 814 | ); 815 | } 816 | function expand_tab( input ) { 817 | return input.replace( / {0,3}\t/g, " " ); 818 | } 819 | 820 | // Add inline content `inline` to `li`. inline comes from processInline 821 | // so is an array of content 822 | function add(li, loose, inline, nl) { 823 | if ( loose ) { 824 | li.push( [ "para" ].concat(inline) ); 825 | return; 826 | } 827 | // Hmmm, should this be any block level element or just paras? 828 | var add_to = li[li.length -1] instanceof Array && li[li.length - 1][0] === "para" 829 | ? li[li.length -1] 830 | : li; 831 | 832 | // If there is already some content in this list, add the new line in 833 | if ( nl && li.length > 1 ) 834 | inline.unshift(nl); 835 | 836 | for ( var i = 0; i < inline.length; i++ ) { 837 | var what = inline[i], 838 | is_str = typeof what === "string"; 839 | if ( is_str && add_to.length > 1 && typeof add_to[add_to.length-1] === "string" ) 840 | add_to[ add_to.length-1 ] += what; 841 | else 842 | add_to.push( what ); 843 | } 844 | } 845 | 846 | // contained means have an indent greater than the current one. On 847 | // *every* line in the block 848 | function get_contained_blocks( depth, blocks ) { 849 | 850 | var re = new RegExp( "^(" + indent_re + "{" + depth + "}.*?\\n?)*$" ), 851 | replace = new RegExp("^" + indent_re + "{" + depth + "}", "gm"), 852 | ret = []; 853 | 854 | while ( blocks.length > 0 ) { 855 | if ( re.exec( blocks[0] ) ) { 856 | var b = blocks.shift(), 857 | // Now remove that indent 858 | x = b.replace( replace, ""); 859 | 860 | ret.push( mk_block( x, b.trailing, b.lineNumber ) ); 861 | } 862 | else 863 | break; 864 | } 865 | return ret; 866 | } 867 | 868 | // passed to stack.forEach to turn list items up the stack into paras 869 | function paragraphify(s, i, stack) { 870 | var list = s.list; 871 | var last_li = list[list.length-1]; 872 | 873 | if ( last_li[1] instanceof Array && last_li[1][0] === "para" ) 874 | return; 875 | if ( i + 1 === stack.length ) { 876 | // Last stack frame 877 | // Keep the same array, but replace the contents 878 | last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ) ); 879 | } 880 | else { 881 | var sublist = last_li.pop(); 882 | last_li.push( ["para"].concat( last_li.splice(1, last_li.length - 1) ), sublist ); 883 | } 884 | } 885 | 886 | // The matcher function 887 | return function( block, next ) { 888 | var m = block.match( is_list_re ); 889 | if ( !m ) 890 | return undefined; 891 | 892 | function make_list( m ) { 893 | var list = bullet_list.exec( m[2] ) 894 | ? ["bulletlist"] 895 | : ["numberlist"]; 896 | 897 | stack.push( { list: list, indent: m[1] } ); 898 | return list; 899 | } 900 | 901 | 902 | var stack = [], // Stack of lists for nesting. 903 | list = make_list( m ), 904 | last_li, 905 | loose = false, 906 | ret = [ stack[0].list ], 907 | i; 908 | 909 | // Loop to search over block looking for inner block elements and loose lists 910 | loose_search: 911 | while ( true ) { 912 | // Split into lines preserving new lines at end of line 913 | var lines = block.split( /(?=\n)/ ); 914 | 915 | // We have to grab all lines for a li and call processInline on them 916 | // once as there are some inline things that can span lines. 917 | var li_accumulate = "", nl = ""; 918 | 919 | // Loop over the lines in this block looking for tight lists. 920 | tight_search: 921 | for ( var line_no = 0; line_no < lines.length; line_no++ ) { 922 | nl = ""; 923 | var l = lines[line_no].replace(/^\n/, function(n) { nl = n; return ""; }); 924 | 925 | 926 | // TODO: really should cache this 927 | var line_re = regex_for_depth( stack.length ); 928 | 929 | m = l.match( line_re ); 930 | //print( "line:", uneval(l), "\nline match:", uneval(m) ); 931 | 932 | // We have a list item 933 | if ( m[1] !== undefined ) { 934 | // Process the previous list item, if any 935 | if ( li_accumulate.length ) { 936 | add( last_li, loose, this.processInline( li_accumulate ), nl ); 937 | // Loose mode will have been dealt with. Reset it 938 | loose = false; 939 | li_accumulate = ""; 940 | } 941 | 942 | m[1] = expand_tab( m[1] ); 943 | var wanted_depth = Math.floor(m[1].length/4)+1; 944 | //print( "want:", wanted_depth, "stack:", stack.length); 945 | if ( wanted_depth > stack.length ) { 946 | // Deep enough for a nested list outright 947 | //print ( "new nested list" ); 948 | list = make_list( m ); 949 | last_li.push( list ); 950 | last_li = list[1] = [ "listitem" ]; 951 | } 952 | else { 953 | // We aren't deep enough to be strictly a new level. This is 954 | // where Md.pl goes nuts. If the indent matches a level in the 955 | // stack, put it there, else put it one deeper then the 956 | // wanted_depth deserves. 957 | var found = false; 958 | for ( i = 0; i < stack.length; i++ ) { 959 | if ( stack[ i ].indent !== m[1] ) 960 | continue; 961 | 962 | list = stack[ i ].list; 963 | stack.splice( i+1, stack.length - (i+1) ); 964 | found = true; 965 | break; 966 | } 967 | 968 | if (!found) { 969 | //print("not found. l:", uneval(l)); 970 | wanted_depth++; 971 | if ( wanted_depth <= stack.length ) { 972 | stack.splice(wanted_depth, stack.length - wanted_depth); 973 | //print("Desired depth now", wanted_depth, "stack:", stack.length); 974 | list = stack[wanted_depth-1].list; 975 | //print("list:", uneval(list) ); 976 | } 977 | else { 978 | //print ("made new stack for messy indent"); 979 | list = make_list(m); 980 | last_li.push(list); 981 | } 982 | } 983 | 984 | //print( uneval(list), "last", list === stack[stack.length-1].list ); 985 | last_li = [ "listitem" ]; 986 | list.push(last_li); 987 | } // end depth of shenegains 988 | nl = ""; 989 | } 990 | 991 | // Add content 992 | if ( l.length > m[0].length ) 993 | li_accumulate += nl + l.substr( m[0].length ); 994 | } // tight_search 995 | 996 | if ( li_accumulate.length ) { 997 | add( last_li, loose, this.processInline( li_accumulate ), nl ); 998 | // Loose mode will have been dealt with. Reset it 999 | loose = false; 1000 | li_accumulate = ""; 1001 | } 1002 | 1003 | // Look at the next block - we might have a loose list. Or an extra 1004 | // paragraph for the current li 1005 | var contained = get_contained_blocks( stack.length, next ); 1006 | 1007 | // Deal with code blocks or properly nested lists 1008 | if ( contained.length > 0 ) { 1009 | // Make sure all listitems up the stack are paragraphs 1010 | forEach( stack, paragraphify, this); 1011 | 1012 | last_li.push.apply( last_li, this.toTree( contained, [] ) ); 1013 | } 1014 | 1015 | var next_block = next[0] && next[0].valueOf() || ""; 1016 | 1017 | if ( next_block.match(is_list_re) || next_block.match( /^ / ) ) { 1018 | block = next.shift(); 1019 | 1020 | // Check for an HR following a list: features/lists/hr_abutting 1021 | var hr = this.dialect.block.horizRule( block, next ); 1022 | 1023 | if ( hr ) { 1024 | ret.push.apply(ret, hr); 1025 | break; 1026 | } 1027 | 1028 | // Make sure all listitems up the stack are paragraphs 1029 | forEach( stack, paragraphify, this); 1030 | 1031 | loose = true; 1032 | continue loose_search; 1033 | } 1034 | break; 1035 | } // loose_search 1036 | 1037 | return ret; 1038 | }; 1039 | })(), 1040 | 1041 | blockquote: function blockquote( block, next ) { 1042 | if ( !block.match( /^>/m ) ) 1043 | return undefined; 1044 | 1045 | var jsonml = []; 1046 | 1047 | // separate out the leading abutting block, if any. I.e. in this case: 1048 | // 1049 | // a 1050 | // > b 1051 | // 1052 | if ( block[ 0 ] !== ">" ) { 1053 | var lines = block.split( /\n/ ), 1054 | prev = [], 1055 | line_no = block.lineNumber; 1056 | 1057 | // keep shifting lines until you find a crotchet 1058 | while ( lines.length && lines[ 0 ][ 0 ] !== ">" ) { 1059 | prev.push( lines.shift() ); 1060 | line_no++; 1061 | } 1062 | 1063 | var abutting = mk_block( prev.join( "\n" ), "\n", block.lineNumber ); 1064 | jsonml.push.apply( jsonml, this.processBlock( abutting, [] ) ); 1065 | // reassemble new block of just block quotes! 1066 | block = mk_block( lines.join( "\n" ), block.trailing, line_no ); 1067 | } 1068 | 1069 | 1070 | // if the next block is also a blockquote merge it in 1071 | while ( next.length && next[ 0 ][ 0 ] === ">" ) { 1072 | var b = next.shift(); 1073 | block = mk_block( block + block.trailing + b, b.trailing, block.lineNumber ); 1074 | } 1075 | 1076 | // Strip off the leading "> " and re-process as a block. 1077 | var input = block.replace( /^> ?/gm, "" ), 1078 | old_tree = this.tree, 1079 | processedBlock = this.toTree( input, [ "blockquote" ] ), 1080 | attr = extract_attr( processedBlock ); 1081 | 1082 | // If any link references were found get rid of them 1083 | if ( attr && attr.references ) { 1084 | delete attr.references; 1085 | // And then remove the attribute object if it's empty 1086 | if ( isEmpty( attr ) ) 1087 | processedBlock.splice( 1, 1 ); 1088 | } 1089 | 1090 | jsonml.push( processedBlock ); 1091 | return jsonml; 1092 | }, 1093 | 1094 | referenceDefn: function referenceDefn( block, next) { 1095 | var re = /^\s*\[(.*?)\]:\s*(\S+)(?:\s+(?:(['"])(.*?)\3|\((.*?)\)))?\n?/; 1096 | // interesting matches are [ , ref_id, url, , title, title ] 1097 | 1098 | if ( !block.match(re) ) 1099 | return undefined; 1100 | 1101 | // make an attribute node if it doesn't exist 1102 | if ( !extract_attr( this.tree ) ) 1103 | this.tree.splice( 1, 0, {} ); 1104 | 1105 | var attrs = extract_attr( this.tree ); 1106 | 1107 | // make a references hash if it doesn't exist 1108 | if ( attrs.references === undefined ) 1109 | attrs.references = {}; 1110 | 1111 | var b = this.loop_re_over_block(re, block, function( m ) { 1112 | 1113 | if ( m[2] && m[2][0] === "<" && m[2][m[2].length-1] === ">" ) 1114 | m[2] = m[2].substring( 1, m[2].length - 1 ); 1115 | 1116 | var ref = attrs.references[ m[1].toLowerCase() ] = { 1117 | href: m[2] 1118 | }; 1119 | 1120 | if ( m[4] !== undefined ) 1121 | ref.title = m[4]; 1122 | else if ( m[5] !== undefined ) 1123 | ref.title = m[5]; 1124 | 1125 | } ); 1126 | 1127 | if ( b.length ) 1128 | next.unshift( mk_block( b, block.trailing ) ); 1129 | 1130 | return []; 1131 | }, 1132 | 1133 | para: function para( block ) { 1134 | // everything's a para! 1135 | return [ ["para"].concat( this.processInline( block ) ) ]; 1136 | } 1137 | }, 1138 | 1139 | inline: { 1140 | 1141 | __oneElement__: function oneElement( text, patterns_or_re, previous_nodes ) { 1142 | var m, 1143 | res; 1144 | 1145 | patterns_or_re = patterns_or_re || this.dialect.inline.__patterns__; 1146 | var re = new RegExp( "([\\s\\S]*?)(" + (patterns_or_re.source || patterns_or_re) + ")" ); 1147 | 1148 | m = re.exec( text ); 1149 | if (!m) { 1150 | // Just boring text 1151 | return [ text.length, text ]; 1152 | } 1153 | else if ( m[1] ) { 1154 | // Some un-interesting text matched. Return that first 1155 | return [ m[1].length, m[1] ]; 1156 | } 1157 | 1158 | var res; 1159 | if ( m[2] in this.dialect.inline ) { 1160 | res = this.dialect.inline[ m[2] ].call( 1161 | this, 1162 | text.substr( m.index ), m, previous_nodes || [] ); 1163 | } 1164 | // Default for now to make dev easier. just slurp special and output it. 1165 | res = res || [ m[2].length, m[2] ]; 1166 | return res; 1167 | }, 1168 | 1169 | __call__: function inline( text, patterns ) { 1170 | 1171 | var out = [], 1172 | res; 1173 | 1174 | function add(x) { 1175 | //D:self.debug(" adding output", uneval(x)); 1176 | if ( typeof x === "string" && typeof out[out.length-1] === "string" ) 1177 | out[ out.length-1 ] += x; 1178 | else 1179 | out.push(x); 1180 | } 1181 | 1182 | while ( text.length > 0 ) { 1183 | res = this.dialect.inline.__oneElement__.call(this, text, patterns, out ); 1184 | text = text.substr( res.shift() ); 1185 | forEach(res, add ); 1186 | } 1187 | 1188 | return out; 1189 | }, 1190 | 1191 | // These characters are intersting elsewhere, so have rules for them so that 1192 | // chunks of plain text blocks don't include them 1193 | "]": function () {}, 1194 | "}": function () {}, 1195 | 1196 | __escape__ : /^\\[\\`\*_{}\[\]()#\+.!\-]/, 1197 | 1198 | "\\": function escaped( text ) { 1199 | // [ length of input processed, node/children to add... ] 1200 | // Only esacape: \ ` * _ { } [ ] ( ) # * + - . ! 1201 | if ( this.dialect.inline.__escape__.exec( text ) ) 1202 | return [ 2, text.charAt( 1 ) ]; 1203 | else 1204 | // Not an esacpe 1205 | return [ 1, "\\" ]; 1206 | }, 1207 | 1208 | "![": function image( text ) { 1209 | 1210 | // Unlike images, alt text is plain text only. no other elements are 1211 | // allowed in there 1212 | 1213 | // ![Alt text](/path/to/img.jpg "Optional title") 1214 | // 1 2 3 4 <--- captures 1215 | var m = text.match( /^!\[(.*?)\][ \t]*\([ \t]*([^")]*?)(?:[ \t]+(["'])(.*?)\3)?[ \t]*\)/ ); 1216 | 1217 | if ( m ) { 1218 | if ( m[2] && m[2][0] === "<" && m[2][m[2].length-1] === ">" ) 1219 | m[2] = m[2].substring( 1, m[2].length - 1 ); 1220 | 1221 | m[2] = this.dialect.inline.__call__.call( this, m[2], /\\/ )[0]; 1222 | 1223 | var attrs = { alt: m[1], href: m[2] || "" }; 1224 | if ( m[4] !== undefined) 1225 | attrs.title = m[4]; 1226 | 1227 | return [ m[0].length, [ "img", attrs ] ]; 1228 | } 1229 | 1230 | // ![Alt text][id] 1231 | m = text.match( /^!\[(.*?)\][ \t]*\[(.*?)\]/ ); 1232 | 1233 | if ( m ) { 1234 | // We can't check if the reference is known here as it likely wont be 1235 | // found till after. Check it in md tree->hmtl tree conversion 1236 | return [ m[0].length, [ "img_ref", { alt: m[1], ref: m[2].toLowerCase(), original: m[0] } ] ]; 1237 | } 1238 | 1239 | // Just consume the '![' 1240 | return [ 2, "![" ]; 1241 | }, 1242 | 1243 | "[": function link( text ) { 1244 | 1245 | var orig = String(text); 1246 | // Inline content is possible inside `link text` 1247 | var res = inline_until_char.call( this, text.substr(1), "]" ); 1248 | 1249 | // No closing ']' found. Just consume the [ 1250 | if ( !res ) 1251 | return [ 1, "[" ]; 1252 | 1253 | var consumed = 1 + res[ 0 ], 1254 | children = res[ 1 ], 1255 | link, 1256 | attrs; 1257 | 1258 | // At this point the first [...] has been parsed. See what follows to find 1259 | // out which kind of link we are (reference or direct url) 1260 | text = text.substr( consumed ); 1261 | 1262 | // [link text](/path/to/img.jpg "Optional title") 1263 | // 1 2 3 <--- captures 1264 | // This will capture up to the last paren in the block. We then pull 1265 | // back based on if there a matching ones in the url 1266 | // ([here](/url/(test)) 1267 | // The parens have to be balanced 1268 | var m = text.match( /^\s*\([ \t]*([^"']*)(?:[ \t]+(["'])(.*?)\2)?[ \t]*\)/ ); 1269 | if ( m ) { 1270 | var url = m[1]; 1271 | consumed += m[0].length; 1272 | 1273 | if ( url && url[0] === "<" && url[url.length-1] === ">" ) 1274 | url = url.substring( 1, url.length - 1 ); 1275 | 1276 | // If there is a title we don't have to worry about parens in the url 1277 | if ( !m[3] ) { 1278 | var open_parens = 1; // One open that isn't in the capture 1279 | for ( var len = 0; len < url.length; len++ ) { 1280 | switch ( url[len] ) { 1281 | case "(": 1282 | open_parens++; 1283 | break; 1284 | case ")": 1285 | if ( --open_parens === 0) { 1286 | consumed -= url.length - len; 1287 | url = url.substring(0, len); 1288 | } 1289 | break; 1290 | } 1291 | } 1292 | } 1293 | 1294 | // Process escapes only 1295 | url = this.dialect.inline.__call__.call( this, url, /\\/ )[0]; 1296 | 1297 | attrs = { href: url || "" }; 1298 | if ( m[3] !== undefined) 1299 | attrs.title = m[3]; 1300 | 1301 | link = [ "link", attrs ].concat( children ); 1302 | return [ consumed, link ]; 1303 | } 1304 | 1305 | // [Alt text][id] 1306 | // [Alt text] [id] 1307 | m = text.match( /^\s*\[(.*?)\]/ ); 1308 | 1309 | if ( m ) { 1310 | 1311 | consumed += m[ 0 ].length; 1312 | 1313 | // [links][] uses links as its reference 1314 | attrs = { ref: ( m[ 1 ] || String(children) ).toLowerCase(), original: orig.substr( 0, consumed ) }; 1315 | 1316 | link = [ "link_ref", attrs ].concat( children ); 1317 | 1318 | // We can't check if the reference is known here as it likely wont be 1319 | // found till after. Check it in md tree->hmtl tree conversion. 1320 | // Store the original so that conversion can revert if the ref isn't found. 1321 | return [ consumed, link ]; 1322 | } 1323 | 1324 | // [id] 1325 | // Only if id is plain (no formatting.) 1326 | if ( children.length === 1 && typeof children[0] === "string" ) { 1327 | 1328 | attrs = { ref: children[0].toLowerCase(), original: orig.substr( 0, consumed ) }; 1329 | link = [ "link_ref", attrs, children[0] ]; 1330 | return [ consumed, link ]; 1331 | } 1332 | 1333 | // Just consume the "[" 1334 | return [ 1, "[" ]; 1335 | }, 1336 | 1337 | 1338 | "<": function autoLink( text ) { 1339 | var m; 1340 | 1341 | if ( ( m = text.match( /^<(?:((https?|ftp|mailto):[^>]+)|(.*?@.*?\.[a-zA-Z]+))>/ ) ) !== null ) { 1342 | if ( m[3] ) 1343 | return [ m[0].length, [ "link", { href: "mailto:" + m[3] }, m[3] ] ]; 1344 | else if ( m[2] === "mailto" ) 1345 | return [ m[0].length, [ "link", { href: m[1] }, m[1].substr("mailto:".length ) ] ]; 1346 | else 1347 | return [ m[0].length, [ "link", { href: m[1] }, m[1] ] ]; 1348 | } 1349 | 1350 | return [ 1, "<" ]; 1351 | }, 1352 | 1353 | "`": function inlineCode( text ) { 1354 | // Inline code block. as many backticks as you like to start it 1355 | // Always skip over the opening ticks. 1356 | var m = text.match( /(`+)(([\s\S]*?)\1)/ ); 1357 | 1358 | if ( m && m[2] ) 1359 | return [ m[1].length + m[2].length, [ "inlinecode", m[3] ] ]; 1360 | else { 1361 | // TODO: No matching end code found - warn! 1362 | return [ 1, "`" ]; 1363 | } 1364 | }, 1365 | 1366 | " \n": function lineBreak() { 1367 | return [ 3, [ "linebreak" ] ]; 1368 | } 1369 | 1370 | } 1371 | }; 1372 | 1373 | // Meta Helper/generator method for em and strong handling 1374 | function strong_em( tag, md ) { 1375 | 1376 | var state_slot = tag + "_state", 1377 | other_slot = tag === "strong" ? "em_state" : "strong_state"; 1378 | 1379 | function CloseTag(len) { 1380 | this.len_after = len; 1381 | this.name = "close_" + md; 1382 | } 1383 | 1384 | return function ( text ) { 1385 | 1386 | if ( this[state_slot][0] === md ) { 1387 | // Most recent em is of this type 1388 | //D:this.debug("closing", md); 1389 | this[state_slot].shift(); 1390 | 1391 | // "Consume" everything to go back to the recrusion in the else-block below 1392 | return[ text.length, new CloseTag(text.length-md.length) ]; 1393 | } 1394 | else { 1395 | // Store a clone of the em/strong states 1396 | var other = this[other_slot].slice(), 1397 | state = this[state_slot].slice(); 1398 | 1399 | this[state_slot].unshift(md); 1400 | 1401 | //D:this.debug_indent += " "; 1402 | 1403 | // Recurse 1404 | var res = this.processInline( text.substr( md.length ) ); 1405 | //D:this.debug_indent = this.debug_indent.substr(2); 1406 | 1407 | var last = res[res.length - 1]; 1408 | 1409 | //D:this.debug("processInline from", tag + ": ", uneval( res ) ); 1410 | 1411 | var check = this[state_slot].shift(); 1412 | if ( last instanceof CloseTag ) { 1413 | res.pop(); 1414 | // We matched! Huzzah. 1415 | var consumed = text.length - last.len_after; 1416 | return [ consumed, [ tag ].concat(res) ]; 1417 | } 1418 | else { 1419 | // Restore the state of the other kind. We might have mistakenly closed it. 1420 | this[other_slot] = other; 1421 | this[state_slot] = state; 1422 | 1423 | // We can't reuse the processed result as it could have wrong parsing contexts in it. 1424 | return [ md.length, md ]; 1425 | } 1426 | } 1427 | }; // End returned function 1428 | } 1429 | 1430 | Gruber.inline["**"] = strong_em("strong", "**"); 1431 | Gruber.inline["__"] = strong_em("strong", "__"); 1432 | Gruber.inline["*"] = strong_em("em", "*"); 1433 | Gruber.inline["_"] = strong_em("em", "_"); 1434 | 1435 | Markdown.dialects.Gruber = Gruber; 1436 | Markdown.buildBlockOrder ( Markdown.dialects.Gruber.block ); 1437 | Markdown.buildInlinePatterns( Markdown.dialects.Gruber.inline ); 1438 | 1439 | 1440 | 1441 | var Maruku = DialectHelpers.subclassDialect( Gruber ), 1442 | extract_attr = MarkdownHelpers.extract_attr, 1443 | forEach = MarkdownHelpers.forEach; 1444 | 1445 | Maruku.processMetaHash = function processMetaHash( meta_string ) { 1446 | var meta = split_meta_hash( meta_string ), 1447 | attr = {}; 1448 | 1449 | for ( var i = 0; i < meta.length; ++i ) { 1450 | // id: #foo 1451 | if ( /^#/.test( meta[ i ] ) ) 1452 | attr.id = meta[ i ].substring( 1 ); 1453 | // class: .foo 1454 | else if ( /^\./.test( meta[ i ] ) ) { 1455 | // if class already exists, append the new one 1456 | if ( attr["class"] ) 1457 | attr["class"] = attr["class"] + meta[ i ].replace( /./, " " ); 1458 | else 1459 | attr["class"] = meta[ i ].substring( 1 ); 1460 | } 1461 | // attribute: foo=bar 1462 | else if ( /\=/.test( meta[ i ] ) ) { 1463 | var s = meta[ i ].split( /\=/ ); 1464 | attr[ s[ 0 ] ] = s[ 1 ]; 1465 | } 1466 | } 1467 | 1468 | return attr; 1469 | }; 1470 | 1471 | function split_meta_hash( meta_string ) { 1472 | var meta = meta_string.split( "" ), 1473 | parts = [ "" ], 1474 | in_quotes = false; 1475 | 1476 | while ( meta.length ) { 1477 | var letter = meta.shift(); 1478 | switch ( letter ) { 1479 | case " " : 1480 | // if we're in a quoted section, keep it 1481 | if ( in_quotes ) 1482 | parts[ parts.length - 1 ] += letter; 1483 | // otherwise make a new part 1484 | else 1485 | parts.push( "" ); 1486 | break; 1487 | case "'" : 1488 | case '"' : 1489 | // reverse the quotes and move straight on 1490 | in_quotes = !in_quotes; 1491 | break; 1492 | case "\\" : 1493 | // shift off the next letter to be used straight away. 1494 | // it was escaped so we'll keep it whatever it is 1495 | letter = meta.shift(); 1496 | /* falls through */ 1497 | default : 1498 | parts[ parts.length - 1 ] += letter; 1499 | break; 1500 | } 1501 | } 1502 | 1503 | return parts; 1504 | } 1505 | 1506 | Maruku.block.document_meta = function document_meta( block ) { 1507 | // we're only interested in the first block 1508 | if ( block.lineNumber > 1 ) 1509 | return undefined; 1510 | 1511 | // document_meta blocks consist of one or more lines of `Key: Value\n` 1512 | if ( ! block.match( /^(?:\w+:.*\n)*\w+:.*$/ ) ) 1513 | return undefined; 1514 | 1515 | // make an attribute node if it doesn't exist 1516 | if ( !extract_attr( this.tree ) ) 1517 | this.tree.splice( 1, 0, {} ); 1518 | 1519 | var pairs = block.split( /\n/ ); 1520 | for ( var p in pairs ) { 1521 | var m = pairs[ p ].match( /(\w+):\s*(.*)$/ ), 1522 | key = m[ 1 ].toLowerCase(), 1523 | value = m[ 2 ]; 1524 | 1525 | this.tree[ 1 ][ key ] = value; 1526 | } 1527 | 1528 | // document_meta produces no content! 1529 | return []; 1530 | }; 1531 | 1532 | Maruku.block.block_meta = function block_meta( block ) { 1533 | // check if the last line of the block is an meta hash 1534 | var m = block.match( /(^|\n) {0,3}\{:\s*((?:\\\}|[^\}])*)\s*\}$/ ); 1535 | if ( !m ) 1536 | return undefined; 1537 | 1538 | // process the meta hash 1539 | var attr = this.dialect.processMetaHash( m[ 2 ] ), 1540 | hash; 1541 | 1542 | // if we matched ^ then we need to apply meta to the previous block 1543 | if ( m[ 1 ] === "" ) { 1544 | var node = this.tree[ this.tree.length - 1 ]; 1545 | hash = extract_attr( node ); 1546 | 1547 | // if the node is a string (rather than JsonML), bail 1548 | if ( typeof node === "string" ) 1549 | return undefined; 1550 | 1551 | // create the attribute hash if it doesn't exist 1552 | if ( !hash ) { 1553 | hash = {}; 1554 | node.splice( 1, 0, hash ); 1555 | } 1556 | 1557 | // add the attributes in 1558 | for ( var a in attr ) 1559 | hash[ a ] = attr[ a ]; 1560 | 1561 | // return nothing so the meta hash is removed 1562 | return []; 1563 | } 1564 | 1565 | // pull the meta hash off the block and process what's left 1566 | var b = block.replace( /\n.*$/, "" ), 1567 | result = this.processBlock( b, [] ); 1568 | 1569 | // get or make the attributes hash 1570 | hash = extract_attr( result[ 0 ] ); 1571 | if ( !hash ) { 1572 | hash = {}; 1573 | result[ 0 ].splice( 1, 0, hash ); 1574 | } 1575 | 1576 | // attach the attributes to the block 1577 | for ( var a in attr ) 1578 | hash[ a ] = attr[ a ]; 1579 | 1580 | return result; 1581 | }; 1582 | 1583 | Maruku.block.definition_list = function definition_list( block, next ) { 1584 | // one or more terms followed by one or more definitions, in a single block 1585 | var tight = /^((?:[^\s:].*\n)+):\s+([\s\S]+)$/, 1586 | list = [ "dl" ], 1587 | i, m; 1588 | 1589 | // see if we're dealing with a tight or loose block 1590 | if ( ( m = block.match( tight ) ) ) { 1591 | // pull subsequent tight DL blocks out of `next` 1592 | var blocks = [ block ]; 1593 | while ( next.length && tight.exec( next[ 0 ] ) ) 1594 | blocks.push( next.shift() ); 1595 | 1596 | for ( var b = 0; b < blocks.length; ++b ) { 1597 | var m = blocks[ b ].match( tight ), 1598 | terms = m[ 1 ].replace( /\n$/, "" ).split( /\n/ ), 1599 | defns = m[ 2 ].split( /\n:\s+/ ); 1600 | 1601 | // print( uneval( m ) ); 1602 | 1603 | for ( i = 0; i < terms.length; ++i ) 1604 | list.push( [ "dt", terms[ i ] ] ); 1605 | 1606 | for ( i = 0; i < defns.length; ++i ) { 1607 | // run inline processing over the definition 1608 | list.push( [ "dd" ].concat( this.processInline( defns[ i ].replace( /(\n)\s+/, "$1" ) ) ) ); 1609 | } 1610 | } 1611 | } 1612 | else { 1613 | return undefined; 1614 | } 1615 | 1616 | return [ list ]; 1617 | }; 1618 | 1619 | // splits on unescaped instances of @ch. If @ch is not a character the result 1620 | // can be unpredictable 1621 | 1622 | Maruku.block.table = function table ( block ) { 1623 | 1624 | var _split_on_unescaped = function( s, ch ) { 1625 | ch = ch || '\\s'; 1626 | if ( ch.match(/^[\\|\[\]{}?*.+^$]$/) ) 1627 | ch = '\\' + ch; 1628 | var res = [ ], 1629 | r = new RegExp('^((?:\\\\.|[^\\\\' + ch + '])*)' + ch + '(.*)'), 1630 | m; 1631 | while ( ( m = s.match( r ) ) ) { 1632 | res.push( m[1] ); 1633 | s = m[2]; 1634 | } 1635 | res.push(s); 1636 | return res; 1637 | }; 1638 | 1639 | var leading_pipe = /^ {0,3}\|(.+)\n {0,3}\|\s*([\-:]+[\-| :]*)\n((?:\s*\|.*(?:\n|$))*)(?=\n|$)/, 1640 | // find at least an unescaped pipe in each line 1641 | no_leading_pipe = /^ {0,3}(\S(?:\\.|[^\\|])*\|.*)\n {0,3}([\-:]+\s*\|[\-| :]*)\n((?:(?:\\.|[^\\|])*\|.*(?:\n|$))*)(?=\n|$)/, 1642 | i, 1643 | m; 1644 | if ( ( m = block.match( leading_pipe ) ) ) { 1645 | // remove leading pipes in contents 1646 | // (header and horizontal rule already have the leading pipe left out) 1647 | m[3] = m[3].replace(/^\s*\|/gm, ''); 1648 | } else if ( ! ( m = block.match( no_leading_pipe ) ) ) { 1649 | return undefined; 1650 | } 1651 | 1652 | var table = [ "table", [ "thead", [ "tr" ] ], [ "tbody" ] ]; 1653 | 1654 | // remove trailing pipes, then split on pipes 1655 | // (no escaped pipes are allowed in horizontal rule) 1656 | m[2] = m[2].replace(/\|\s*$/, '').split('|'); 1657 | 1658 | // process alignment 1659 | var html_attrs = [ ]; 1660 | forEach (m[2], function (s) { 1661 | if (s.match(/^\s*-+:\s*$/)) 1662 | html_attrs.push({align: "right"}); 1663 | else if (s.match(/^\s*:-+\s*$/)) 1664 | html_attrs.push({align: "left"}); 1665 | else if (s.match(/^\s*:-+:\s*$/)) 1666 | html_attrs.push({align: "center"}); 1667 | else 1668 | html_attrs.push({}); 1669 | }); 1670 | 1671 | // now for the header, avoid escaped pipes 1672 | m[1] = _split_on_unescaped(m[1].replace(/\|\s*$/, ''), '|'); 1673 | for (i = 0; i < m[1].length; i++) { 1674 | table[1][1].push(['th', html_attrs[i] || {}].concat( 1675 | this.processInline(m[1][i].trim()))); 1676 | } 1677 | 1678 | // now for body contents 1679 | forEach (m[3].replace(/\|\s*$/mg, '').split('\n'), function (row) { 1680 | var html_row = ['tr']; 1681 | row = _split_on_unescaped(row, '|'); 1682 | for (i = 0; i < row.length; i++) 1683 | html_row.push(['td', html_attrs[i] || {}].concat(this.processInline(row[i].trim()))); 1684 | table[2].push(html_row); 1685 | }, this); 1686 | 1687 | return [table]; 1688 | }; 1689 | 1690 | Maruku.inline[ "{:" ] = function inline_meta( text, matches, out ) { 1691 | if ( !out.length ) 1692 | return [ 2, "{:" ]; 1693 | 1694 | // get the preceeding element 1695 | var before = out[ out.length - 1 ]; 1696 | 1697 | if ( typeof before === "string" ) 1698 | return [ 2, "{:" ]; 1699 | 1700 | // match a meta hash 1701 | var m = text.match( /^\{:\s*((?:\\\}|[^\}])*)\s*\}/ ); 1702 | 1703 | // no match, false alarm 1704 | if ( !m ) 1705 | return [ 2, "{:" ]; 1706 | 1707 | // attach the attributes to the preceeding element 1708 | var meta = this.dialect.processMetaHash( m[ 1 ] ), 1709 | attr = extract_attr( before ); 1710 | 1711 | if ( !attr ) { 1712 | attr = {}; 1713 | before.splice( 1, 0, attr ); 1714 | } 1715 | 1716 | for ( var k in meta ) 1717 | attr[ k ] = meta[ k ]; 1718 | 1719 | // cut out the string and replace it with nothing 1720 | return [ m[ 0 ].length, "" ]; 1721 | }; 1722 | 1723 | 1724 | Markdown.dialects.Maruku = Maruku; 1725 | Markdown.dialects.Maruku.inline.__escape__ = /^\\[\\`\*_{}\[\]()#\+.!\-|:]/; 1726 | Markdown.buildBlockOrder ( Markdown.dialects.Maruku.block ); 1727 | Markdown.buildInlinePatterns( Markdown.dialects.Maruku.inline ); 1728 | 1729 | 1730 | // Include all our depndencies and; 1731 | expose.Markdown = Markdown; 1732 | expose.parse = Markdown.parse; 1733 | expose.toHTML = Markdown.toHTML; 1734 | expose.toHTMLTree = Markdown.toHTMLTree; 1735 | expose.renderJsonML = Markdown.renderJsonML; 1736 | 1737 | })(function() { 1738 | window.markdown = {}; 1739 | return window.markdown; 1740 | }()); 1741 | --------------------------------------------------------------------------------