You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 

404 lines
44 KiB

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="utf-8">
  5. <meta http-equiv="X-UA-Compatible" content="IE=edge">
  6. <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=no">
  7. <meta name="apple-mobile-web-app-capable" content="yes">
  8. <meta name="apple-mobile-web-app-status-bar-style" content="black">
  9. <meta name="mobile-web-app-capable" content="yes">
  10. <title>
  11. Lab 4: Text filtering editors - HackMD
  12. </title>
  13. <link rel="icon" type="image/png" href="https://hackmd.io/favicon.png">
  14. <link rel="apple-touch-icon" href="https://hackmd.io/apple-touch-icon.png">
  15. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha256-916EbMg70RQy9LHiGkXzG8hSg9EdNy97GazNG/aiY1w=" crossorigin="anonymous" />
  16. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha256-eZrrJcwDc/3uDhsdt61sL2oOBY362qM3lon1gyExkL0=" crossorigin="anonymous" />
  17. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/ionicons/2.0.1/css/ionicons.min.css" integrity="sha256-3iu9jgsy9TpTwXKb7bNQzqWekRX7pPK+2OLj3R922fo=" crossorigin="anonymous" />
  18. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/octicons/3.5.0/octicons.min.css" integrity="sha256-QiWfLIsCT02Sdwkogf6YMiQlj4NE84MKkzEMkZnMGdg=" crossorigin="anonymous" />
  19. <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.5.1/themes/prism.min.css" integrity="sha256-vtR0hSWRc3Tb26iuN2oZHt3KRUomwTufNIf5/4oeCyg=" crossorigin="anonymous" />
  20. <link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@hackmd/emojify.js@2.1.0/dist/css/basic/emojify.min.css" integrity="sha256-UOrvMOsSDSrW6szVLe8ZDZezBxh5IoIfgTwdNDgTjiU=" crossorigin="anonymous" />
  21. <style>
  22. @import url(https://fonts.googleapis.com/css?family=Roboto:300,300i,400,400i,500,500i|Source+Code+Pro:300,400,500|Source+Sans+Pro:300,300i,400,400i,600,600i|Source+Serif+Pro&subset=latin-ext);.hljs{background:#fff;color:#333;display:block;overflow-x:auto;padding:.5em}.hljs-comment,.hljs-meta{color:#969896}.hljs-emphasis,.hljs-quote,.hljs-string,.hljs-strong,.hljs-template-variable,.hljs-variable{color:#df5000}.hljs-keyword,.hljs-selector-tag,.hljs-type{color:#a71d5d}.hljs-attribute,.hljs-bullet,.hljs-literal,.hljs-number,.hljs-symbol{color:#0086b3}.hljs-built_in,.hljs-builtin-name{color:#005cc5}.hljs-name,.hljs-section{color:#63a35c}.hljs-tag{color:#333}.hljs-attr,.hljs-selector-attr,.hljs-selector-class,.hljs-selector-id,.hljs-selector-pseudo,.hljs-title{color:#795da3}.hljs-addition{background-color:#eaffea;color:#55a532}.hljs-deletion{background-color:#ffecec;color:#bd2c00}.hljs-link{text-decoration:underline}.markdown-body{word-wrap:break-word;font-size:16px;line-height:1.5}.markdown-body:after,.markdown-body:before{content:"";display:table}.markdown-body:after{clear:both}.markdown-body>:first-child{margin-top:0!important}.markdown-body>:last-child{margin-bottom:0!important}.markdown-body a:not([href]){color:inherit;text-decoration:none}.markdown-body .absent{color:#c00}.markdown-body .anchor{float:left;line-height:1;margin-left:-20px;padding-right:4px}.markdown-body .anchor:focus{outline:none}.markdown-body blockquote,.markdown-body dl,.markdown-body ol,.markdown-body p,.markdown-body pre,.markdown-body table,.markdown-body ul{margin-bottom:16px;margin-top:0}.markdown-body hr{background-color:#e7e7e7;border:0;height:.25em;margin:24px 0;padding:0}.markdown-body blockquote{border-left:.25em solid #ddd;color:#777;font-size:16px;padding:0 1em}.markdown-body blockquote>:first-child{margin-top:0}.markdown-body blockquote>:last-child{margin-bottom:0}.markdown-body kbd,.popover kbd{background-color:#fcfcfc;border:1px solid;border-color:#ccc #ccc #bbb;border-radius:3px;box-shadow:inset 0 -1px 0 #bbb;color:#555;display:inline-block;font-size:11px;line-height:10px;padding:3px 5px;vertical-align:middle}.markdown-body .loweralpha{list-style-type:lower-alpha}.markdown-body h1,.markdown-body h2,.markdown-body h3,.markdown-body h4,.markdown-body h5,.markdown-body h6{font-weight:600;line-height:1.25;margin-bottom:16px;margin-top:24px}.markdown-body h1 .octicon-link,.markdown-body h2 .octicon-link,.markdown-body h3 .octicon-link,.markdown-body h4 .octicon-link,.markdown-body h5 .octicon-link,.markdown-body h6 .octicon-link{color:#000;vertical-align:middle;visibility:hidden}.markdown-body h1:hover .anchor,.markdown-body h2:hover .anchor,.markdown-body h3:hover .anchor,.markdown-body h4:hover .anchor,.markdown-body h5:hover .anchor,.markdown-body h6:hover .anchor{text-decoration:none}.markdown-body h1:hover .anchor .octicon-link,.markdown-body h2:hover .anchor .octicon-link,.markdown-body h3:hover .anchor .octicon-link,.markdown-body h4:hover .anchor .octicon-link,.markdown-body h5:hover .anchor .octicon-link,.markdown-body h6:hover .anchor .octicon-link{visibility:visible}.markdown-body h1 code,.markdown-body h1 tt,.markdown-body h2 code,.markdown-body h2 tt,.markdown-body h3 code,.markdown-body h3 tt,.markdown-body h4 code,.markdown-body h4 tt,.markdown-body h5 code,.markdown-body h5 tt,.markdown-body h6 code,.markdown-body h6 tt{font-size:inherit}.markdown-body h1{font-size:2em}.markdown-body h1,.markdown-body h2{border-bottom:1px solid #eee;padding-bottom:.3em}.markdown-body h2{font-size:1.5em}.markdown-body h3{font-size:1.25em}.markdown-body h4{font-size:1em}.markdown-body h5{font-size:.875em}.markdown-body h6{color:#777;font-size:.85em}.markdown-body ol,.markdown-body ul{padding-left:2em}.markdown-body ol.no-list,.markdown-body ul.no-list{list-style-type:none;padding:0}.markdown-body ol ol,.markdown-body ol ul,.markdown-body ul ol,.markdown-body ul ul{margin-bottom:0;margin-top:0}.markdown-body li>p{margin-top:16px}.markdown-body li+li{padding-top:.25em}.markdown-body dl{padding:0}.markdown-body dl dt{font-size:1em;font-style:italic;font-weight:700;margin-top:16px;padding:0}.markdown-body dl dd{margin-bottom:16px;padding:0 16px}.markdown-body table{display:block;overflow:auto;width:100%;word-break:normal;word-break:keep-all}.markdown-body table th{font-weight:700}.markdown-body table td,.markdown-body table th{border:1px solid #ddd;padding:6px 13px}.markdown-body table tr{background-color:#fff;border-top:1px solid #ccc}.markdown-body table tr:nth-child(2n){background-color:#f8f8f8}.markdown-body img{background-color:#fff;box-sizing:initial;max-width:100%}.markdown-body img[align=right]{padding-left:20px}.markdown-body img[align=left]{padding-right:20px}.markdown-body .emoji{background-color:initial;max-width:none;vertical-align:text-top}.markdown-body span.frame{display:block;overflow:hidden}.markdown-body span.frame>span{border:1px solid #ddd;display:block;float:left;margin:13px 0 0;overflow:hidden;padding:7px;width:auto}.markdown-body span.frame span img{display:block;float:left}.markdown-body span.frame span span{clear:both;color:#333;display:block;padding:5px 0 0}.markdown-body span.align-center{clear:both;display:block;overflow:hidden}.markdown-body span.align-center>span{display:block;margin:13px auto 0;overflow:hidden;text-align:center}.markdown-body span.align-center span img{margin:0 auto;text-align:center}.markdown-body span.align-right{clear:both;display:block;overflow:hidden}.markdown-body span.align-right>span{display:block;margin:13px 0 0;overflow:hidden;text-align:right}.markdown-body span.align-right span img{margin:0;text-align:right}.markdown-body span.float-left{display:block;float:left;margin-right:13px;overflow:hidden}.markdown-body span.float-left span{margin:13px 0 0}.markdown-body span.float-right{display:block;float:right;margin-left:13px;overflow:hidden}.markdown-body span.float-right>span{display:block;margin:13px auto 0;overflow:hidden;text-align:right}.markdown-body code,.markdown-body tt{background-color:#0000000a;border-radius:3px;font-size:85%;margin:0;padding:.2em 0}.markdown-body code:after,.markdown-body code:before,.markdown-body tt:after,.markdown-body tt:before{content:"\00a0";letter-spacing:-.2em}.markdown-body code br,.markdown-body tt br{display:none}.markdown-body del code{text-decoration:inherit}.markdown-body pre{word-wrap:normal}.markdown-body pre>code{background:#0000;border:0;font-size:100%;margin:0;padding:0;white-space:pre;word-break:normal}.markdown-body .highlight{margin-bottom:16px}.markdown-body .highlight pre{margin-bottom:0;word-break:normal}.markdown-body .highlight pre,.markdown-body pre{background-color:#f7f7f7;border-radius:3px;font-size:85%;line-height:1.45;overflow:auto;padding:16px}.markdown-body pre code,.markdown-body pre tt{word-wrap:normal;background-color:initial;border:0;display:inline;line-height:inherit;margin:0;max-width:auto;overflow:visible;padding:0}.markdown-body pre code:after,.markdown-body pre code:before,.markdown-body pre tt:after,.markdown-body pre tt:before{content:normal}.markdown-body .csv-data td,.markdown-body .csv-data th{font-size:12px;line-height:1;overflow:hidden;padding:5px;text-align:left;white-space:nowrap}.markdown-body .csv-data .blob-line-num{background:#fff;border:0;padding:10px 8px 9px;text-align:right}.markdown-body .csv-data tr{border-top:0}.markdown-body .csv-data th{background:#f8f8f8;border-top:0;font-weight:700}.news .alert .markdown-body blockquote{border:0;padding:0 0 0 40px}.activity-tab .news .alert .commits,.activity-tab .news .markdown-body blockquote{padding-left:0}.task-list-item{list-style-type:none}.task-list-item label{font-weight:400}.task-list-item.enabled label{cursor:pointer}.task-list-item+.task-list-item{margin-top:3px}.task-list-item-checkbox{cursor:default!important;float:left;margin:.31em 0 .2em -1.3em!important;vertical-align:middle}.markdown-body{max-width:758px;overflow:visible!important;padding-bottom:40px;padding-top:40px;position:relative}.markdown-body .emoji{vertical-align:top}.markdown-body pre{border:inherit!important}.markdown-body code{color:inherit!important}.markdown-body pre code .wrapper{display:-moz-inline-flex;display:-ms-inline-flex;display:-o-inline-flex;display:inline-flex}.markdown-body pre code .gutter{float:left;overflow:hidden;-webkit-user-select:none;user-select:none}.markdown-body pre code .gutter.linenumber{border-right:3px solid #6ce26c!important;box-sizing:initial;color:#afafaf!important;cursor:default;display:inline-block;min-width:20px;padding:0 8px 0 0;position:relative;text-align:right;z-index:4}.markdown-body pre code .gutter.linenumber>span:before{content:attr(data-linenumber)}.markdown-body pre code .code{float:left;margin:0 0 0 16px}.markdown-body .gist .line-numbers{border-bottom:none;border-left:none;border-top:none}.markdown-body .gist .line-data{border:none}.markdown-body .gist table{border-collapse:inherit!important;border-spacing:0}.markdown-body code[data-gist-id]{background:none;padding:0}.markdown-body code[data-gist-id]:after,.markdown-body code[data-gist-id]:before{content:""}.markdown-body code[data-gist-id] .blob-num{border:unset}.markdown-body code[data-gist-id] table{margin-bottom:unset;overflow:unset}.markdown-body code[data-gist-id] table tr{background:unset}.markdown-body[dir=rtl] pre{direction:ltr}.markdown-body[dir=rtl] code{direction:ltr;unicode-bidi:embed}.markdown-body .alert>p:last-child{margin-bottom:0}.markdown-body pre.abc,.markdown-body pre.flow-chart,.markdown-body pre.graphviz,.markdown-body pre.mermaid,.markdown-body pre.sequence-diagram,.markdown-body pre.vega{background-color:inherit;border-radius:0;overflow:visible;text-align:center;white-space:inherit}.markdown-body pre.abc>code,.markdown-body pre.flow-chart>code,.markdown-body pre.graphviz>code,.markdown-body pre.mermaid>code,.markdown-body pre.sequence-diagram>code,.markdown-body pre.vega>code{text-align:left}.markdown-body pre.abc>svg,.markdown-body pre.flow-chart>svg,.markdown-body pre.graphviz>svg,.markdown-body pre.mermaid>svg,.markdown-body pre.sequence-diagram>svg,.markdown-body pre.vega>svg{height:100%;max-width:100%}.markdown-body pre>code.wrap{word-wrap:break-word;white-space:pre-wrap;white-space:-moz-pre-wrap;white-space:-pre-wrap;white-space:-o-pre-wrap}.markdown-body .alert>p:last-child,.markdown-body .alert>ul:last-child{margin-bottom:0}.markdown-body summary{display:list-item}.markdown-body summary:focus{outline:none}.markdown-body details summary{cursor:pointer}.markdown-body details:not([open])>:not(summary){display:none}.markdown-body figure{margin:1em 40px}.markdown-body .mark,.markdown-body mark{background-color:#fff1a7}.vimeo,.youtube{background-color:#000;background-position:50%;background-repeat:no-repeat;background-size:contain;cursor:pointer;display:table;overflow:hidden;text-align:center}.vimeo,.youtube{position:relative;width:100%}.youtube{padding-bottom:56.25%}.vimeo img{object-fit:contain;width:100%;z-index:0}.youtube img{object-fit:cover;z-index:0}.vimeo iframe,.youtube iframe,.youtube img{height:100%;left:0;position:absolute;top:0;width:100%}.vimeo iframe,.youtube iframe{vertical-align:middle;z-index:1}.vimeo .icon,.youtube .icon{color:#fff;height:auto;left:50%;opacity:.3;position:absolute;top:50%;transform:translate(-50%,-50%);transition:opacity .2s;width:auto;z-index:0}.vimeo:hover .icon,.youtube:hover .icon{opacity:.6;transition:opacity .2s}.slideshare .inner,.speakerdeck .inner{position:relative;width:100%}.slideshare .inner iframe,.speakerdeck .inner iframe{bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.figma{display:table;padding-bottom:56.25%;position:relative;width:100%}.figma iframe{border:1px solid #eee;bottom:0;height:100%;left:0;position:absolute;right:0;top:0;width:100%}.markmap-container{height:300px}.markmap-container>svg{height:100%;width:100%}.MJX_Assistive_MathML{display:none}#MathJax_Message{z-index:1000!important}.ui-infobar{color:#777;margin:25px auto -25px;max-width:760px;position:relative;z-index:2}.toc .invisable-node{list-style-type:none}.ui-toc{bottom:20px;position:fixed;z-index:998}.ui-toc.both-mode{margin-left:8px}.ui-toc.both-mode .ui-toc-label{border-bottom-left-radius:0;border-top-left-radius:0;height:40px;padding:10px 4px}.ui-toc-label{background-color:#e6e6e6;border:none;color:#868686;transition:opacity .2s}.ui-toc .open .ui-toc-label{color:#fff;opacity:1;transition:opacity .2s}.ui-toc-label:focus{background-color:#ccc;color:#000;opacity:.3}.ui-toc-label:hover{background-color:#ccc;opacity:1;transition:opacity .2s}.ui-toc-dropdown{margin-bottom:20px;margin-top:20px;max-height:70vh;max-width:45vw;overflow:auto;padding-left:10px;padding-right:10px;text-align:inherit;width:25vw}.ui-toc-dropdown>.toc{max-height:calc(70vh - 100px);overflow:auto}.ui-toc-dropdown[dir=rtl] .nav{letter-spacing:.0029em;padding-right:0}.ui-toc-dropdown a{overflow:hidden;text-overflow:ellipsis;white-space:pre}.ui-toc-dropdown .nav>li>a{color:#767676;display:block;font-size:13px;font-weight:500;padding:4px 20px}.ui-toc-dropdown .nav>li:first-child:last-child>ul,.ui-toc-dropdown .toc.expand ul{display:block}.ui-toc-dropdown .nav>li>a:focus,.ui-toc-dropdown .nav>li>a:hover{background-color:initial;border-left:1px solid #000;color:#000;padding-left:19px;text-decoration:none}.ui-toc-dropdown[dir=rtl] .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav>li>a:hover{border-left:none;border-right:1px solid #000;padding-right:19px}.ui-toc-dropdown .nav>.active:focus>a,.ui-toc-dropdown .nav>.active:hover>a,.ui-toc-dropdown .nav>.active>a{background-color:initial;border-left:2px solid #000;color:#000;font-weight:700;padding-left:18px}.ui-toc-dropdown[dir=rtl] .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav>.active>a{border-left:none;border-right:2px solid #000;padding-right:18px}.ui-toc-dropdown .nav .nav{display:none;padding-bottom:10px}.ui-toc-dropdown .nav>.active>ul{display:block}.ui-toc-dropdown .nav .nav>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:30px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a{padding-right:30px}.ui-toc-dropdown .nav .nav>li>ul>li>a{font-size:12px;font-weight:400;padding-bottom:1px;padding-left:40px;padding-top:1px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a{padding-right:40px}.ui-toc-dropdown .nav .nav>li>a:focus,.ui-toc-dropdown .nav .nav>li>a:hover{padding-left:29px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>a:hover{padding-right:29px}.ui-toc-dropdown .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown .nav .nav>li>ul>li>a:hover{padding-left:39px}.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:focus,.ui-toc-dropdown[dir=rtl] .nav .nav>li>ul>li>a:hover{padding-right:39px}.ui-toc-dropdown .nav .nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>a{font-weight:500;padding-left:28px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>a{padding-right:28px}.ui-toc-dropdown .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown .nav .nav>.active>.nav>.active>a{font-weight:500;padding-left:38px}.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:focus>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active:hover>a,.ui-toc-dropdown[dir=rtl] .nav .nav>.active>.nav>.active>a{padding-right:38px}.markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-tw] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang=zh-cn] .markdown-body{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang^=ja]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-tw]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html .markdown-body[lang=zh-cn]{font-family:-apple-system,BlinkMacSystemFont,Segoe UI,Helvetica Neue,Helvetica,Roboto,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol}html[lang^=ja] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,MS Pゴシック,sans-serif}html[lang=zh-tw] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html[lang=zh-cn] .ui-toc-dropdown{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}html .ui-toc-dropdown[lang^=ja]{font-family:Source Sans Pro,Helvetica,Arial,Meiryo UI,MS PGothic,MS Pゴシック,sans-serif}html .ui-toc-dropdown[lang=zh-tw]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft JhengHei UI,微軟正黑UI,sans-serif}html .ui-toc-dropdown[lang=zh-cn]{font-family:Source Sans Pro,Helvetica,Arial,Microsoft YaHei UI,微软雅黑UI,sans-serif}.ui-affix-toc{max-height:70vh;max-width:15vw;overflow:auto;position:fixed;top:0}.back-to-top,.expand-toggle,.go-to-bottom{color:#999;display:block;font-size:12px;font-weight:500;margin-left:10px;margin-top:10px;padding:4px 10px}.back-to-top:focus,.back-to-top:hover,.expand-toggle:focus,.expand-toggle:hover,.go-to-bottom:focus,.go-to-bottom:hover{color:#563d7c;text-decoration:none}.back-to-top,.go-to-bottom{margin-top:0}.ui-user-icon{background-position:50%;background-repeat:no-repeat;background-size:cover;border-radius:50%;display:block;height:20px;margin-bottom:2px;margin-right:5px;margin-top:2px;width:20px}.ui-user-icon.small{display:inline-block;height:18px;margin:0 0 .2em;vertical-align:middle;width:18px}.ui-infobar>small>span{line-height:22px}.ui-infobar>small .dropdown{display:inline-block}.ui-infobar>small .dropdown a:focus,.ui-infobar>small .dropdown a:hover{text-decoration:none}.ui-more-info{color:#888;cursor:pointer;vertical-align:middle}.ui-more-info .fa{font-size:16px}.ui-connectedGithub,.ui-published-note{color:#888}.ui-connectedGithub{line-height:23px;white-space:nowrap}.ui-connectedGithub a.file-path{color:#888;padding-left:22px;text-decoration:none}.ui-connectedGithub a.file-path:active,.ui-connectedGithub a.file-path:hover{color:#888;text-decoration:underline}.ui-connectedGithub .fa{font-size:20px}.ui-published-note .fa{font-size:20px;vertical-align:top}.unselectable{-webkit-user-select:none;-o-user-select:none;user-select:none}.selectable{-webkit-user-select:text;-o-user-select:text;user-select:text}.inline-spoiler-section{cursor:pointer}.inline-spoiler-section .spoiler-text{background-color:#333;border-radius:2px}.inline-spoiler-section .spoiler-text>*{opacity:0}.inline-spoiler-section .spoiler-img{filter:blur(10px)}.inline-spoiler-section.raw{background-color:#333;border-radius:2px}.inline-spoiler-section.raw>*{opacity:0}.inline-spoiler-section.unveil{cursor:auto}.inline-spoiler-section.unveil .spoiler-text{background-color:#3333331a}.inline-spoiler-section.unveil .spoiler-text>*{opacity:1}.inline-spoiler-section.unveil .spoiler-img{filter:none}@media print{blockquote,div,img,pre,table{page-break-inside:avoid!important}a[href]:after{font-size:12px!important}}.markdown-body.slides{color:#222;position:relative;z-index:1}.markdown-body.slides:before{background-color:currentColor;bottom:0;box-shadow:0 0 0 50vw;content:"";display:block;left:0;position:absolute;right:0;top:0;z-index:-1}.markdown-body.slides section[data-markdown]{background-color:#fff;margin-bottom:1.5em;position:relative;text-align:center}.markdown-body.slides section[data-markdown] code{text-align:left}.markdown-body.slides section[data-markdown]:before{content:"";display:block;padding-bottom:56.23%}.markdown-body.slides section[data-markdown]>div:first-child{left:1em;max-height:100%;overflow:hidden;position:absolute;right:1em;top:50%;transform:translateY(-50%)}.markdown-body.slides section[data-markdown]>ul{display:inline-block}.markdown-body.slides>section>section+section:after{border:3px solid #777;content:"";height:1.5em;position:absolute;right:1em;top:-1.5em}.site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,sans-serif}html[lang^=ja] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif}html[lang=zh-tw] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] .site-ui-font{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}body{font-smoothing:subpixel-antialiased!important;-webkit-font-smoothing:subpixel-antialiased!important;-moz-osx-font-smoothing:auto!important;-webkit-overflow-scrolling:touch;font-family:Source Sans Pro,Helvetica,Arial,sans-serif;letter-spacing:.025em}html[lang^=ja] body{font-family:Source Sans Pro,Helvetica,Arial,Hiragino Kaku Gothic Pro,ヒラギノ角ゴ Pro W3,Osaka,Meiryo,メイリオ,MS Gothic,MS ゴシック,sans-serif}html[lang=zh-tw] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang TC,Microsoft JhengHei,微軟正黑,sans-serif}html[lang=zh-cn] body{font-family:Source Sans Pro,Helvetica,Arial,PingFang SC,Microsoft YaHei,微软雅黑,sans-serif}abbr[title]{border-bottom:none;text-decoration:underline;-webkit-text-decoration:underline dotted;text-decoration:underline dotted}abbr[data-original-title],abbr[title]{cursor:help}body.modal-open{overflow-y:auto;padding-right:0!important}svg{text-shadow:none}
  23. </style>
  24. <!-- HTML5 shim and Respond.js for IE8 support of HTML5 elements and media queries -->
  25. <!-- WARNING: Respond.js doesn't work if you view the page via file:// -->
  26. <!--[if lt IE 9]>
  27. <script src="https://cdnjs.cloudflare.com/ajax/libs/html5shiv/3.7.3/html5shiv.min.js" integrity="sha256-3Jy/GbSLrg0o9y5Z5n1uw0qxZECH7C6OQpVBgNFYa0g=" crossorigin="anonymous"></script>
  28. <script src="https://cdnjs.cloudflare.com/ajax/libs/respond.js/1.4.2/respond.min.js" integrity="sha256-g6iAfvZp+nDQ2TdTR/VVKJf3bGro4ub5fvWSWVRi2NE=" crossorigin="anonymous"></script>
  29. <script src="https://cdnjs.cloudflare.com/ajax/libs/es5-shim/4.5.9/es5-shim.min.js" integrity="sha256-8E4Is26QH0bD52WoQpcB+R/tcWQtpzlCojrybUd7Mxo=" crossorigin="anonymous"></script>
  30. <![endif]-->
  31. </head>
  32. <body>
  33. <div id="doc" class="markdown-body container-fluid comment-enabled" data-hard-breaks="true"><h1 id="Lab-4-Text-filtering-editors" data-id="Lab-4-Text-filtering-editors"><a class="anchor hidden-xs" href="#Lab-4-Text-filtering-editors" title="Lab-4-Text-filtering-editors"><span class="octicon octicon-link"></span></a><span>Lab 4: Text filtering editors</span></h1><p><span>Copy the following files from /etc to your home root folder</span></p><pre><code>$ cp /etc/fstab ~
  34. $ cp /etc/passwd ~
  35. </code></pre><h3 id="Part-1-Grep" data-id="Part-1-Grep"><a class="anchor hidden-xs" href="#Part-1-Grep" title="Part-1-Grep"><span class="octicon octicon-link"></span></a><span>Part 1: Grep</span></h3><p><span>The grep command searches for lines matching a pattern and prints the matching lines to output.</span></p><ul>
  36. <li><span>View all occurrences of “systemd” in the </span><code>passwd</code><span> file.</span><pre><code>$ grep "systemd" passwd
  37. </code></pre>
  38. <span>Sample output:</span><pre><code>systemd-network:x:100:102:systemd Network Management,,,:/run/systemd:/usr/sbin/nologin
  39. systemd-resolve:x:101:103:systemd Resolver,,,:/run/systemd:/usr/sbin/nologin
  40. systemd-timesync:x:102:104:systemd Time Synchronization,,,:/run/systemd:/usr/sbin/nologin
  41. systemd-coredump:x:999:999:systemd Core Dumper:/:/usr/sbin/nologin
  42. </code></pre>
  43. </li>
  44. <li><span>Show line number of the matches.</span><pre><code>$ grep -n "systemd" passwd
  45. </code></pre>
  46. </li>
  47. <li><span>Invert the match to show lines without “systemd”. This is done with the </span><code>-v</code><span> option.</span><pre><code>$ grep -v "systemd" passwd
  48. </code></pre>
  49. </li>
  50. </ul><p><span>It is also necessary in some cases to print the lines before or after a match.</span></p><ul>
  51. <li><span>Print 5 lines after the match.</span><pre><code>$ grep -A 5 "systemd" passwd
  52. </code></pre>
  53. </li>
  54. <li><span>Print 3 lines before the match.</span><pre><code>$ grep -B 3 "systemd" passwd
  55. </code></pre>
  56. </li>
  57. <li><span>Use the </span><code>-C</code><span> option to print 5 lines before and after a match.</span><pre><code>$ grep -C 5 "systemd" passwd
  58. </code></pre>
  59. </li>
  60. <li><span>Specify the </span><code>-P</code><span> option to use PCRE (Perl Compatible Regular Expression).</span><pre><code>$ grep -P "(systemd|root)" passwd
  61. </code></pre>
  62. </li>
  63. <li><strong><span>Class activity:</span></strong><span> Save the following lines to a file </span><code>regextest.txt</code><span> and try to match all the fields.</span><pre><code>03/22 08:51:06 INFO :...read_physical_netif: index #0, interface VLINK1 has address 129.1.1.1, ifidx 0
  64. 03/22 08:51:06 ERROR :...read_physical_netif: index #4, interface CTCD0 has address 9.67.116.98, ifidx 4
  65. </code></pre>
  66. </li>
  67. </ul><blockquote>
  68. <p><span>Regex cheat sheet: </span><a href="https://quickref.me/grep" target="_blank" rel="noopener"><span>https://quickref.me/grep</span></a></p>
  69. </blockquote><h3 id="Part-2-AWK" data-id="Part-2-AWK"><a class="anchor hidden-xs" href="#Part-2-AWK" title="Part-2-AWK"><span class="octicon octicon-link"></span></a><span>Part 2: AWK</span></h3><p><span>AWK is a language designed for text processing and typically used as a data extraction and reporting tool. It can be used like sed and grep to filter data with additional capabilities. It is a standard feature of most Unix-like operating systems.</span></p><ul>
  70. <li><span>awk can be used like grep. The syntax is shown</span><pre><code>$ awk '/systemd/{print $0}' passwd
  71. </code></pre>
  72. </li>
  73. <li><span>We can use the </span><code>gsub</code><span> method to substiture all occurrences of systemd</span><pre><code>$ awk '{gsub(/systemd/, "NEWSYSTEMD")}{print}' passwd
  74. </code></pre>
  75. </li>
  76. <li><span>Add header and footer to the text document</span><pre><code>$ awk 'BEGIN {print "PASSWD FILE\n--------------"} {print} END {print "--------------\nEND OF PASSWD FILE"}' passwd
  77. </code></pre>
  78. </li>
  79. <li><span>We can specify delimiters to separate fields in a string. In the example below, we use </span><code>:</code><span> as the delimiter</span><pre><code>$ awk -F ":" '{print $1, $6, $7}' passwd
  80. </code></pre>
  81. </li>
  82. <li><span>Numeric comparison is possible with awk.</span><pre><code>$ awk -F ":" '{ if ($3 &gt; 100) {print $0} }' passwd
  83. </code></pre>
  84. </li>
  85. </ul><h3 id="Part-3-SED" data-id="Part-3-SED"><a class="anchor hidden-xs" href="#Part-3-SED" title="Part-3-SED"><span class="octicon octicon-link"></span></a><span>Part 3: SED</span></h3><p><span>The sed command (short for stream editor) performs editing operation on text coming from standard input or file. The sed command can be used like grep but it has more functionalities.</span></p><ul>
  86. <li>
  87. <p><span>Sed by default will output the entire content of the file even when there is a match.</span></p>
  88. <pre><code>$ sed '/systemd/p' passwd
  89. </code></pre>
  90. <blockquote>
  91. <p><span>The pattern we are searching for is enclosed in the </span><code>/.../</code><span>. In this case, we are searching for “systemd”.</span><br>
  92. <span>The enclosed pattern is followed by a </span><code>p</code><span> command so that sed will print the line to standard output.</span></p>
  93. </blockquote>
  94. </li>
  95. <li>
  96. <p><span>Now, let’s use sed like grep. To print only the lines that match, we add the </span><code>-n</code><span> option.</span></p>
  97. <pre><code>$ sed -n '/systemd/p' passwd
  98. </code></pre>
  99. </li>
  100. <li>
  101. <p><span>Sed can substitute a matched pattern with another string before an output is displayed. It follows the structure </span><code>s/pattern/replacement/</code><span>.</span><br>
  102. <span>In the output, replace “systemd” with “NEWSYSTEMD”</span></p>
  103. <pre><code>$ sed -n 's/systemd/NEWSYSTEMD/p' passwd
  104. </code></pre>
  105. </li>
  106. <li>
  107. <p><span>In case you want to output all contents of the file to another file while replacing “systemd”, you can remove the </span><code>-n</code><span> option. Analyse the output from:</span></p>
  108. <pre><code>$ sed 's/systemd/NEWSYSTEMD/' passwd
  109. </code></pre>
  110. </li>
  111. <li>
  112. <p><span>We can restrict sed to perform it’s operation on a specific line number. In the example below, we restrict sed to line 1.</span></p>
  113. <pre><code>$ sed '1 s/root/NOTROOT/' passwd
  114. </code></pre>
  115. </li>
  116. <li>
  117. <p><span>We can specify a range of line numbers.</span></p>
  118. <pre><code>$ sed '2,4 s/bin/NOBIN/g' passwd
  119. </code></pre>
  120. <blockquote>
  121. <p><code>g</code><span> stands for global, which means that all matching occurrences in the line would be replaced. By default, sed will replace only the first occurrence in the line.</span></p>
  122. </blockquote>
  123. </li>
  124. <li>
  125. <p><span>We can also specify the line number where the match should start from. Sed will terminate when the first match is found.</span></p>
  126. <pre><code>$ sed -n '5,/systemd/p' passwd
  127. </code></pre>
  128. </li>
  129. <li>
  130. <p><span>Search for the word “sda” and replace it with “hda” globally (s/regexp/replacement/g), when the line contains the key “efi” (/regexp/) in the file fstab</span></p>
  131. <pre><code>$ sed '/efi/ s/sda/hda/g' fstab
  132. </code></pre>
  133. </li>
  134. <li>
  135. <p><span>Search for the word “:” and replace it with “;” when the line contains the key “root” in file passwd</span></p>
  136. <pre><code>$ sed '/root/ s/:/;/g' passwd
  137. </code></pre>
  138. </li>
  139. <li>
  140. <p><span>Create the following file called unique with the following content</span></p>
  141. <pre><code>$ vi unique.txt
  142. </code></pre>
  143. <pre><code>This line occurs only once.
  144. This line occurs twice.
  145. This line occurs twice.
  146. This line occurs three times.
  147. This line occurs three times.
  148. This line occurs three times.
  149. </code></pre>
  150. </li>
  151. <li>
  152. <p><span>Delete line 2 and 3 from the file unique</span></p>
  153. <pre><code>$ sed '2,3 d' unique.txt
  154. </code></pre>
  155. </li>
  156. <li>
  157. <p><span>Delete all line that starts with “This”</span></p>
  158. <pre><code>$ sed '/^This/ d' unique.txt
  159. </code></pre>
  160. </li>
  161. </ul><h2 id="Questions-to-answer" data-id="Questions-to-answer"><a class="anchor hidden-xs" href="#Questions-to-answer" title="Questions-to-answer"><span class="octicon octicon-link"></span></a><span>Questions to answer</span></h2><p><span>Save the following lines to a file </span><code>server-data.log</code><span>.</span></p><pre><code>2022/09/18 13:25:34 wazuh-remoted: INFO: Remote syslog allowed from: '10.110.15.0/24'
  162. 2022/09/18 13:25:34 wazuh-remoted: INFO: Remote syslog allowed from: '10.410.15.0/24'
  163. 2022/09/18 13:25:34 wazuh-remoted: ERROR: Remote syslog blocked from: '10.110.18.0/24'
  164. 2022/09/18 13:25:34 wazuh-remoted: INFO: Remote syslog allowed from: '10.110.15.0/24'
  165. 2022/09/18 13:25:35 wazuh-remoted: WARNING: Remote syslog not parsed from: '10.110.18.0/24'
  166. 2022/09/18 13:25:35 wazuh-remoted: ERROR: Remote syslog blocked from: '10.110.18.0/24'
  167. Log1 2022/09/18 13:25:35 wazuh-remoted: INFO: Remote syslog allowed from: '10.110.15.0/24'
  168. 2022/09/18 13:25:35 wazuh-remoted: INFO: Remote syslog allowed from: '10.110.15.0/24' END
  169. 2022/09/18 13:25:35 wazuh-remoted: ACTION: none INFO: Remote syslog allowed from: '10.110.15.0/24'
  170. </code></pre><blockquote>
  171. <p><strong><span>The following tasks are to be completed with either grep, sed, or awk.</span></strong><br>
  172. <strong><span>All actions are to be performed on </span><code>server-data.log</code></strong></p>
  173. </blockquote><ol>
  174. <li><span>View only error and warning messages in </span><code>server-data.log</code><span>. Show how you can do this with grep and awk.</span></li>
  175. <li><span>View every line except lines with informational messages.</span></li>
  176. <li><span>Count how many error messages are in the log.</span></li>
  177. <li><span>Hide the IP addresses. Replace all IP addresses with </span><code>xxx.xxx.xxx.xxx/xx</code><span> and save the output to a file </span><code>newlog.log</code><span>. Show the output.</span>
  178. <blockquote>
  179. <p><span>This simulates a scenario where you want to send your logs to a third-party and you need to hide some information in the log messages.</span></p>
  180. </blockquote>
  181. </li>
  182. <li><span>Write a single regular expression to match the following lines in </span><code>server-data.log</code><span>. Show the full command and regex used.</span><pre><code>2022/09/18 13:25:34 wazuh-remoted: INFO: Remote syslog allowed from: '10.110.15.0/24'
  183. 2022/09/18 13:25:34 wazuh-remoted: ERROR: Remote syslog blocked from: '10.110.18.0/24'
  184. 2022/09/18 13:25:34 wazuh-remoted: INFO: Remote syslog allowed from: '10.110.15.0/24'
  185. 2022/09/18 13:25:35 wazuh-remoted: WARNING: Remote syslog not parsed from: '10.110.18.0/24'
  186. 2022/09/18 13:25:35 wazuh-remoted: ERROR: Remote syslog blocked from: '10.110.18.0/24'
  187. </code></pre>
  188. <span>Try to be as strict as possible when matching. Identify all the fields in the logs, find the common patterns in them and match as much as you can. Your regex should validate data where necessary.</span><br>
  189. <span>For example, using the wildcard </span><code>.</code><span> to match huge portions of the lines reduces the quality of the regex.</span>
  190. <blockquote>
  191. <p><span>Of course, you can use wildcards. Just don’t use them excessively.</span></p>
  192. </blockquote>
  193. </li>
  194. </ol><h3 id="Bonus" data-id="Bonus"><a class="anchor hidden-xs" href="#Bonus" title="Bonus"><span class="octicon octicon-link"></span></a><span>Bonus</span></h3><ol start="6">
  195. <li><span>Consider the following log:</span><pre><code>at com.databricks.backend.daemon.data.client.DatabricksFileSystemV2.recordOperation(DatabricksFileSystemV2.scala:474)
  196. at com.databricks.backend.daemon.data.client.DBFSV2.initialize(DatabricksFileSystemV2.scala:64)
  197. at com.databricks.backend.daemon.data.client.DatabricksFileSystem.initialize(DatabricksFileSystem.scala:222)
  198. at org.apache.hadoop.fs.FileSystem.createFileSystem(FileSystem.java:2669)
  199. at org.apache.hadoop.fs.FileSystem.access$200(FileSystem.java:94)
  200. at org.apache.hadoop.fs.FileSystem$Cache.getInternal(FileSystem.java:2703)
  201. </code></pre>
  202. <span>Write a sed one-liner that will show stack traces lines in the following fashion:</span><pre><code>Exception occured inside method `org.apache.hadoop.fs.FileSystem$Cache.getInternal` from file `FileSystem.java` on line `2703`. The file was written in `java`.
  203. Called method org.apache.hadoop.fs.FileSystem$Cache.getInternal which calls line 2703 of file FileSystem.java. The file is written in java.
  204. </code></pre>
  205. <strong><span>HINT:</span></strong><span> sed capture groups are extra useful here</span></li>
  206. </ol></div>
  207. <div class="ui-toc dropup unselectable hidden-print" style="display:none;">
  208. <div class="pull-right dropdown">
  209. <a id="tocLabel" class="ui-toc-label btn btn-default" data-toggle="dropdown" href="#" role="button" aria-haspopup="true" aria-expanded="false" title="Table of content">
  210. <i class="fa fa-bars"></i>
  211. </a>
  212. <ul id="ui-toc" class="ui-toc-dropdown dropdown-menu" aria-labelledby="tocLabel">
  213. <div class="toc"><ul class="nav">
  214. <li><a href="#Lab-4-Text-filtering-editors" title="Lab 4: Text filtering editors">Lab 4: Text filtering editors</a><ul class="nav">
  215. <li class="invisable-node"><ul class="nav">
  216. <li><a href="#Part-1-Grep" title="Part 1: Grep">Part 1: Grep</a></li>
  217. <li><a href="#Part-2-AWK" title="Part 2: AWK">Part 2: AWK</a></li>
  218. <li><a href="#Part-3-SED" title="Part 3: SED">Part 3: SED</a></li>
  219. </ul>
  220. </li>
  221. <li><a href="#Questions-to-answer" title="Questions to answer">Questions to answer</a><ul class="nav">
  222. <li><a href="#Bonus" title="Bonus">Bonus</a></li>
  223. </ul>
  224. </li>
  225. </ul>
  226. </li>
  227. </ul>
  228. </div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
  229. </ul>
  230. </div>
  231. </div>
  232. <div id="ui-toc-affix" class="ui-affix-toc ui-toc-dropdown unselectable hidden-print" data-spy="affix" style="top:17px;display:none;" null null>
  233. <div class="toc"><ul class="nav">
  234. <li><a href="#Lab-4-Text-filtering-editors" title="Lab 4: Text filtering editors">Lab 4: Text filtering editors</a><ul class="nav">
  235. <li class="invisable-node"><ul class="nav">
  236. <li><a href="#Part-1-Grep" title="Part 1: Grep">Part 1: Grep</a></li>
  237. <li><a href="#Part-2-AWK" title="Part 2: AWK">Part 2: AWK</a></li>
  238. <li><a href="#Part-3-SED" title="Part 3: SED">Part 3: SED</a></li>
  239. </ul>
  240. </li>
  241. <li><a href="#Questions-to-answer" title="Questions to answer">Questions to answer</a><ul class="nav">
  242. <li><a href="#Bonus" title="Bonus">Bonus</a></li>
  243. </ul>
  244. </li>
  245. </ul>
  246. </li>
  247. </ul>
  248. </div><div class="toc-menu"><a class="expand-toggle" href="#">Expand all</a><a class="back-to-top" href="#">Back to top</a><a class="go-to-bottom" href="#">Go to bottom</a></div>
  249. </div>
  250. <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script>
  251. <script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha256-U5ZEeKfGNOja007MMD3YBI0A3OSZOQbeG6z2f2Y0hu8=" crossorigin="anonymous" defer></script>
  252. <script src="https://cdnjs.cloudflare.com/ajax/libs/gist-embed/2.6.0/gist-embed.min.js" integrity="sha256-KyF2D6xPIJUW5sUDSs93vWyZm+1RzIpKCexxElmxl8g=" crossorigin="anonymous" defer></script>
  253. <script>
  254. var markdown = $(".markdown-body");
  255. //smooth all hash trigger scrolling
  256. function smoothHashScroll() {
  257. var hashElements = $("a[href^='#']").toArray();
  258. for (var i = 0; i < hashElements.length; i++) {
  259. var element = hashElements[i];
  260. var $element = $(element);
  261. var hash = element.hash;
  262. if (hash) {
  263. $element.on('click', function (e) {
  264. // store hash
  265. var hash = this.hash;
  266. if ($(hash).length <= 0) return;
  267. // prevent default anchor click behavior
  268. e.preventDefault();
  269. // animate
  270. $('body, html').stop(true, true).animate({
  271. scrollTop: $(hash).offset().top
  272. }, 100, "linear", function () {
  273. // when done, add hash to url
  274. // (default click behaviour)
  275. window.location.hash = hash;
  276. });
  277. });
  278. }
  279. }
  280. }
  281. smoothHashScroll();
  282. var toc = $('.ui-toc');
  283. var tocAffix = $('.ui-affix-toc');
  284. var tocDropdown = $('.ui-toc-dropdown');
  285. //toc
  286. tocDropdown.click(function (e) {
  287. e.stopPropagation();
  288. });
  289. var enoughForAffixToc = true;
  290. function generateScrollspy() {
  291. $(document.body).scrollspy({
  292. target: ''
  293. });
  294. $(document.body).scrollspy('refresh');
  295. if (enoughForAffixToc) {
  296. toc.hide();
  297. tocAffix.show();
  298. } else {
  299. tocAffix.hide();
  300. toc.show();
  301. }
  302. $(document.body).scroll();
  303. }
  304. function windowResize() {
  305. //toc right
  306. var paddingRight = parseFloat(markdown.css('padding-right'));
  307. var right = ($(window).width() - (markdown.offset().left + markdown.outerWidth() - paddingRight));
  308. toc.css('right', right + 'px');
  309. //affix toc left
  310. var newbool;
  311. var rightMargin = (markdown.parent().outerWidth() - markdown.outerWidth()) / 2;
  312. //for ipad or wider device
  313. if (rightMargin >= 133) {
  314. newbool = true;
  315. var affixLeftMargin = (tocAffix.outerWidth() - tocAffix.width()) / 2;
  316. var left = markdown.offset().left + markdown.outerWidth() - affixLeftMargin;
  317. tocAffix.css('left', left + 'px');
  318. } else {
  319. newbool = false;
  320. }
  321. if (newbool != enoughForAffixToc) {
  322. enoughForAffixToc = newbool;
  323. generateScrollspy();
  324. }
  325. }
  326. $(window).resize(function () {
  327. windowResize();
  328. });
  329. $(document).ready(function () {
  330. windowResize();
  331. generateScrollspy();
  332. });
  333. //remove hash
  334. function removeHash() {
  335. window.location.hash = '';
  336. }
  337. var backtotop = $('.back-to-top');
  338. var gotobottom = $('.go-to-bottom');
  339. backtotop.click(function (e) {
  340. e.preventDefault();
  341. e.stopPropagation();
  342. if (scrollToTop)
  343. scrollToTop();
  344. removeHash();
  345. });
  346. gotobottom.click(function (e) {
  347. e.preventDefault();
  348. e.stopPropagation();
  349. if (scrollToBottom)
  350. scrollToBottom();
  351. removeHash();
  352. });
  353. var toggle = $('.expand-toggle');
  354. var tocExpand = false;
  355. checkExpandToggle();
  356. toggle.click(function (e) {
  357. e.preventDefault();
  358. e.stopPropagation();
  359. tocExpand = !tocExpand;
  360. checkExpandToggle();
  361. })
  362. function checkExpandToggle () {
  363. var toc = $('.ui-toc-dropdown .toc');
  364. var toggle = $('.expand-toggle');
  365. if (!tocExpand) {
  366. toc.removeClass('expand');
  367. toggle.text('Expand all');
  368. } else {
  369. toc.addClass('expand');
  370. toggle.text('Collapse all');
  371. }
  372. }
  373. function scrollToTop() {
  374. $('body, html').stop(true, true).animate({
  375. scrollTop: 0
  376. }, 100, "linear");
  377. }
  378. function scrollToBottom() {
  379. $('body, html').stop(true, true).animate({
  380. scrollTop: $(document.body)[0].scrollHeight
  381. }, 100, "linear");
  382. }
  383. </script>
  384. </body>
  385. </html>