├── docs ├── CNAME ├── robots.txt ├── image │ ├── bg_grid.png │ ├── og-img.png │ ├── bg_slash.png │ ├── img_visual.png │ ├── favicon-96x96.png │ ├── img_payment_detail.png │ ├── bg_dot.svg │ ├── wave.svg │ ├── img_bubble_deco.svg │ ├── grey_bg.svg │ ├── theme_light_red_bg.svg │ ├── theme_light_blue_bg.svg │ ├── img_visual_light.svg │ ├── red_line_bg.svg │ ├── index_portrait_1.svg │ ├── img_features.svg │ ├── img_project_2.svg │ ├── img_cta_bg.svg │ ├── index_portrait_2.svg │ ├── img_project_1.svg │ ├── theme_light_character.svg │ ├── img_apply.svg │ ├── theme_dark_character.svg │ └── img_student_experence.svg ├── webfonts │ ├── fa-brands-400.eot │ ├── fa-brands-400.ttf │ ├── fa-brands-400.woff │ ├── fa-solid-900.eot │ ├── fa-solid-900.ttf │ ├── fa-solid-900.woff │ ├── fa-solid-900.woff2 │ ├── fa-brands-400.woff2 │ ├── fa-solid-900.css │ └── fa-brands-400.css ├── sitemap.xml └── humans.txt ├── src ├── statics │ ├── CNAME │ ├── robots.txt │ ├── sitemap.xml │ └── humans.txt ├── html │ ├── layout │ │ ├── banner.pug │ │ ├── ga.pug │ │ ├── header.pug │ │ ├── layout.pug │ │ └── footer.pug │ ├── mixin │ │ └── _mixin.pug │ └── faq.pug ├── image │ ├── bg_grid.png │ ├── bg_slash.png │ ├── og-img.png │ ├── img_visual.png │ ├── favicon-96x96.png │ ├── img_payment_detail.png │ ├── bg_dot.svg │ ├── wave.svg │ ├── grey_bg.svg │ ├── theme_light_blue_bg.svg │ ├── theme_light_red_bg.svg │ ├── sprite │ │ ├── logo_lidemy.svg │ │ ├── icon_arrow_right.svg │ │ ├── icon_arrow_right_blue.svg │ │ ├── icon_arrow_right_red.svg │ │ ├── icon_avatar_4.svg │ │ ├── img_about_teacher_left.svg │ │ ├── icon_avatar_2.svg │ │ ├── icon_avatar_1.svg │ │ ├── icon_avatar_3.svg │ │ ├── icon_methods_2.svg │ │ ├── icon_methods_3.svg │ │ ├── img_about_teacher.svg │ │ └── icon_methods_1.svg │ ├── img_bubble_deco.svg │ ├── img_visual_light.svg │ ├── red_line_bg.svg │ ├── index_portrait_1.svg │ ├── img_features.svg │ ├── img_project_2.svg │ ├── index_portrait_2.svg │ ├── img_project_1.svg │ ├── img_cta_bg.svg │ ├── theme_light_character.svg │ ├── img_apply.svg │ ├── theme_dark_character.svg │ └── img_student_experence.svg ├── webfonts │ ├── fa-solid-900.ttf │ └── fa-brands-400.ttf ├── js │ ├── index.js │ ├── parallax.js │ ├── bundle │ │ ├── faq.js │ │ ├── clipboard.js │ │ └── chart.js │ ├── throttle.js │ ├── layout.js │ └── header.js └── scss │ ├── _config.scss │ ├── font-awesome │ └── scss │ │ ├── _fixed-width.scss │ │ ├── _screen-reader.scss │ │ ├── v4-shims.scss │ │ ├── _animated.scss │ │ ├── _list.scss │ │ ├── _core.scss │ │ ├── _larger.scss │ │ ├── fontawesome.scss │ │ ├── _bordered-pulled.scss │ │ ├── _stacked.scss │ │ ├── brands.scss │ │ ├── solid.scss │ │ ├── regular.scss │ │ ├── _rotated-flipped.scss │ │ └── _mixins.scss │ ├── layout │ ├── _banner.scss │ ├── _cta_block.scss │ ├── _footer.scss │ └── _header.scss │ ├── _variables.scss │ ├── _reset.scss │ ├── main.scss │ ├── _mixin.scss │ ├── _layout.scss │ ├── sprite │ └── view │ │ └── _sprite.scss │ ├── page │ └── _faq.scss │ └── _element.scss ├── .babelrc ├── .gitignore ├── README.md ├── minfont.js ├── package.json └── gulpfile.js /docs/CNAME: -------------------------------------------------------------------------------- 1 | bootcamp.lidemy.com -------------------------------------------------------------------------------- /src/statics/CNAME: -------------------------------------------------------------------------------- 1 | bootcamp.lidemy.com -------------------------------------------------------------------------------- /docs/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: -------------------------------------------------------------------------------- /src/statics/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: -------------------------------------------------------------------------------- /.babelrc: -------------------------------------------------------------------------------- 1 | { 2 | "presets": [ 3 | "@babel/preset-env" 4 | ] 5 | } -------------------------------------------------------------------------------- /src/html/layout/banner.pug: -------------------------------------------------------------------------------- 1 | section.banner 2 | p.fixed_info 🎉 第五期報名已截止 🎉 -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | public/ 3 | node_modules/ 4 | build/ 5 | src/scss/sprite/ -------------------------------------------------------------------------------- /docs/image/bg_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/image/bg_grid.png -------------------------------------------------------------------------------- /docs/image/og-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/image/og-img.png -------------------------------------------------------------------------------- /src/image/bg_grid.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/image/bg_grid.png -------------------------------------------------------------------------------- /src/image/bg_slash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/image/bg_slash.png -------------------------------------------------------------------------------- /src/image/og-img.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/image/og-img.png -------------------------------------------------------------------------------- /docs/image/bg_slash.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/image/bg_slash.png -------------------------------------------------------------------------------- /src/image/img_visual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/image/img_visual.png -------------------------------------------------------------------------------- /docs/image/img_visual.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/image/img_visual.png -------------------------------------------------------------------------------- /src/image/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/image/favicon-96x96.png -------------------------------------------------------------------------------- /docs/image/favicon-96x96.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/image/favicon-96x96.png -------------------------------------------------------------------------------- /src/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /docs/webfonts/fa-brands-400.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-brands-400.eot -------------------------------------------------------------------------------- /docs/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /docs/webfonts/fa-brands-400.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-brands-400.woff -------------------------------------------------------------------------------- /docs/webfonts/fa-solid-900.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-solid-900.eot -------------------------------------------------------------------------------- /docs/webfonts/fa-solid-900.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-solid-900.ttf -------------------------------------------------------------------------------- /docs/webfonts/fa-solid-900.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-solid-900.woff -------------------------------------------------------------------------------- /docs/webfonts/fa-solid-900.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-solid-900.woff2 -------------------------------------------------------------------------------- /src/image/img_payment_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/image/img_payment_detail.png -------------------------------------------------------------------------------- /src/js/index.js: -------------------------------------------------------------------------------- 1 | import layout from './layout' 2 | import header from './header' 3 | import parallax from './parallax' -------------------------------------------------------------------------------- /src/webfonts/fa-brands-400.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/src/webfonts/fa-brands-400.ttf -------------------------------------------------------------------------------- /docs/image/img_payment_detail.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/image/img_payment_detail.png -------------------------------------------------------------------------------- /docs/webfonts/fa-brands-400.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Lidemy/mtr-4th-web/HEAD/docs/webfonts/fa-brands-400.woff2 -------------------------------------------------------------------------------- /src/js/parallax.js: -------------------------------------------------------------------------------- 1 | import Rellax from 'rellax'; 2 | 3 | if (document.querySelector('.rellax')) { 4 | var rellax = new Rellax('.rellax'); 5 | } 6 | -------------------------------------------------------------------------------- /src/scss/_config.scss: -------------------------------------------------------------------------------- 1 | // rfs: https://github.com/twbs/rfs 2 | $rfs-base-value: 15; 3 | $rfs-breakpoint-unit: px; 4 | $rfs-breakpoint: 1000; 5 | $rfs-factor: 100; -------------------------------------------------------------------------------- /docs/image/bg_dot.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_fixed-width.scss: -------------------------------------------------------------------------------- 1 | // Fixed Width Icons 2 | // ------------------------- 3 | .#{$fa-css-prefix}-fw { 4 | text-align: center; 5 | width: $fa-fw-width; 6 | } 7 | -------------------------------------------------------------------------------- /src/image/bg_dot.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_screen-reader.scss: -------------------------------------------------------------------------------- 1 | // Screen Readers 2 | // ------------------------- 3 | 4 | .sr-only { @include sr-only; } 5 | .sr-only-focusable { @include sr-only-focusable; } 6 | -------------------------------------------------------------------------------- /docs/image/wave.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/js/bundle/faq.js: -------------------------------------------------------------------------------- 1 | import $ from 'jquery'; 2 | 3 | $(document).ready(function () { 4 | $(".faq__list__item-link").click(function (e) { 5 | e.preventDefault() 6 | $(this).closest(".faq__list__item").toggleClass("active").siblings().removeClass("active") 7 | }) 8 | }); 9 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/v4-shims.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | @import 'shims'; 7 | -------------------------------------------------------------------------------- /src/image/wave.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /docs/image/img_bubble_deco.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/html/layout/ga.pug: -------------------------------------------------------------------------------- 1 | mixin ga(id) 2 | script(async='', src='https://www.googletagmanager.com/gtag/js?id='+id) 3 | script. 4 | window.dataLayer = window.dataLayer || []; 5 | function gtag(){dataLayer.push(arguments);} 6 | gtag('js', new Date()); 7 | gtag('config', '!{id}') -------------------------------------------------------------------------------- /docs/image/grey_bg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/image/theme_light_red_bg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/image/theme_light_blue_bg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/image/grey_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/image/theme_light_blue_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/image/theme_light_red_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/scss/layout/_banner.scss: -------------------------------------------------------------------------------- 1 | /* banner -------------------- */ 2 | .banner { 3 | width: 100%; 4 | height: 40px; 5 | background: #795548; 6 | position: fixed; 7 | bottom: 0; 8 | left: 0; 9 | display: flex; 10 | align-items: center; 11 | justify-content: center; 12 | z-index: 5; 13 | .fixed_info { 14 | color: white; 15 | margin: 0; 16 | } 17 | } -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_animated.scss: -------------------------------------------------------------------------------- 1 | // Animated Icons 2 | // -------------------------- 3 | 4 | .#{$fa-css-prefix}-spin { 5 | animation: fa-spin 2s infinite linear; 6 | } 7 | 8 | .#{$fa-css-prefix}-pulse { 9 | animation: fa-spin 1s infinite steps(8); 10 | } 11 | 12 | @keyframes fa-spin { 13 | 0% { 14 | transform: rotate(0deg); 15 | } 16 | 17 | 100% { 18 | transform: rotate(360deg); 19 | } 20 | } 21 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_list.scss: -------------------------------------------------------------------------------- 1 | // List Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-ul { 5 | list-style-type: none; 6 | margin-left: $fa-li-width * 5/4; 7 | padding-left: 0; 8 | 9 | > li { position: relative; } 10 | } 11 | 12 | .#{$fa-css-prefix}-li { 13 | left: -$fa-li-width; 14 | position: absolute; 15 | text-align: center; 16 | width: $fa-li-width; 17 | line-height: inherit; 18 | } 19 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_core.scss: -------------------------------------------------------------------------------- 1 | // Base Class Definition 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}, 5 | .fas, 6 | .far, 7 | .fal, 8 | .fad, 9 | .fab { 10 | -moz-osx-font-smoothing: grayscale; 11 | -webkit-font-smoothing: antialiased; 12 | display: inline-block; 13 | font-style: normal; 14 | font-variant: normal; 15 | text-rendering: auto; 16 | line-height: 1; 17 | } 18 | 19 | %fa-icon { 20 | @include fa-icon; 21 | } 22 | -------------------------------------------------------------------------------- /src/image/sprite/logo_lidemy.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /src/image/img_bubble_deco.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /docs/image/img_visual_light.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_larger.scss: -------------------------------------------------------------------------------- 1 | // Icon Sizes 2 | // ------------------------- 3 | 4 | // makes the font 33% larger relative to the icon container 5 | .#{$fa-css-prefix}-lg { 6 | font-size: (4em / 3); 7 | line-height: (3em / 4); 8 | vertical-align: -.0667em; 9 | } 10 | 11 | .#{$fa-css-prefix}-xs { 12 | font-size: .75em; 13 | } 14 | 15 | .#{$fa-css-prefix}-sm { 16 | font-size: .875em; 17 | } 18 | 19 | @for $i from 1 through 10 { 20 | .#{$fa-css-prefix}-#{$i}x { 21 | font-size: $i * 1em; 22 | } 23 | } 24 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/fontawesome.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | @import 'mixins'; 7 | @import 'core'; 8 | @import 'larger'; 9 | @import 'fixed-width'; 10 | @import 'list'; 11 | @import 'bordered-pulled'; 12 | @import 'animated'; 13 | @import 'rotated-flipped'; 14 | @import 'stacked'; 15 | @import 'icons'; 16 | @import 'screen-reader'; 17 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_bordered-pulled.scss: -------------------------------------------------------------------------------- 1 | // Bordered & Pulled 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-border { 5 | border: solid .08em $fa-border-color; 6 | border-radius: .1em; 7 | padding: .2em .25em .15em; 8 | } 9 | 10 | .#{$fa-css-prefix}-pull-left { float: left; } 11 | .#{$fa-css-prefix}-pull-right { float: right; } 12 | 13 | .#{$fa-css-prefix}, 14 | .fas, 15 | .far, 16 | .fal, 17 | .fab { 18 | &.#{$fa-css-prefix}-pull-left { margin-right: .3em; } 19 | &.#{$fa-css-prefix}-pull-right { margin-left: .3em; } 20 | } 21 | -------------------------------------------------------------------------------- /docs/webfonts/fa-solid-900.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Font Awesome 5 Free Solid"; 3 | src: url("fa-solid-900.eot"); /* IE9 */ 4 | src: url("fa-solid-900.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ 5 | url("fa-solid-900.woff") format("woff"), /* chrome, firefox */ 6 | url("fa-solid-900.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url("fa-solid-900.svg#Font Awesome 5 Free Solid") format("svg"); /* iOS 4.1- */ 8 | font-style: normal; 9 | font-weight: normal; 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /docs/webfonts/fa-brands-400.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: "Font Awesome 5 Brands Regular"; 3 | src: url("fa-brands-400.eot"); /* IE9 */ 4 | src: url("fa-brands-400.eot?#iefix") format("embedded-opentype"), /* IE6-IE8 */ 5 | url("fa-brands-400.woff") format("woff"), /* chrome, firefox */ 6 | url("fa-brands-400.ttf") format("truetype"), /* chrome, firefox, opera, Safari, Android, iOS 4.2+ */ 7 | url("fa-brands-400.svg#Font Awesome 5 Brands Regular") format("svg"); /* iOS 4.1- */ 8 | font-style: normal; 9 | font-weight: normal; 10 | } 11 | 12 | 13 | -------------------------------------------------------------------------------- /src/js/throttle.js: -------------------------------------------------------------------------------- 1 | export default function throttle(func, limit) { 2 | let lastFunc 3 | let lastRan 4 | return function() { 5 | const context = this 6 | const args = arguments 7 | if (!lastRan) { 8 | func.apply(context, args) 9 | lastRan = Date.now() 10 | } else { 11 | clearTimeout(lastFunc) 12 | lastFunc = setTimeout(function() { 13 | if ((Date.now() - lastRan) >= limit) { 14 | func.apply(context, args) 15 | lastRan = Date.now() 16 | } 17 | }, limit - (Date.now() - lastRan)) 18 | } 19 | } 20 | } -------------------------------------------------------------------------------- /src/scss/_variables.scss: -------------------------------------------------------------------------------- 1 | // main color 2 | $main-color: #ca4141; 3 | $main-color-dark: #B53939; 4 | $main-bg-Color: #f8f8f8; 5 | $sub-color: #18A0FB; 6 | $logo-color: #eb2629; 7 | $shadow-color: rgba(0, 0, 0, 0.1); 8 | 9 | $color-theme-light: #f5ebeb; 10 | $color-theme-dark: #4F3F43; 11 | 12 | $grey: #666; 13 | $grey-dark: #333; 14 | $grey-light: #999; 15 | 16 | // width 17 | $width-desktop-xl: 1440px; 18 | $width-desktop-l: 1200px; 19 | $width-desktop-m: 1080px; 20 | $width-desktop-s: 900px; 21 | 22 | $width-tablet: 768px; 23 | $width-tablet-s: 640px; 24 | 25 | $width-mobile-l: 480px; 26 | $width-mobile-m: 414px; 27 | $width-mobile-s: 375px; 28 | $width-mobile-xs: 320px; -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_stacked.scss: -------------------------------------------------------------------------------- 1 | // Stacked Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-stack { 5 | display: inline-block; 6 | height: 2em; 7 | line-height: 2em; 8 | position: relative; 9 | vertical-align: middle; 10 | width: ($fa-fw-width*2); 11 | } 12 | 13 | .#{$fa-css-prefix}-stack-1x, 14 | .#{$fa-css-prefix}-stack-2x { 15 | left: 0; 16 | position: absolute; 17 | text-align: center; 18 | width: 100%; 19 | } 20 | 21 | .#{$fa-css-prefix}-stack-1x { 22 | line-height: inherit; 23 | } 24 | 25 | .#{$fa-css-prefix}-stack-2x { 26 | font-size: 2em; 27 | } 28 | 29 | .#{$fa-css-prefix}-inverse { 30 | color: $fa-inverse; 31 | } 32 | -------------------------------------------------------------------------------- /docs/image/red_line_bg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/html/mixin/_mixin.pug: -------------------------------------------------------------------------------- 1 | mixin common_title(title, id, alignType='center') 2 | h3.common__title(class=`${alignType}`) 3 | a(href=`#${id}`)= title 4 | 5 | mixin post_item(title, id, theme) 6 | section.section.post(class=`${id} ${theme ? theme : ''}`) 7 | +common_title(title, id, 'left') 8 | .post__content 9 | block 10 | 11 | mixin cta_block(leftText, leftLink, rightText, rightLink) 12 | section.section.cta.lazy(data-bg="image/img_cta_bg.svg") 13 | h3.cta__title 想要一起來學習程式嗎? 14 | p.cta__content 第五期現正招生中,到三月底截止,強烈建議你先把官網的資訊都看完,全盤了解過後再做決定,有任何問題都可以透過 Lidemy 粉絲專頁與我們聯絡! 15 | .cta__operate 16 | a(href=`${leftLink}`).cta__button.cta__button-apply= leftText 17 | a(href=`${rightLink}`).cta__button.cta__button-mail= rightText -------------------------------------------------------------------------------- /src/image/img_visual_light.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /src/js/bundle/clipboard.js: -------------------------------------------------------------------------------- 1 | import boostrap from 'bootstrap'; 2 | import $ from 'jquery'; 3 | import ClipboardJS from 'clipboard'; 4 | 5 | $('[data-toggle="tooltip"]').tooltip() 6 | 7 | function setTooltip(btn, message) { 8 | $(btn).tooltip('hide') 9 | .attr('data-original-title', message) 10 | .tooltip('show'); 11 | } 12 | 13 | function hideTooltip(btn) { 14 | setTimeout(function () { 15 | $(btn) 16 | .attr('data-original-title', 'Copy me') 17 | .tooltip('hide'); 18 | }, 1000); 19 | } 20 | 21 | const clipboard = new ClipboardJS('.copy__btn'); 22 | 23 | clipboard.on('success', function (e) { 24 | setTooltip(e.trigger, 'Copied!'); 25 | hideTooltip(e.trigger); 26 | }) 27 | 28 | clipboard.on('error', function (e) { 29 | setTooltip(e.trigger, 'Failed!'); 30 | hideTooltip(e.trigger); 31 | }); 32 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Lidemy 程式導師實驗計畫第四期 2 | 3 | 不喊口號也不誇大成效,開放透明的前後端線上學習計畫。 4 | 5 | 用六個月的時間,培養出一個找得到工作且基礎紮實的網頁工程師。 6 | 7 | 課綱:https://github.com/Lidemy/mentor-program-4th 8 | 9 | 10 | ![img](src/image/og-img.png) 11 | 12 | --- 13 | 14 | ## Install 15 | 16 | ``` 17 | $ npm install 18 | ``` 19 | 20 | 21 | ## Usage 22 | 23 | ### ✏️ dev 24 | 25 | ``` 26 | npm run dev 27 | ``` 28 | 29 | ### ✏️ production 30 | 31 | ``` 32 | npm run build 33 | ``` 34 | 35 | ### optimize webfont 36 | 37 | We defined every font-awesome class we used in `minfont.js` and get this unicode from `src/scss/font-awesome/scss/_variables.scss`. After we have unicodes, we can use [gulp-fontmin](https://www.npmjs.com/package/gulp-fontmin-woff2) to reduce the size of font file. 38 | 39 | Be careful if you want to use new icon, you must add the class name to `minfont.js` 40 | -------------------------------------------------------------------------------- /src/html/layout/header.pug: -------------------------------------------------------------------------------- 1 | header.header 2 | .header__content 3 | .header__logo 4 | a.header__logo-img(href="/", aria-label="Home") 5 | i(class="fas fa-bars header__responsive__icon") 6 | nav.header__nav 7 | ul 8 | - 9 | var navs = [ 10 | { name: "首頁", src: "index" }, 11 | { name: "計畫介紹", src: "introduce" }, 12 | { name: "課程大綱", src: "syllabus" }, 13 | { name: "教學成果", src: "achievement" }, 14 | { name: "課程資訊", src: "course-info" }, 15 | { name: "FAQ", src: "faq" } 16 | ]; 17 | each item in navs 18 | li(class= (currentUrl === item.src ? 'current' : '')) 19 | a(href= (item.src === 'index' ? '/' : item.src + '.html'))= item.name 20 | a.header__cta-btn(href="course-info.html") 了解報名資訊 -------------------------------------------------------------------------------- /src/image/red_line_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/scss/_reset.scss: -------------------------------------------------------------------------------- 1 | * { 2 | margin: 0; 3 | padding: 0; 4 | box-sizing: border-box; 5 | letter-spacing: 0.02rem; 6 | font-family: 'Work Sans','Noto Sans TC', '微軟正黑體', Arial, Helvetica, sans-serif; 7 | } 8 | 9 | ul { 10 | list-style: none; 11 | margin: 0; 12 | } 13 | 14 | a, button { 15 | text-decoration: none; 16 | color: inherit; 17 | border: none; 18 | outline: none; 19 | &:hover { 20 | text-decoration: none; 21 | color: $main-color; 22 | } 23 | } 24 | 25 | p { 26 | line-height: 1.8rem; 27 | letter-spacing: 0.04rem; 28 | margin-bottom: 0.5rem; 29 | color: #999; 30 | 31 | strong { 32 | color: #333; 33 | } 34 | 35 | a { 36 | border-bottom: 1px dotted #999; 37 | color: #000; 38 | 39 | &:hover { 40 | color: $main-color; 41 | } 42 | } 43 | } 44 | 45 | code { 46 | font-size: 13px; 47 | color: lighten($main-color, 5%); 48 | } 49 | -------------------------------------------------------------------------------- /src/scss/main.scss: -------------------------------------------------------------------------------- 1 | 2 | @import './_config.scss'; 3 | 4 | @import 'node_modules/bootstrap/scss/bootstrap'; 5 | 6 | @import './sprite/view/_sprite.scss'; 7 | @import './_variables.scss'; 8 | 9 | @import './font-awesome/scss/fontawesome.scss'; 10 | @import './font-awesome/scss/solid.scss'; 11 | @import './font-awesome/scss/brands.scss'; 12 | 13 | @import './_reset.scss'; 14 | @import './_mixin.scss'; 15 | @import './_layout.scss'; 16 | @import './_element.scss'; 17 | 18 | @import '../../node_modules/rfs/scss'; 19 | 20 | @import './layout/_header.scss'; 21 | @import './layout/_footer.scss'; 22 | @import './layout/_cta_block.scss'; 23 | @import './layout/_banner.scss'; 24 | 25 | @import './page/_index.scss'; 26 | @import './page/_faq.scss'; 27 | @import './page/_course-info.scss'; 28 | @import './page/_achievement.scss'; 29 | @import './page/_introduce.scss'; 30 | @import './page/_syllabus.scss'; 31 | 32 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/brands.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | 7 | @font-face { 8 | font-family: 'Font Awesome 5 Brands'; 9 | font-style: normal; 10 | font-weight: 400; 11 | font-display: $fa-font-display; 12 | src: url('#{$fa-font-path}/fa-brands-400.eot'); 13 | src: url('#{$fa-font-path}/fa-brands-400.eot?#iefix') format('embedded-opentype'), 14 | url('#{$fa-font-path}/fa-brands-400.woff2') format('woff2'), 15 | url('#{$fa-font-path}/fa-brands-400.woff') format('woff'), 16 | url('#{$fa-font-path}/fa-brands-400.ttf') format('truetype'), 17 | url('#{$fa-font-path}/fa-brands-400.svg#fontawesome') format('svg'); 18 | } 19 | 20 | .fab { 21 | font-family: 'Font Awesome 5 Brands'; 22 | font-weight: 400; 23 | } 24 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/solid.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | 7 | @font-face { 8 | font-family: 'Font Awesome 5 Free'; 9 | font-style: normal; 10 | font-weight: 900; 11 | font-display: $fa-font-display; 12 | src: url('#{$fa-font-path}/fa-solid-900.eot'); 13 | src: url('#{$fa-font-path}/fa-solid-900.eot?#iefix') format('embedded-opentype'), 14 | url('#{$fa-font-path}/fa-solid-900.woff2') format('woff2'), 15 | url('#{$fa-font-path}/fa-solid-900.woff') format('woff'), 16 | url('#{$fa-font-path}/fa-solid-900.ttf') format('truetype'), 17 | url('#{$fa-font-path}/fa-solid-900.svg#fontawesome') format('svg'); 18 | } 19 | 20 | .fa, 21 | .fas { 22 | font-family: 'Font Awesome 5 Free'; 23 | font-weight: 900; 24 | } 25 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/regular.scss: -------------------------------------------------------------------------------- 1 | /*! 2 | * Font Awesome Free 5.13.0 by @fontawesome - https://fontawesome.com 3 | * License - https://fontawesome.com/license/free (Icons: CC BY 4.0, Fonts: SIL OFL 1.1, Code: MIT License) 4 | */ 5 | @import 'variables'; 6 | 7 | @font-face { 8 | font-family: 'Font Awesome 5 Free'; 9 | font-style: normal; 10 | font-weight: 400; 11 | font-display: $fa-font-display; 12 | src: url('#{$fa-font-path}/fa-regular-400.eot'); 13 | src: url('#{$fa-font-path}/fa-regular-400.eot?#iefix') format('embedded-opentype'), 14 | url('#{$fa-font-path}/fa-regular-400.woff2') format('woff2'), 15 | url('#{$fa-font-path}/fa-regular-400.woff') format('woff'), 16 | url('#{$fa-font-path}/fa-regular-400.ttf') format('truetype'), 17 | url('#{$fa-font-path}/fa-regular-400.svg#fontawesome') format('svg'); 18 | } 19 | 20 | .far { 21 | font-family: 'Font Awesome 5 Free'; 22 | font-weight: 400; 23 | } 24 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_rotated-flipped.scss: -------------------------------------------------------------------------------- 1 | // Rotated & Flipped Icons 2 | // ------------------------- 3 | 4 | .#{$fa-css-prefix}-rotate-90 { @include fa-icon-rotate(90deg, 1); } 5 | .#{$fa-css-prefix}-rotate-180 { @include fa-icon-rotate(180deg, 2); } 6 | .#{$fa-css-prefix}-rotate-270 { @include fa-icon-rotate(270deg, 3); } 7 | 8 | .#{$fa-css-prefix}-flip-horizontal { @include fa-icon-flip(-1, 1, 0); } 9 | .#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(1, -1, 2); } 10 | .#{$fa-css-prefix}-flip-both, .#{$fa-css-prefix}-flip-horizontal.#{$fa-css-prefix}-flip-vertical { @include fa-icon-flip(-1, -1, 2); } 11 | 12 | // Hook for IE8-9 13 | // ------------------------- 14 | 15 | :root { 16 | .#{$fa-css-prefix}-rotate-90, 17 | .#{$fa-css-prefix}-rotate-180, 18 | .#{$fa-css-prefix}-rotate-270, 19 | .#{$fa-css-prefix}-flip-horizontal, 20 | .#{$fa-css-prefix}-flip-vertical, 21 | .#{$fa-css-prefix}-flip-both { 22 | filter: none; 23 | } 24 | } 25 | -------------------------------------------------------------------------------- /src/scss/layout/_cta_block.scss: -------------------------------------------------------------------------------- 1 | .cta { 2 | max-width: $width-desktop-s; 3 | text-align: center; 4 | padding: 70px 20px; 5 | 6 | background-position: 0 165px; 7 | background-repeat: no-repeat; 8 | background-size: 230px auto; 9 | 10 | &__title { 11 | @include font-size(26px); 12 | margin-bottom: 1rem; 13 | } 14 | 15 | &__content { 16 | @include font-size(14px); 17 | max-width: 500px; 18 | margin: 0 auto 1rem; 19 | } 20 | } 21 | 22 | @include mq('tablet') { 23 | .cta { 24 | padding-bottom: 130px; 25 | background-position: center 250px; 26 | } 27 | } 28 | @include mq('mobile-s') { 29 | .cta { 30 | padding-bottom: 150px; 31 | background-position: center 350px; 32 | 33 | &__button { 34 | width: 100%; 35 | margin-bottom: 0.5rem; 36 | } 37 | } 38 | } 39 | 40 | .cta__button { 41 | @include button_1($withIcon: true); 42 | color: white; 43 | &:not(:nth-last-of-type(1)) { 44 | margin-right: 10px; 45 | } 46 | 47 | &-mail { 48 | background: darken($grey, 15); 49 | &:hover { 50 | background: darken($grey, 25); 51 | } 52 | } 53 | } -------------------------------------------------------------------------------- /src/js/layout.js: -------------------------------------------------------------------------------- 1 | import throttle from './throttle'; 2 | import smoothscroll from 'smoothscroll-polyfill'; 3 | import LazyLoad from "vanilla-lazyload"; 4 | 5 | // Support safari scroll behavior 6 | smoothscroll.polyfill(); 7 | 8 | function scrollToOffset(e, offset) { 9 | e.preventDefault(); 10 | 11 | if ('top' === offset) { 12 | offset = 0; 13 | } else if (!offset) { 14 | const url = location.hash.substr(1); 15 | if (!url) return 16 | 17 | offset = document.querySelector(`.${url}`).offsetTop - 120; 18 | } 19 | 20 | window.scrollTo({ 21 | top: offset, 22 | left: 0, 23 | behavior: 'smooth' 24 | }); 25 | } 26 | 27 | const btnScroll = document.querySelector(".scroll-top-btn"); 28 | 29 | // Add scroll throttle 30 | window.addEventListener('scroll', throttle(function() { 31 | if (window.pageYOffset > 900) { 32 | btnScroll.classList.remove("content-invisible") 33 | } else { 34 | btnScroll.classList.add("content-invisible") 35 | } 36 | }, 500)) 37 | 38 | // Add event listener 39 | window.addEventListener('DOMContentLoaded', scrollToOffset); 40 | window.addEventListener('hashchange', scrollToOffset); 41 | btnScroll.addEventListener('click', function(e) { scrollToOffset(e, 'top') }) 42 | 43 | 44 | var ll = new LazyLoad({ 45 | elements_selector: ".lazy" 46 | }); -------------------------------------------------------------------------------- /docs/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | https://bootcamp.lidemy.com/index.html 12 | 2020-04-29T04:30:42+00:00 13 | 1.00 14 | 15 | 16 | https://bootcamp.lidemy.com/introduce.html 17 | 2020-04-29T04:30:42+00:00 18 | 0.80 19 | 20 | 21 | https://bootcamp.lidemy.com/syllabus.html 22 | 2020-04-29T04:30:42+00:00 23 | 0.80 24 | 25 | 26 | https://bootcamp.lidemy.com/achievement.html 27 | 2020-04-29T04:30:42+00:00 28 | 0.80 29 | 30 | 31 | https://bootcamp.lidemy.com/course-info.html 32 | 2020-04-29T04:30:42+00:00 33 | 0.80 34 | 35 | 36 | https://bootcamp.lidemy.com/faq.html 37 | 2020-04-29T04:30:42+00:00 38 | 0.80 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/statics/sitemap.xml: -------------------------------------------------------------------------------- 1 | 2 | 7 | 8 | 9 | 10 | 11 | https://bootcamp.lidemy.com/index.html 12 | 2020-04-29T04:30:42+00:00 13 | 1.00 14 | 15 | 16 | https://bootcamp.lidemy.com/introduce.html 17 | 2020-04-29T04:30:42+00:00 18 | 0.80 19 | 20 | 21 | https://bootcamp.lidemy.com/syllabus.html 22 | 2020-04-29T04:30:42+00:00 23 | 0.80 24 | 25 | 26 | https://bootcamp.lidemy.com/achievement.html 27 | 2020-04-29T04:30:42+00:00 28 | 0.80 29 | 30 | 31 | https://bootcamp.lidemy.com/course-info.html 32 | 2020-04-29T04:30:42+00:00 33 | 0.80 34 | 35 | 36 | https://bootcamp.lidemy.com/faq.html 37 | 2020-04-29T04:30:42+00:00 38 | 0.80 39 | 40 | 41 | 42 | -------------------------------------------------------------------------------- /src/image/sprite/icon_arrow_right.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /src/scss/font-awesome/scss/_mixins.scss: -------------------------------------------------------------------------------- 1 | // Mixins 2 | // -------------------------- 3 | 4 | @mixin fa-icon { 5 | -webkit-font-smoothing: antialiased; 6 | -moz-osx-font-smoothing: grayscale; 7 | display: inline-block; 8 | font-style: normal; 9 | font-variant: normal; 10 | font-weight: normal; 11 | line-height: 1; 12 | } 13 | 14 | @mixin fa-icon-rotate($degrees, $rotation) { 15 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation})"; 16 | transform: rotate($degrees); 17 | } 18 | 19 | @mixin fa-icon-flip($horiz, $vert, $rotation) { 20 | -ms-filter: "progid:DXImageTransform.Microsoft.BasicImage(rotation=#{$rotation}, mirror=1)"; 21 | transform: scale($horiz, $vert); 22 | } 23 | 24 | 25 | // Only display content to screen readers. A la Bootstrap 4. 26 | // 27 | // See: http://a11yproject.com/posts/how-to-hide-content/ 28 | 29 | @mixin sr-only { 30 | border: 0; 31 | clip: rect(0, 0, 0, 0); 32 | height: 1px; 33 | margin: -1px; 34 | overflow: hidden; 35 | padding: 0; 36 | position: absolute; 37 | width: 1px; 38 | } 39 | 40 | // Use in conjunction with .sr-only to only display content when it's focused. 41 | // 42 | // Useful for "Skip to main content" links; see http://www.w3.org/TR/2013/NOTE-WCAG20-TECHS-20130905/G1 43 | // 44 | // Credit: HTML5 Boilerplate 45 | 46 | @mixin sr-only-focusable { 47 | &:active, 48 | &:focus { 49 | clip: auto; 50 | height: auto; 51 | margin: 0; 52 | overflow: visible; 53 | position: static; 54 | width: auto; 55 | } 56 | } 57 | -------------------------------------------------------------------------------- /src/image/sprite/icon_arrow_right_blue.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/image/sprite/icon_arrow_right_red.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /src/js/header.js: -------------------------------------------------------------------------------- 1 | import throttle from './throttle' 2 | 3 | let timer; 4 | let header = document.querySelector('.header') 5 | let headerContent = document.querySelectorAll( 6 | '.header__cta-btn, .header__nav' 7 | ) 8 | 9 | function setShrinkHeader() { 10 | clearTimeout(timer) 11 | 12 | if (window.pageYOffset > 120) { 13 | header.classList.add('is-shrunk') 14 | headerContent.forEach((content) => { 15 | content.classList.add('content-invisible') 16 | }) 17 | } else { 18 | header.classList.remove('is-shrunk') 19 | timer = setTimeout(function () { 20 | headerContent.forEach((content) => { 21 | content.classList.remove('content-invisible') 22 | }) 23 | }, 50) 24 | } 25 | } 26 | 27 | function openMenu() { 28 | // mobile menu open 29 | header.classList.toggle('menu-opened') 30 | 31 | // desktop nav shrink 32 | header.classList.toggle('is-shrunk') 33 | const isheaderShrunk = header.classList.contains('is-shrunk') 34 | 35 | if (isheaderShrunk) { 36 | headerContent.forEach((content) => { 37 | content.classList.add('content-invisible') 38 | }) 39 | } else { 40 | setTimeout(function () { 41 | headerContent.forEach((content) => { 42 | content.classList.remove('content-invisible') 43 | }) 44 | }, 50) 45 | } 46 | } 47 | 48 | document.addEventListener('scroll', throttle(setShrinkHeader, 200)) 49 | document.querySelector(".header__responsive__icon").addEventListener('click', openMenu) 50 | window.addEventListener('pageshow', function(e) { 51 | if (e.persisted) { 52 | header.classList.remove('menu-opened') 53 | } 54 | }) 55 | -------------------------------------------------------------------------------- /minfont.js: -------------------------------------------------------------------------------- 1 | // grep -Ri "fa-*" ./src/scss 2 | const fs = require('fs') 3 | const fas = ` 4 | fa-volume-up 5 | fa-thumbs-up 6 | fa-globe-americas 7 | fa-database 8 | fa-tools 9 | fa-server 10 | fa-chart-line 11 | fa-shield-alt 12 | fa-code-branch 13 | fa-chalkboard-teacher 14 | fa-eye 15 | fa-bars 16 | fa-external-link-alt 17 | fa-chevron-up 18 | fa-check 19 | fa-user-circle 20 | fa-arrow-right 21 | fa-arrow-down 22 | fa-arrow-up 23 | fa-calendar-alt 24 | fa-stream 25 | fa-check-square 26 | fa-arrow-alt-circle-right 27 | fa-copy 28 | fa-long-arrow-alt-right 29 | `.split('\n').filter(n => n) 30 | 31 | const fab = ` 32 | fa-github 33 | fa-facebook-square 34 | fa-medium 35 | fa-react 36 | fa-js 37 | fa-html5 38 | fa-css3-alt 39 | fa-chrome 40 | fa-php 41 | `.split('\n').filter(n => n) 42 | 43 | const cssContent = fs.readFileSync('./src/scss/font-awesome/scss/_variables.scss', 'utf8') 44 | function getUnicode(classNames) { 45 | let unicodes = [] 46 | let names = classNames.map(name => { 47 | return name.replace('fa-', 'fa-var-') 48 | }) 49 | for(let name of names) { 50 | let result = cssContent.match(new RegExp(`${name}: (.*);`)) 51 | if (result && result[1]) { 52 | console.log(name, result[1]) 53 | unicodes.push(result[1].replace('\\', '\\u')) 54 | } else { 55 | throw new Error('Not found: ' + name) 56 | } 57 | } 58 | return unicodes 59 | } 60 | 61 | let fasCodes = getUnicode(fas) 62 | let fabCodes = getUnicode(fab) 63 | 64 | console.log('fas:') 65 | console.log(fasCodes.join('')) 66 | console.log('fab:') 67 | console.log(fabCodes.join('')) 68 | console.log('all:(copy this string to gulpfile.js)') 69 | console.log(fasCodes.join('') + fabCodes.join('')) 70 | -------------------------------------------------------------------------------- /docs/image/index_portrait_1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/humans.txt: -------------------------------------------------------------------------------- 1 | ___ ___ ___ ___ ___ 2 | /\__\ ___ /\ \ /\ \ /\__\ |\__\ 3 | /:/ / /\ \ /::\ \ /::\ \ /::| | |:| | 4 | /:/ / \:\ \ /:/\:\ \ /:/\:\ \ /:|:| | |:| | 5 | /:/ / /::\__\ /:/ \:\__\ /::\~\:\ \ /:/|:|__|__ |:|__|__ 6 | /:/__/ __/:/\/__/ /:/__/ \:|__| /:/\:\ \:\__\ /:/ |::::\__\ /::::\__\ 7 | \:\ \ /\/:/ / \:\ \ /:/ / \:\~\:\ \/__/ \/__/~~/:/ / /:/~~/~ 8 | \:\ \ \::/__/ \:\ /:/ / \:\ \:\__\ /:/ / /:/ / 9 | \:\ \ \:\__\ \:\/:/ / \:\ \/__/ /:/ / \/__/ 10 | \:\__\ \/__/ \::/__/ \:\__\ /:/ / 11 | \/__/ ~~ \/__/ \/__/ 12 | 13 | ASCII generated by http://www.network-science.de/ascii/ 14 | 15 | 恭喜你找到這邊來 (* ̄▽ ̄)/‧★*"`'*-.,_,.-*'`"*-.,_☆ 16 | 底下是這個網站背後的團隊以及使用的技術 17 | 如果有任何問題,請聯絡 huli@lidemy.com 18 | 感謝 <(_ _)> 19 | 20 | ─────────────────────────────────────────────────────────────────────── 21 | 22 | /* TEAM */ 23 | Yakim (Designer, Developer) 24 | GitHub: https://github.com/yakim-shu 25 | Site: https://yakimhsu.com/ 26 | 27 | Chih Yang (Developer) 28 | GitHub: https://github.com/ChihYang41 29 | Site: https://chihyang41.github.io/ 30 | 31 | Minw (Support) 32 | GitHub: https://github.com/ishin4554 33 | Site: https://medium.com/@minw 34 | 35 | Huli (Support) 36 | GitHub: https://github.com/aszx87410 37 | Site: https://blog.huli.tw 38 | 39 | /* SITE */ 40 | Technology: pug, scss, gulp, babel, browserify 41 | Image: font-awesome, Getillustrations 42 | Source code: https://github.com/Lidemy/mtr-4th-web -------------------------------------------------------------------------------- /src/statics/humans.txt: -------------------------------------------------------------------------------- 1 | ___ ___ ___ ___ ___ 2 | /\__\ ___ /\ \ /\ \ /\__\ |\__\ 3 | /:/ / /\ \ /::\ \ /::\ \ /::| | |:| | 4 | /:/ / \:\ \ /:/\:\ \ /:/\:\ \ /:|:| | |:| | 5 | /:/ / /::\__\ /:/ \:\__\ /::\~\:\ \ /:/|:|__|__ |:|__|__ 6 | /:/__/ __/:/\/__/ /:/__/ \:|__| /:/\:\ \:\__\ /:/ |::::\__\ /::::\__\ 7 | \:\ \ /\/:/ / \:\ \ /:/ / \:\~\:\ \/__/ \/__/~~/:/ / /:/~~/~ 8 | \:\ \ \::/__/ \:\ /:/ / \:\ \:\__\ /:/ / /:/ / 9 | \:\ \ \:\__\ \:\/:/ / \:\ \/__/ /:/ / \/__/ 10 | \:\__\ \/__/ \::/__/ \:\__\ /:/ / 11 | \/__/ ~~ \/__/ \/__/ 12 | 13 | ASCII generated by http://www.network-science.de/ascii/ 14 | 15 | 恭喜你找到這邊來 (* ̄▽ ̄)/‧★*"`'*-.,_,.-*'`"*-.,_☆ 16 | 底下是這個網站背後的團隊以及使用的技術 17 | 如果有任何問題,請聯絡 huli@lidemy.com 18 | 感謝 <(_ _)> 19 | 20 | ─────────────────────────────────────────────────────────────────────── 21 | 22 | /* TEAM */ 23 | Yakim (Designer, Developer) 24 | GitHub: https://github.com/yakim-shu 25 | Site: https://yakimhsu.com/ 26 | 27 | Chih Yang (Developer) 28 | GitHub: https://github.com/ChihYang41 29 | Site: https://chihyang41.github.io/ 30 | 31 | Minw (Support) 32 | GitHub: https://github.com/ishin4554 33 | Site: https://medium.com/@minw 34 | 35 | Huli (Support) 36 | GitHub: https://github.com/aszx87410 37 | Site: https://blog.huli.tw 38 | 39 | /* SITE */ 40 | Technology: pug, scss, gulp, babel, browserify 41 | Image: font-awesome, Getillustrations 42 | Source code: https://github.com/Lidemy/mtr-4th-web -------------------------------------------------------------------------------- /src/js/bundle/chart.js: -------------------------------------------------------------------------------- 1 | import Chart from 'chart.js'; 2 | 3 | // options 4 | const options = { 5 | maintainAspectRatio: false, 6 | devicePixelRatio: 2, 7 | radius: 10, 8 | layout: { 9 | padding: { 10 | top: 20, 11 | } 12 | }, 13 | legend: { 14 | align: 'center', 15 | position: 'top', 16 | fullWidth: false, 17 | labels: { 18 | fontColor: '#666', 19 | fontSize: 12, 20 | } 21 | }, 22 | } 23 | 24 | // data 25 | const data = { 26 | labels: ['第四期','第三期', '第二期', '第一期'], 27 | scaleLabel: { 28 | labelString: '###' 29 | }, 30 | datasets: [ 31 | { 32 | label: '時限內求職成功人數', 33 | backgroundColor: '#D26B6B', 34 | hoverBackgroundColor: '#C25A5A', 35 | borderColor: '#FFD9D9', 36 | data: [21, 14, 8, 2], 37 | barThickness: 'flex', 38 | maxBarThickness: 30, 39 | 40 | }, 41 | { 42 | label: '結業人數', 43 | backgroundColor: '#FC849A', 44 | hoverBackgroundColor: '#F28397', 45 | borderColor: '#E27474', 46 | data: [60, 39, 29, 3], 47 | barThickness: 'flex', 48 | maxBarThickness: 30, 49 | }, 50 | { 51 | label: '學生總人數', 52 | backgroundColor: '#FFD2D2', 53 | hoverBackgroundColor: '#F6CCCC', 54 | borderColor: '#E27474', 55 | data: [77, 56, 38, 12], 56 | barThickness: 'flex', 57 | maxBarThickness: 30, 58 | }, 59 | ] 60 | } 61 | 62 | const ctx = document.getElementById('chart').getContext('2d'); 63 | const chart = new Chart(ctx, { 64 | type: 'horizontalBar', data, options, 65 | }); 66 | 67 | let isTablet = false; 68 | const updateChartLayout = () => { 69 | if (window.innerWidth < 480) { 70 | if (isTablet) return 71 | 72 | chart.options.legend.align = 'start' 73 | chart.update() 74 | isTablet = true 75 | 76 | } else if (isTablet) { 77 | 78 | chart.options.legend.align = 'center' 79 | chart.update() 80 | isTablet = false 81 | } 82 | } 83 | 84 | // binding events 85 | ['resize', 'DOMContentLoaded'].forEach(function (item) { 86 | window.addEventListener(item, updateChartLayout); 87 | }); 88 | 89 | -------------------------------------------------------------------------------- /docs/image/img_features.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/html/layout/layout.pug: -------------------------------------------------------------------------------- 1 | - 2 | var meta = { 3 | url: 'https://bootcamp.lidemy.com', 4 | title: 'Lidemy 程式導師實驗計畫第五期', 5 | type: 'website', 6 | desc: '不喊口號也不誇大成效,開放透明的前後端線上學習計畫。 試著用六個月的時間,培養出一個找得到工作且基礎紮實的網頁工程師。', 7 | img_src: '/image/og-img.png?v=2', 8 | twitter_card: 'summary_large_image' 9 | } 10 | 11 | mixin head_block(headInfo) 12 | head 13 | meta(charset="UTF-8") 14 | meta(name="viewport" content="width=device-width, initial-scale=1.0") 15 | meta(name="Description" content= meta.desc) 16 | meta(http-equiv="X-UA-Compatible" content="IE=edge") 17 | 18 | meta(property="og:title" content= meta.title) 19 | meta(property="og:description" content= meta.desc) 20 | meta(property="og:image" content= meta.url + meta.img_src) 21 | meta(property="og:type" content= meta.type) 22 | meta(property="og:url" content= meta.url) 23 | meta(property="og:site_name" content= meta.title) 24 | meta(property="og:image:width" content="1200") 25 | meta(property="og:image:height" content="628") 26 | 27 | meta(name="twitter:card" content= meta.twitter_card) 28 | meta(name="twitter:title" content= meta.title) 29 | meta(name="twitter:description" content= meta.desc) 30 | meta(name="twitter:image" content= meta.url + meta.img_src) 31 | 32 | link(rel="author" type="text/plain" href="/humans.txt" ) 33 | link(rel='stylesheet' href='css/main.min.css') 34 | link(rel="icon" type="image/png" sizes="96x96" href="./image/favicon-96x96.png") 35 | title #{headInfo.title} | Lidemy 程式導師實驗計畫第五期 36 | 37 | include ga.pug 38 | +ga('UA-77560722-2') 39 | 40 | 41 | 42 | // layout 43 | doctype html 44 | block current 45 | - var currentUrl 46 | 47 | html(lang='en') 48 | block head 49 | +head_block('default') 50 | 51 | body(class= (currentUrl === 'index' && 'theme-index')) 52 | block header 53 | include header.pug 54 | .wrapper 55 | block content 56 | button.scroll-top-btn.content-invisible(aria-label="scrollToTop") 57 | block footer 58 | include footer.pug 59 | block banner 60 | include banner.pug 61 | 62 | script(defer src="js/index.bundle.js") 63 | link(rel="stylesheet" href="https://fonts.googleapis.com/css2?family=Work+Sans&display=swap") 64 | 65 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "mtr-4th-web", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "gulpfile.js", 6 | "dependencies": { 7 | "@babel/runtime": "^7.9.2", 8 | "@popperjs/core": "^2.3.3", 9 | "autoprefixer": "^9.7.6", 10 | "babel": "^6.23.0", 11 | "bootstrap": "^4.4.1", 12 | "chart.js": "^2.9.3", 13 | "clipboard": "^2.0.6", 14 | "gulp": "^4.0.2", 15 | "gulp-concat": "^2.6.1", 16 | "gulp-csso": "^4.0.1", 17 | "gulp-fontmin-woff2": "^0.7.6", 18 | "gulp-imagemin": "^7.1.0", 19 | "gulp-postcss": "^8.0.0", 20 | "gulp-pug": "^4.0.1", 21 | "gulp-rename": "^2.0.0", 22 | "gulp-sass": "^4.0.2", 23 | "gulp-sourcemaps": "^2.6.5", 24 | "gulp-uglify": "^3.0.2", 25 | "postcss-uncss": "^0.17.0", 26 | "rellax": "^1.12.1", 27 | "smoothscroll-polyfill": "^0.4.4", 28 | "uncss": "^0.17.3", 29 | "vanilla-lazyload": "^15.1.1", 30 | "vinyl-buffer": "^1.0.1" 31 | }, 32 | "devDependencies": { 33 | "@babel/core": "^7.9.0", 34 | "@babel/plugin-transform-runtime": "^7.9.0", 35 | "@babel/preset-env": "^7.9.5", 36 | "babel-core": "^6.26.3", 37 | "babel-preset-env": "^1.7.0", 38 | "babelify": "^10.0.0", 39 | "browserify": "^16.5.1", 40 | "del": "^5.1.0", 41 | "event-stream": "^4.0.1", 42 | "font-awesome": "^4.7.0", 43 | "glob": "^7.1.6", 44 | "gulp-babel": "^8.0.0", 45 | "gulp-connect": "^5.7.0", 46 | "gulp-if": "^3.0.0", 47 | "gulp-svg-sprite": "^1.5.0", 48 | "jquery": "^3.5.0", 49 | "merge-stream": "^2.0.0", 50 | "popper.js": "^1.16.1", 51 | "rfs": "^9.0.3", 52 | "vinyl-source-stream": "^2.0.0" 53 | }, 54 | "scripts": { 55 | "test": "echo \"Error: no test specified\" && exit 1", 56 | "gulp": "NODE_ENV='development' gulp", 57 | "gulp-build": "NODE_ENV='production' gulp", 58 | "dev": "npm run gulp", 59 | "start": "npm run gulp", 60 | "build": "npm run gulp-build" 61 | }, 62 | "repository": { 63 | "type": "git", 64 | "url": "git+https://github.com/yakim-shu/MTR-4rd-web.git" 65 | }, 66 | "author": "", 67 | "license": "ISC", 68 | "bugs": { 69 | "url": "https://github.com/yakim-shu/MTR-4rd-web/issues" 70 | }, 71 | "homepage": "https://github.com/yakim-shu/MTR-4rd-web#readme" 72 | } 73 | -------------------------------------------------------------------------------- /docs/image/img_project_2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/image/img_cta_bg.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/image/index_portrait_2.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scss/_mixin.scss: -------------------------------------------------------------------------------- 1 | /* ------- media query ------- */ 2 | $breakpoints: ( 3 | 'mobile-s': $width-mobile-s, 4 | 'mobile-m': $width-mobile-m, 5 | 'mobile-l': $width-mobile-l, 6 | 'tablet': $width-tablet, 7 | 'tablet-s': $width-tablet-s, 8 | 'desktop-s': $width-desktop-s, 9 | 'desktop-m': $width-desktop-m, 10 | 'desktop-l': $width-desktop-l, 11 | 'desktop-xl': $width-desktop-xl 12 | ); 13 | 14 | @mixin mq($width) { 15 | @if map_has_key($breakpoints, $width) { 16 | $width: map_get($breakpoints, $width); 17 | 18 | @media screen and (max-width: $width) { 19 | @content; 20 | } 21 | } 22 | } 23 | 24 | /* ------- mixins ------- */ 25 | 26 | /* size */ 27 | @mixin size($width, $height: $width) { 28 | width: $width; 29 | height: $height; 30 | } 31 | 32 | /* pseudo */ 33 | @mixin pseudo($display: block, $content: '') { 34 | content: $content; 35 | display: $display; 36 | } 37 | 38 | @mixin arrow-icon-pseudo($width: 45px, $height: 20px) { 39 | @extend .svg-icon_arrow_right; 40 | @include pseudo(inline-block); 41 | @include relative($top: 7px, $left: 15px); 42 | width: $width; 43 | height: $height; 44 | } 45 | 46 | /* position */ 47 | @mixin position( 48 | $position, 49 | $top: null, 50 | $right: null, 51 | $bottom: null, 52 | $left: null 53 | ) { 54 | position: $position; 55 | top: $top; 56 | right: $right; 57 | bottom: $bottom; 58 | left: $left; 59 | } 60 | 61 | @mixin absolute($args...) { 62 | @include position(absolute, $args...); 63 | } 64 | 65 | @mixin relative($args...) { 66 | @include position(relative, $args...); 67 | } 68 | 69 | @mixin fixed($args...) { 70 | @include position(fixed, $args...); 71 | } 72 | 73 | /* border-radius */ 74 | @mixin border-radius($pixel...) { 75 | border-radius: $pixel; 76 | } 77 | 78 | /* ------- extends ------- */ 79 | %transition { 80 | transition: all 0.3s; 81 | } 82 | 83 | %reset { 84 | margin: 0; 85 | padding: 0; 86 | } 87 | 88 | %responsive-img { 89 | overflow: hidden; 90 | 91 | img { 92 | max-width: 100%; 93 | height: auto; 94 | } 95 | } 96 | 97 | %weight-font-style { 98 | font-family: 'Palanquin Dark', sans-serif; 99 | letter-spacing: 0.15rem; 100 | font-weight: bold; 101 | } 102 | 103 | %fontawesome-icon { 104 | @extend %fa-icon; 105 | @extend .fas; 106 | display: inline-block; 107 | text-rendering: auto; 108 | } 109 | 110 | %custom-border-bottom { 111 | content: ''; 112 | display: block; 113 | background: #ebd8d8; 114 | width: 100%; 115 | height: 9px; 116 | position: absolute; 117 | left: 0; 118 | bottom: -1px; 119 | z-index: -1; 120 | } -------------------------------------------------------------------------------- /src/image/index_portrait_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | -------------------------------------------------------------------------------- /docs/image/img_project_1.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /docs/image/theme_light_character.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/scss/_layout.scss: -------------------------------------------------------------------------------- 1 | body { 2 | background-color: $main-bg-Color; 3 | padding-bottom: 40px; 4 | } 5 | 6 | body.theme-index { 7 | background-color: white; 8 | background-image: url(./../image/grey_bg.svg), url(./../image/red_line_bg.svg); 9 | background-position: right -60vw top 400px,left -25vw top -300px; 10 | background-repeat: no-repeat; 11 | 12 | @include mq('desktop-m') { 13 | background-position: right -35vw top 43vw,left -40vw top -360px; 14 | background-size: 90%; 15 | } 16 | @include mq('tablet') { 17 | background-position: right -35vw top 55vw; 18 | background-image: url(./../image/grey_bg.svg); 19 | } 20 | @include mq('mobile-l') { 21 | background-position: right -35vw top 65vw; 22 | } 23 | } 24 | 25 | .wrapper { 26 | padding: 160px 0 0; 27 | 28 | @include mq('mobile-l') { 29 | padding-top: 110px; 30 | } 31 | } 32 | 33 | .scroll-top-btn { 34 | @extend %transition; 35 | @include fixed($bottom: 20px, $right: calc((100vw - 1200px) / 2)); 36 | @include size(50px); 37 | background-color: lighten($main-color, 8); 38 | border-radius: 50%; 39 | box-shadow: 0 5px 5px rgba(0,0,0, .2); 40 | z-index: 10; 41 | 42 | &:focus { 43 | outline: none; 44 | }; 45 | 46 | &:after { 47 | @extend %fontawesome-icon; 48 | @include font-size(15px); 49 | @include pseudo(inline-block); 50 | content: fa-content($fa-var-arrow-up); 51 | color: white; 52 | } 53 | 54 | @include mq('desktop-l') { 55 | right: 20px; 56 | } 57 | } 58 | 59 | /* uncss:ignore start */ 60 | .scroll-top-btn.content-invisible { 61 | visibility: hidden; 62 | opacity: 0; 63 | } 64 | /* uncss:ignore end */ 65 | 66 | 67 | .theme-index { 68 | .wrapper { 69 | background: url(./../image/img_visual_light.svg) center top no-repeat; 70 | background-position-y: 100px; 71 | padding-top: 220px; 72 | 73 | @include mq('mobile-l') { 74 | background-position-y: 75px; 75 | background-size: 20% auto; 76 | padding-top: 150px; 77 | } 78 | } 79 | 80 | .full-bg { 81 | background-color: white; 82 | background-image: url(./../image/bg_dot.svg), url(./../image/grey_bg.svg), url(./../image/theme_light_red_bg.svg); 83 | background-repeat: repeat, no-repeat, no-repeat; 84 | background-position: center,left 50vw top 150px,left -45vw bottom -50px; 85 | padding: 0; 86 | 87 | @include mq('desktop-l') { 88 | background-image: url(./../image/bg_dot.svg), url(./../image/grey_bg.svg); 89 | background-position: center,left 30vw top 400px; 90 | background-repeat: repeat, no-repeat; 91 | } 92 | } 93 | } 94 | 95 | .section { 96 | padding: 0 20px; 97 | margin: 0 auto; 98 | } 99 | 100 | .full-bg { 101 | background: $color-theme-light; 102 | padding: 4rem 20px; 103 | 104 | &.theme-dark { 105 | background: $main-color; 106 | } 107 | 108 | @include mq('mobile-l') { 109 | padding: 2rem 15px; 110 | } 111 | } 112 | 113 | -------------------------------------------------------------------------------- /src/scss/sprite/view/_sprite.scss: -------------------------------------------------------------------------------- 1 | %svg-common { 2 | background: url("sprite.svg") no-repeat; 3 | } 4 | 5 | .svg-icon_arrow_right { 6 | @extend %svg-common; 7 | background-position: 0 0; 8 | } 9 | 10 | .svg-icon_arrow_right-dims { 11 | width: 17px; 12 | height: 18px; 13 | } 14 | 15 | .svg-icon_arrow_right_blue { 16 | @extend %svg-common; 17 | background-position: 0 1.2491325468424705%; 18 | } 19 | 20 | .svg-icon_arrow_right_blue-dims { 21 | width: 48px; 22 | height: 23px; 23 | } 24 | 25 | .svg-icon_arrow_right_red { 26 | @extend %svg-common; 27 | background-position: 0 2.8452463566967383%; 28 | } 29 | 30 | .svg-icon_arrow_right_red-dims { 31 | width: 48px; 32 | height: 23px; 33 | } 34 | 35 | .svg-icon_avatar_1 { 36 | @extend %svg-common; 37 | background-position: 0 4.647785039941903%; 38 | } 39 | 40 | .svg-icon_avatar_1-dims { 41 | width: 93px; 42 | height: 87px; 43 | } 44 | 45 | .svg-icon_avatar_2 { 46 | @extend %svg-common; 47 | background-position: 0 10.965867828612927%; 48 | } 49 | 50 | .svg-icon_avatar_2-dims { 51 | width: 87px; 52 | height: 87px; 53 | } 54 | 55 | .svg-icon_avatar_3 { 56 | @extend %svg-common; 57 | background-position: 0 17.423133235724745%; 58 | } 59 | 60 | .svg-icon_avatar_3-dims { 61 | width: 87px; 62 | height: 98px; 63 | } 64 | 65 | .svg-icon_avatar_4 { 66 | @extend %svg-common; 67 | background-position: 0 24.40087145969499%; 68 | } 69 | 70 | .svg-icon_avatar_4-dims { 71 | width: 87px; 72 | height: 87px; 73 | } 74 | 75 | .svg-icon_methods_1 { 76 | @extend %svg-common; 77 | background-position: 0 32.216298552932216%; 78 | } 79 | 80 | .svg-icon_methods_1-dims { 81 | width: 164px; 82 | height: 151px; 83 | } 84 | 85 | .svg-icon_methods_2 { 86 | @extend %svg-common; 87 | background-position: 0 43.6834094368341%; 88 | } 89 | 90 | .svg-icon_methods_2-dims { 91 | width: 164px; 92 | height: 150px; 93 | } 94 | 95 | .svg-icon_methods_3 { 96 | @extend %svg-common; 97 | background-position: 0 55.09893455098935%; 98 | } 99 | 100 | .svg-icon_methods_3-dims { 101 | width: 165px; 102 | height: 150px; 103 | } 104 | 105 | .svg-icon_methods_4 { 106 | @extend %svg-common; 107 | background-position: 0 66.5144596651446%; 108 | } 109 | 110 | .svg-icon_methods_4-dims { 111 | width: 164px; 112 | height: 150px; 113 | } 114 | 115 | .svg-img_about_teacher { 116 | @extend %svg-common; 117 | background-position: 0 77.59633236085325%; 118 | } 119 | 120 | .svg-img_about_teacher-dims { 121 | width: 304px; 122 | height: 144.35px; 123 | } 124 | 125 | .svg-img_about_teacher_left { 126 | @extend %svg-common; 127 | background-position: 0 92.19242902208202%; 128 | } 129 | 130 | .svg-img_about_teacher_left-dims { 131 | width: 91px; 132 | height: 196px; 133 | } 134 | 135 | .svg-logo_lidemy { 136 | @extend %svg-common; 137 | background-position: 0 96.94602272727273%; 138 | } 139 | 140 | .svg-logo_lidemy-dims { 141 | width: 56px; 142 | height: 56px; 143 | } 144 | 145 | .svg-logo_mtr { 146 | @extend %svg-common; 147 | background-position: 0 100%; 148 | } 149 | 150 | .svg-logo_mtr-dims { 151 | width: 114px; 152 | height: 43px; 153 | } 154 | 155 | -------------------------------------------------------------------------------- /src/scss/page/_faq.scss: -------------------------------------------------------------------------------- 1 | /* faq -------------------- */ 2 | .faq { 3 | max-width: $width-desktop-s; 4 | line-height: 1.5em; 5 | margin: 0 auto 30px; 6 | &__title { 7 | @include font-size(36px); 8 | font-weight: bold; 9 | line-height: 2.5em; 10 | color: $main-color; 11 | text-align: center; 12 | } 13 | &__list { 14 | display: flex; 15 | align-items: center; 16 | justify-content: center; 17 | flex-direction: column; 18 | } 19 | } 20 | 21 | /* faq__list__item */ 22 | .faq__list__item { 23 | @extend %transition; 24 | @include border-radius(5px); 25 | width: 100%; 26 | margin-bottom: 13px; 27 | color: $grey; 28 | border: 1px solid #dedede; 29 | } 30 | 31 | /* faq__list__item > link */ 32 | .faq__list__item-link { 33 | @extend %transition; 34 | @include border-radius(5px); 35 | display: flex; 36 | align-items: center; 37 | justify-content: space-between; 38 | width: 100%; 39 | padding: 25px 20px 25px 0; 40 | color: $grey; 41 | background: white; 42 | 43 | .fa-chevron-up{ 44 | transition: transform 0.5s; 45 | } 46 | 47 | &:hover { 48 | background-color: $main-color; 49 | color: white; 50 | } 51 | } 52 | 53 | /* faq__list__item > link > question */ 54 | .faq__list__item-question { 55 | display: flex; 56 | flex-direction: row; 57 | align-items: center; 58 | justify-content: flex-start; 59 | 60 | h3 { 61 | @include font-size(16px); 62 | padding: 0 20px; 63 | margin-bottom: 0; 64 | 65 | } 66 | 67 | span { 68 | @include font-size(24px); 69 | font-weight: bold; 70 | padding-left: 24px; 71 | 72 | @include mq('mobile-l') { 73 | display: none; 74 | } 75 | } 76 | } 77 | 78 | /* faq__list__item > content */ 79 | .faq__list__item-content { 80 | @include font-size(15px); 81 | @include border-radius(0 0 5px 5px); 82 | transition: max-height 0.5s cubic-bezier(0, 1, 0, 1); 83 | max-height:0; 84 | display: flex; 85 | align-items: flex-start; 86 | background-color: white; 87 | overflow: hidden; 88 | 89 | &-text { 90 | padding: 20px; 91 | } 92 | 93 | p { 94 | margin-bottom: 20px; 95 | color: $grey; 96 | } 97 | 98 | a { 99 | color: $main-color; 100 | } 101 | 102 | span { 103 | @include font-size(24px); 104 | padding: 22px 0 0 26px; 105 | font-weight: bold; 106 | color: $main-color; 107 | 108 | @include mq('mobile-l') { 109 | display: none; 110 | } 111 | } 112 | } 113 | 114 | /* uncss:ignore start */ 115 | /* active */ 116 | .faq__list__item.active { 117 | box-shadow: 0px 5px 15px rgba(202, 65, 65, 0.15), 0px 2px 0px rgba(0, 0, 0, 0.05); 118 | margin: 15px 0 28px 0; 119 | /* uncss:ignore */ 120 | .fa-chevron-up { 121 | transform: rotate(180deg); 122 | } 123 | /* uncss:ignore */ 124 | .faq__list__item-link { 125 | @include border-radius(5px 5px 0 0); 126 | background-color: $main-color; 127 | color: white; 128 | } 129 | /* uncss:ignore */ 130 | .faq__list__item-content { 131 | transition: max-height 1s ease-in-out; 132 | max-height: 2000px; 133 | } 134 | } 135 | /* uncss:ignore end */ 136 | -------------------------------------------------------------------------------- /src/image/img_features.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | -------------------------------------------------------------------------------- /docs/image/img_apply.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/image/img_project_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /src/image/index_portrait_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /src/scss/layout/_footer.scss: -------------------------------------------------------------------------------- 1 | .footer { 2 | width: 100%; 3 | background: white; 4 | color: $grey; 5 | border-top: 1px solid $main-color; 6 | box-shadow: 0px -5px 20px rgba(202, 65, 65, 0.05); 7 | } 8 | 9 | // footer content 10 | .footer__content { 11 | display: flex; 12 | justify-content: space-evenly; 13 | padding: 60px; 14 | max-width: 1200px; 15 | margin: 0 auto; 16 | } 17 | 18 | // footer social media links 19 | .footer__links { 20 | display: flex; 21 | justify-content: flex-start; 22 | flex-direction: column; 23 | width: 250px; 24 | 25 | .logo { 26 | display: flex; 27 | align-items: center; 28 | margin-bottom: 28px; 29 | 30 | .pic { 31 | @extend .svg-logo_lidemy; 32 | width: 52px; 33 | height: 52px; 34 | margin-right: 16px; 35 | } 36 | 37 | h3 { 38 | @include font-size(24px); 39 | margin: 0; 40 | } 41 | } 42 | 43 | p { 44 | @include font-size(14px); 45 | } 46 | 47 | .footer__follow { 48 | color: black; 49 | font-weight: bold; 50 | letter-spacing: 0.12rem; 51 | } 52 | } 53 | 54 | .social-icons { 55 | a { 56 | @include font-size(27px); 57 | margin-right: 24px; 58 | } 59 | } 60 | 61 | // footer navs 62 | .footer__nav-list { 63 | display: flex; 64 | justify-content: space-evenly; 65 | flex: 1; 66 | max-width: 750px; 67 | } 68 | 69 | .footer__nav-item { 70 | display: flex; 71 | flex-direction: column; 72 | justify-content: flex-start; 73 | 74 | h4 { 75 | @include font-size(14px); 76 | padding-bottom: 12px; 77 | margin-bottom: 15px; 78 | font-weight: bold; 79 | letter-spacing: 0.12rem; 80 | border-bottom: 1px solid $grey-light; 81 | } 82 | 83 | a { 84 | @include font-size(12px); 85 | line-height: 2em; 86 | letter-spacing: 0.15rem; 87 | } 88 | } 89 | 90 | .footer__footnote { 91 | @include font-size(12px); 92 | text-align: center; 93 | background: $main-color; 94 | color: white; 95 | display: flex; 96 | flex-wrap: wrap; 97 | justify-content: center; 98 | align-items: center; 99 | padding: 10px 0; 100 | 101 | a { 102 | margin: 0 5px; 103 | } 104 | 105 | .resource { 106 | a { 107 | color: rgba(white, .8); 108 | border:none; 109 | } 110 | } 111 | .copyright, .resource { 112 | color: white; 113 | margin: 0 10px 0; 114 | } 115 | 116 | &__btn { 117 | display: inline-block; 118 | margin: 5px 0; 119 | a { 120 | display: inline-block; 121 | padding: 0px 5px; 122 | border: 1px solid white; 123 | border-radius: 2px; 124 | 125 | &:hover { 126 | color: white; 127 | background: rgba(white, .2); 128 | } 129 | } 130 | } 131 | 132 | } 133 | 134 | 135 | @include mq('desktop-s') { 136 | .footer { 137 | &__content { 138 | flex-direction: column; 139 | padding: 40px 30px; 140 | 141 | } 142 | &__links { 143 | width: 100%; 144 | 145 | .logo { 146 | margin-bottom: .5rem; 147 | .pic { 148 | transform: scale(0.75); 149 | } 150 | 151 | h3 { 152 | @include font-size(16px) 153 | } 154 | } 155 | 156 | p { 157 | @include font-size(13px) 158 | } 159 | 160 | } 161 | 162 | &__social { 163 | justify-content: center; 164 | } 165 | 166 | &__follow { 167 | display: none; 168 | } 169 | } 170 | } 171 | 172 | .footer__nav { 173 | @include mq('desktop-s') { 174 | &-list { 175 | max-width: 100%; 176 | margin-top: 2rem; 177 | flex-wrap: wrap; 178 | justify-content: space-between; 179 | } 180 | 181 | &-item { 182 | min-width: 170px; 183 | margin-bottom: 1.5rem; 184 | padding: 0 10px; 185 | } 186 | } 187 | 188 | @include mq('mobile-m') { 189 | &-item { 190 | min-width: auto; 191 | width: calc((100% - 20px) / 2); 192 | margin-bottom: 1.5rem; 193 | padding: 0; 194 | 195 | a { 196 | font-size: 13px; 197 | } 198 | 199 | &:nth-child(odd) { 200 | margin-right: 20px; 201 | } 202 | } 203 | } 204 | } -------------------------------------------------------------------------------- /src/image/sprite/icon_avatar_4.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /docs/image/theme_dark_character.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/html/layout/footer.pug: -------------------------------------------------------------------------------- 1 | mixin footer_nav_item(item) 2 | li.footer__nav-item 3 | h4.footer__nav-title= item.title 4 | each content in item.contents 5 | a(href=`${content.link}`)= content.text 6 | 7 | //- footer 8 | block footer 9 | footer.footer 10 | .footer__content 11 | .footer__links 12 | a(href="index.html").logo 13 | .pic 14 | .footer__logo-img 15 | h3 Lidemy 16 | p 用六個月的時間,培養出一個找得到工作且基礎紮實的網頁工程師。 17 | p.footer__follow FOLLOW US 18 | .footer__social.social-icons 19 | a(href="https://github.com/Lidemy/mentor-program-4th", target="_blank", rel="noopener", aria-label="GitHub").github-link 20 | 21 | a(href="https://www.facebook.com/lidemytw/", target="_blank", rel="noopener", aria-label="Facebook").facebook-link 22 | 23 | a(href="https://medium.com/@hulitw", target="_blank", rel="noopener", aria-label="Medium").medium-link 24 | 25 | ul.footer__nav-list 26 | - 27 | var footerItems = [ 28 | { 29 | title: "HOME", 30 | contents: [ 31 | { text: "課程特色", link: "/#anchor-features"}, 32 | { text: "教學方式", link: "/#anchor-methods"}, 33 | { text: "關於導師", link: "/#anchor-about-teacher"}, 34 | { text: "課程時程", link: "/#anchor-schedule"}, 35 | { text: "適合怎樣的人", link: "/#anchor-target"}, 36 | { text: "學員心得節錄", link: "/#anchor-previous-experience"}, 37 | ] 38 | }, 39 | { 40 | title: "INTRODUCE", 41 | contents: [ 42 | { text: "計畫介紹", link: "introduce.html#anchor-projectIntro"}, 43 | { text: "老師介紹", link: "introduce.html#anchor-teacherIntro"}, 44 | { text: "歷屆改進心得", link: "introduce.html#anchor-improvement"}, 45 | ] 46 | }, 47 | { 48 | title: "COURSE", 49 | contents: [ 50 | { text: "程式基礎", link: "syllabus.html#anchor-part1"}, 51 | { text: "網站開發", link: "syllabus.html#anchor-part2"}, 52 | { text: "探究原理", link: "syllabus.html#anchor-part3"}, 53 | { text: "專案開發", link: "syllabus.html#anchor-part4"}, 54 | ] 55 | }, 56 | { 57 | title: "RESULT", 58 | contents: [ 59 | { text: "歷屆數據", link: "achievement.html#anchor-data"}, 60 | { text: "學生求職成果", link: "achievement.html#anchor-report"}, 61 | { text: "結業心得", link: "achievement.html#anchor-experience"}, 62 | ] 63 | }, 64 | { 65 | title: "APPLY", 66 | contents: [ 67 | { text: "課程制度", link: "course-info.html#anchor-rule"}, 68 | { text: "收費方式", link: "course-info.html#anchor-charge"}, 69 | { text: "報名方式", link: "course-info.html#anchor-registration"}, 70 | { text: "報名信內容", link: "course-info.html#anchor-letter"}, 71 | { text: "時程列表", link: "course-info.html#anchor-schedule-list"}, 72 | ] 73 | }, 74 | { 75 | title: "FAQ", 76 | contents: [ 77 | { text: "常見問題", link: "faq.html#anchor-faq"}, 78 | ] 79 | }, 80 | ]; 81 | each item in footerItems 82 | +footer_nav_item(item) 83 | .footer__footnote 84 | p.resource illustrator from 85 | a(href="https://getillustrations.com/illustration-pack/ghost-illustrations-builder" target="_blank" rel="noopener") getillustrations.com 86 | p.copyright © 2020 Lidemy. All rights reserved. 87 | .footer__footnote__btn 88 | a(href="https://github.com/Lidemy/mtr-4th-web" target="_blank" rel="noopener") Source Code. 89 | a(href="/humans.txt" target="_blank" rel="noopener") Team. -------------------------------------------------------------------------------- /src/image/img_project_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/image/img_cta_bg.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | -------------------------------------------------------------------------------- /src/image/sprite/img_about_teacher_left.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | -------------------------------------------------------------------------------- /src/image/theme_light_character.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | -------------------------------------------------------------------------------- /docs/image/img_student_experence.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /src/html/faq.pug: -------------------------------------------------------------------------------- 1 | extends layout/layout.pug 2 | 3 | include mixin/_mixin.pug 4 | 5 | //- mixin 6 | mixin list_item(title, activeClass) 7 | li(class= `faq__list__item ${activeClass || ''}`) 8 | a(href='#').faq__list__item-link 9 | .faq__list__item-question 10 | span Q 11 | h3= title 12 | i(class="fas fa-chevron-up") 13 | .faq__list__item-content 14 | span A 15 | .faq__list__item-content-text 16 | if(block) 17 | block 18 | 19 | block head 20 | +head_block({ 21 | title: 'FAQ' 22 | }) 23 | 24 | block current 25 | - var currentUrl = "faq" 26 | 27 | block content 28 | .section.faq.anchor-faq 29 | //- h2.faq__title FAQ 30 | +common_title('FAQ', 'anchor-faq') 31 | ul.faq__list 32 | +list_item('為什麼這個計畫到了第五期還是「實驗」計畫?', 'active') 33 | p 這個計畫搞不好永遠都會叫做「實驗」計畫,因為每一期我都當作一個實驗,實驗我的教學成效如何、品質如何,根據學生的回饋調整課程內容,繼續做下一輪的實驗,持續優化、改進。 34 | +list_item('為什麼我要花這麼多錢只為了看線上影片?') 35 | p 因為這個課程不只有線上影片。 36 | p 除了線上影片以外,還有批改作業的服務以及學習社群,還有學員專屬的直播 QA 時間。這些東西全都加在一起,才是這個計畫的獨特之處。若是你覺得只看線上影片就很足夠了,部分的課程內容其實有在對外販售,可以參考: 37 | a(href="https://lidemy.com/", target="_blank", rel="noopener") Lidemy 課程列表 。 38 | +list_item('為什麼課程裡前後端都有而不是只專注在一個?兩邊都學會不會樣樣通樣樣鬆?') 39 | p 首先,讓你前後端都學絕對不是讓你成為 Full-stack 工程師,成為 Half-stack 倒是有點機會。無論你是前端還是後端,別忘了前面還有大家經常性忽略的一個詞「Web」,Web 前端與後端才是全名。 40 | p 既然 Web 包含了前後端兩個部分,少了任何一部份都不完整,都會讓你對於整個網路的理解缺了一塊。因此這堂課從前到後再由後到前,希望把你對網路的知識整個打通,這樣我覺得才是最完整、最全面的學習。 41 | p 至於樣樣通樣樣鬆,不會。 42 | p 一併學習前後端的好處就是對網路的基礎會比只學單個的紮實許多,因為你對整體有個全面性的理解。而且這邊前後端都注重原理與基礎,基礎打好之後學工具便不是難事。 43 | +list_item('學生出來會不會沒人帶就什麼都不會?') 44 | p 首先,大家要很清楚知道的一點是,在職場上沒人帶才是常態。很有可能你進去的公司只有你一個工程師,或是儘管有一個 team,但也不會有一個人專門去帶你。本來就沒有人有義務去帶你。 45 | p 為了不讓學生變成只會看影片跟著打 code ,關了影片什麼都寫不出來的那種人,我在作業上有做一些調整,很多作業的內容跟要你寫的東西是課程裡面沒有的,你就必須自己去找資料才能實作得出來。 46 | p 所以在課程中就已經培養了一定程度的自學能力。 47 | +list_item('學費方案是怎麼訂的?') 48 | p 在一開始的程式導師實驗計畫,只有「A 求職方案」,背後的理念是:「你來我這邊學半年,如果還找不到工作,那是我的問題,是我沒教好」所以一毛錢都不用付,但如果找到工作了,代表我教得不錯,那就要收一筆學費。 49 | p 但是轉職可不是件簡單的事,雖然說六個月很長了,但是這跟你每天付出多少時間是有關的,一天只能付出兩小時跟一天付出六小時,最後的時數就差了三倍。 50 | p 我規劃的課綱以及作業大概是「每週至少付出 50 個小時」的量,這差不多就是要全職學習了,否則很難做到。而我也認為對想要在半年內轉職的人來說,這樣的時間是必須的。 51 | p 但是一開始的收費規則並沒有很強硬的規定時間以及轉職意願,所以幾期下來,有一些學生是課程開始時想要轉職,到後面卻因為各種因素不想轉了,也有一些可以付出的時間越來越少。 52 | p 若是「沒辦法付出時間」或者「沒有求職意願」,那我前面所說的「你來我這邊學半年,如果還找不到工作,那是我的問題,是我沒教好」這句話就不成立了,因為這句話的前提是:「這半年要持續付出一定時間」以及「你要有求職意願」。 53 | p 但如果只收這種人,就會沒辦法顧到其他的人。例如說已經有工作想來加強基礎,或者是想要邊工作邊學習程式轉職成工程師,時間也可以接受拉得比較長(可能多兩個月之類的),或是純粹對程式有興趣想要學習的人。針對這些人,原本的付費規則就不適用了,因此才有了第四期這個新的付費規則:「就直接付學費吧」。 54 | p 以前幾期的資料來看,若是課程有好好上完,年薪 50 萬跑不掉,那學費就是 60k,因此 B 方案就以這個價錢為基準再降 5k,所以總額才定在 55k。 55 | p 為什麼要降 5k?這是為了讓想要轉職的人也可以考慮 B 方案。如果有人符合選擇 A 方案的資格,但是對自己很有自信,覺得一定可以轉職成功,那就可以選擇 B 方案。對他來說,整體學費變少了,對我來說,我也不須承擔找不到工作學費歸零的風險,是對雙方都有利益的行為。 56 | +list_item('收費方案有點複雜,可以舉一些例子嗎?') 57 | p 案例一:兩個月後選擇「A 求職方案」,繳交保證金 5000 元,跟到課程結束,於課程開始七個月後找到工作,年薪為 50 萬,總共的學費為:500k * 12% = 60k,扣掉保證金 5k,還要再繳 55k 58 | p 案例二:兩個月後選擇「A 求職方案」,繳交保證金 5000 元,課程開始八個月後都還沒找到工作,可以選擇什麼都不做,繼續留在課程,或是退出計畫,退回保證金 5000 元以及收回課程 59 | p 案例三:兩個月後選擇「A 求職方案」,繳交保證金 5000,在第四個月的時候沒有求職意願了,選擇退出課程,需要付 (4-2) * 12500 = 25000 元學費。 60 | p 案例四:兩個月後選擇「B 買斷方案」,繳交保證金 5000 元,一個月後開始每個月付 12500 元學費,付一個月之後就不想上了,退出課程,不收其他費用。 61 | p 附上幾個時間點: 62 | 2021-04-12 課程開始 63 |
64 | 2021-06-01 開始繳交保證金 5000 元並選擇課程方案,選擇「B 買斷方案」的同學需要繳交第一期 5000 + 12500 的款項,之後每個月再付 12500 元,總共要付四期 65 |
66 | 2021-10-12 課程結束,「A 求職方案」的同學開始準備求職 67 |
68 | 2021-12-12 求職期限截止,選擇「A 求職方案」的同學在這個時間點以前沒有找到工作都不用付學費 69 | +list_item('上了這堂課以後,就可以做出這個網站嗎?') 70 | p 很遺憾地告訴你,沒辦法。 71 | p 因為網站漂亮大部分是設計師的功勞,而不是工程師的。工程師通常都只是照著設計稿把網頁刻出來,而這堂課裡面完全不教設計,所以就算上完,也不會掌握任何設計相關能力。 72 | p 不過若是已經有了設計稿,要照著設計稿把這個網站刻出來,我相信是有辦法的(但要花很多時間) 73 | +list_item('上這個課真的不需要有任何程式基礎嗎?') 74 | p 真的,一點都不需要。 75 | p 但同時我也不否認,如果有程式基礎這堂課會上的比較順利。以前滿多學生其實都沒有程式基礎,而且背景跟程式甚至跟理科一點關係都沒有,最後有在時限內轉職成功的,也有失敗的。 76 | p 這堂課原本就是設計給毫無程式基礎的初學者上的,將來也會是這樣,所以不需要擔心。若是還有疑慮,可以參考歷屆學生的心得,找看看有沒有跟你背景差不多的人,聽一下他們怎麼說。 77 | +list_item('上了這堂課以後,一定可以轉職成工程師嗎?') 78 | p 很遺憾地告訴你,不一定。 79 | p 過去也帶了不少學生,並不是每一個人都可以轉職成工程師。不過根據過往的經歷來看,如果有把課程修完,基本上要找到工作是沒有問題的。所以其實最難的點是難在「把課程修完」,因為中途會碰到很多原因讓你想放棄,例如說自己的私事或是提不起興趣、時間不夠等等,也有可能是我的課程設計得不夠好,或者是課程太無聊,老師講得太爛。 80 | p 但我會努力做好我的部分,會盡量去改善課程,讓課程變得更好。 81 | 82 | script(defer src="js/faq.bundle.js") -------------------------------------------------------------------------------- /src/scss/_element.scss: -------------------------------------------------------------------------------- 1 | @mixin button_1($withIcon, $iconId: $fa-var-long-arrow-alt-right) { 2 | @extend %transition; 3 | display: inline-block; 4 | padding: 12px 25px; 5 | background: $main-color; 6 | color: white; 7 | box-shadow: 0px 5px 5px rgba(75, 93, 104, 0.1); 8 | border-radius: 30px; 9 | letter-spacing: 0.2rem; 10 | font-size: 15px; 11 | 12 | &:hover { 13 | color: white; 14 | } 15 | 16 | @if ($withIcon) { 17 | &:after { 18 | @extend %fontawesome-icon; 19 | @extend %transition; 20 | color: white; 21 | content: fa-content($iconId); 22 | position: relative; 23 | right: -5px; 24 | } 25 | 26 | &:hover { 27 | background-color: darken($main-color, 5); 28 | 29 | &:after { 30 | right: -10px; 31 | } 32 | } 33 | } 34 | } 35 | 36 | %shadow-card { 37 | background: white; 38 | box-shadow: 0px 4px 30px rgba(0, 0, 0, 0.1); 39 | border-radius: 10px; 40 | padding: 40px 20px; 41 | margin: 0 auto; 42 | } 43 | 44 | /* common__title -------------------- */ 45 | .common__title { 46 | @include font-size(22px); 47 | line-height: 3.2rem; 48 | margin-bottom: 20px; 49 | color: $color-theme-dark; 50 | width: 100%; 51 | margin: 0 auto; 52 | text-align: center; 53 | 54 | &.left { 55 | text-align: left; 56 | } 57 | 58 | a { 59 | position: relative; 60 | padding-left: 15px; 61 | 62 | &:before { 63 | @include pseudo(inline-block, '#'); 64 | @include absolute($left: 0); 65 | color: $main-color; 66 | font-size: 16px; 67 | font-weight: bold; 68 | } 69 | 70 | &:hover { 71 | color: $main-color; 72 | } 73 | } 74 | } 75 | 76 | 77 | /* link -------------------- */ 78 | %link { 79 | @include font-size(15px); 80 | display: inline-flex; 81 | align-items: center; 82 | justify-content: center; 83 | font-weight: normal; 84 | font-weight: normal; 85 | 86 | &:before { 87 | @extend .svg-icon_arrow_right_red; 88 | @include pseudo(inline-block); 89 | @include relative($top: 7px, $left: 15px); 90 | width: 45px; 91 | height: 20px; 92 | } 93 | } 94 | 95 | /* wave -------------------- */ 96 | .wave { 97 | height: 24px; 98 | background-position: left top; 99 | background-repeat: repeat-x; 100 | } 101 | 102 | /* post -------------------- */ 103 | .post { 104 | max-width: $width-tablet; 105 | margin: 0 auto; 106 | 107 | &:not(:nth-last-of-type(1)) { 108 | margin-bottom: 2.5rem; 109 | } 110 | 111 | &__content { 112 | border-top: 1px dashed $grey-light; 113 | padding: 25px 0; 114 | 115 | p { 116 | @include font-size(16px); 117 | line-height: 2rem; 118 | color: $grey; 119 | } 120 | 121 | ol { 122 | padding-left: 40px; 123 | } 124 | 125 | .annotation { 126 | @include font-size(14px); 127 | } 128 | } 129 | } 130 | 131 | /* post > strong, a */ 132 | .post__content a { 133 | display: inline-block; 134 | margin: 2px 5px; 135 | color: $color-theme-dark; 136 | font-weight: bold; 137 | border: none; 138 | text-decoration: underline; 139 | text-underline-position: under; 140 | text-decoration-style: wavy; 141 | text-decoration-color: lighten($color-theme-dark, 30); 142 | line-height: 1.7rem; 143 | 144 | .theme-light & { 145 | color: white; 146 | } 147 | 148 | &:hover { 149 | border-color: lighten($color-theme-dark, 30); 150 | color: lighten($color-theme-dark, 30); 151 | } 152 | } 153 | .post__content strong{ 154 | margin-bottom: 10px; 155 | position: relative; 156 | margin: 0 5px; 157 | z-index: 1; 158 | padding: 0 5px; 159 | font-weight: normal; 160 | 161 | &:before { 162 | content: ''; 163 | display: block; 164 | background: #ebd8d8; 165 | width: 100%; 166 | height: 9px; 167 | position: absolute; 168 | left: 0; 169 | bottom: -1px; 170 | z-index: -1; 171 | 172 | .theme-light & { 173 | background: darken($main-color, 10); 174 | } 175 | } 176 | } 177 | 178 | /* post: theme-light */ 179 | .post { 180 | .theme-light &__title { 181 | color: white; 182 | &:before { 183 | color: rgba(white, 0.5); 184 | } 185 | 186 | a:hover { 187 | color: rgba(white, 0.9); 188 | } 189 | } 190 | .theme-light &__content { 191 | border-color: white; 192 | p { 193 | color: white; 194 | strong { 195 | color: white; 196 | } 197 | } 198 | } 199 | } -------------------------------------------------------------------------------- /src/image/sprite/icon_avatar_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | -------------------------------------------------------------------------------- /src/image/sprite/icon_avatar_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | -------------------------------------------------------------------------------- /src/image/img_apply.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | -------------------------------------------------------------------------------- /src/image/sprite/icon_avatar_3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | -------------------------------------------------------------------------------- /src/image/sprite/icon_methods_2.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | -------------------------------------------------------------------------------- /src/image/sprite/icon_methods_3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | -------------------------------------------------------------------------------- /src/scss/layout/_header.scss: -------------------------------------------------------------------------------- 1 | $width-header: 1000px; 2 | 3 | /* header -------------------- */ 4 | .header { 5 | position: fixed; 6 | z-index: 9; 7 | display: flex; 8 | justify-content: flex-end; 9 | width: 100%; 10 | margin: 30px auto; 11 | pointer-events: none; 12 | 13 | @include mq('desktop-m') { 14 | padding: 0 30px; 15 | } 16 | 17 | @include mq('tablet') { 18 | padding: 0 4vw; 19 | } 20 | 21 | @include mq('mobile-l') { 22 | margin: 15px auto; 23 | } 24 | 25 | } 26 | 27 | /* uncss:ignore start */ 28 | header.menu-opened { 29 | @include mq('desktop-s') { 30 | .header__content { 31 | height: auto; 32 | flex-direction: column; 33 | align-items: flex-start; 34 | } 35 | 36 | .header__logo { 37 | margin-bottom: 30px; 38 | } 39 | 40 | nav ul { 41 | display: flex; 42 | flex-direction: column; 43 | } 44 | 45 | .header__cta-btn { 46 | display: block; 47 | } 48 | } 49 | } 50 | /* uncss:ignore end */ 51 | 52 | /* header > content */ 53 | .header__content { 54 | height: 90px; 55 | width: $width-header; 56 | max-width: 100%; 57 | margin: 0 auto; 58 | display: flex; 59 | align-items: center; 60 | padding: 25px 40px; 61 | background: white; 62 | border-radius: 50px; 63 | pointer-events: auto; 64 | box-shadow: 0 4px 30px 0 $shadow-color; 65 | border: solid 0.5px $shadow-color; 66 | transition: all 0.275s cubic-bezier(0.07, 0.82, 0.41, 0.97); 67 | transition-property: width, height; 68 | 69 | @include mq('desktop-s') { 70 | overflow: hidden; 71 | } 72 | 73 | @include mq('mobile-l') { 74 | padding: 20px 30px; 75 | height: 70px; 76 | } 77 | } 78 | 79 | /* header > content > logo */ 80 | .header__logo { 81 | display: flex; 82 | flex-direction: row; 83 | justify-content: space-between; 84 | align-items: center; 85 | 86 | @include mq('desktop-s') { 87 | width: 100%; 88 | } 89 | } 90 | 91 | .header__logo-img { 92 | @extend .svg-logo_mtr; 93 | display: block; 94 | height: 40px; 95 | width: 110px; 96 | 97 | @include mq('mobile-l') { 98 | transform: scale(0.85); 99 | } 100 | } 101 | 102 | /* header > content > icon */ 103 | .header__responsive__icon { 104 | @extend %transition; 105 | @include border-radius(50%); 106 | width: 45px; 107 | height: 45px; 108 | display: none; 109 | color: white; 110 | background-color: $main-color; 111 | cursor: pointer; 112 | 113 | &:hover { 114 | transform: scale(1.04); 115 | } 116 | 117 | @include mq('desktop-s') { 118 | display: flex; 119 | align-items: center; 120 | justify-content: center; 121 | width: 35px; 122 | height: 35px; 123 | } 124 | } 125 | 126 | /* header > content > nav */ 127 | .header nav { 128 | width: 100%; 129 | display: flex; 130 | flex: 1; 131 | justify-content: center; 132 | opacity: 1; 133 | transition: opacity .5s; 134 | 135 | ul { 136 | display: flex; 137 | flex: 1; 138 | flex-direction: row; 139 | justify-content: center; 140 | 141 | @include mq('desktop-s') { 142 | flex-direction: column; 143 | display: none; 144 | } 145 | } 146 | } 147 | 148 | /* nav > ul > li */ 149 | .header nav li { 150 | display: inline-block; 151 | font-size: 15px; 152 | color: $grey; 153 | 154 | @include mq('desktop-s') { 155 | border-top: 1px solid rgba(0, 0, 0, 0.08); 156 | 157 | &:nth-last-of-type(1) { 158 | border-bottom: 1px solid rgba(0, 0, 0, 0.08); 159 | margin-bottom: 27px; 160 | } 161 | } 162 | 163 | &.current a { 164 | color: $main-color; 165 | border-bottom: 1px solid $main-color; 166 | 167 | @include mq('desktop-s') { 168 | border: none; 169 | } 170 | 171 | &:before { 172 | display: none; 173 | } 174 | } 175 | 176 | a { 177 | @extend %transition; 178 | display: inline-block; 179 | padding: 16px 0; 180 | margin: 0 13px; 181 | position: relative; 182 | 183 | @include mq('desktop-s') { 184 | width: 100%; 185 | } 186 | 187 | &:before { 188 | z-index: 1; 189 | content: ''; 190 | position: absolute; 191 | left: 0; 192 | bottom: -2px; 193 | width: 100%; 194 | height: 1px; 195 | background: $main-color; 196 | transform: scale(0, 1); 197 | transition: transform 0.6s ease; 198 | 199 | @include mq('desktop-s') { 200 | width: 0; 201 | } 202 | } 203 | } 204 | } 205 | 206 | /* nav > ul > li:hover */ 207 | nav li:hover { 208 | a { 209 | color: $main-color; 210 | 211 | &:before { 212 | transform-origin: left; 213 | transform: scale(1, 1); 214 | } 215 | } 216 | } 217 | 218 | /* header > content > CTA button */ 219 | .header__cta-btn { 220 | @include button_1($withIcon: true); 221 | transition-delay: 0.2s; 222 | 223 | @include mq('desktop-s') { 224 | display: none; 225 | } 226 | } 227 | 228 | /* uncss:ignore start */ 229 | /* media query */ 230 | @media (min-width: $width-header) { 231 | .header.is-shrunk { 232 | .header__content { 233 | margin-right:calc((100% - 1000px) / 2); 234 | } 235 | } 236 | } 237 | 238 | @media (min-width: 901px) { 239 | // header shrunk 240 | .header.is-shrunk { 241 | .header__logo { 242 | width: 100%; 243 | } 244 | 245 | .header__content { 246 | display: flex; 247 | justify-content: space-between; 248 | width: 280px; 249 | margin-right:calc((100% - 900px) / 2); 250 | } 251 | 252 | nav { 253 | display: none; 254 | } 255 | 256 | .header__cta-btn { 257 | display: none; 258 | } 259 | 260 | .header__responsive__icon { 261 | width: 45px; 262 | height: 45px; 263 | display: flex; 264 | align-items: center; 265 | justify-content: center; 266 | } 267 | } 268 | 269 | /* header invisible */ 270 | .header__nav.content-invisible, 271 | .header__cta-btn.content-invisible { 272 | visibility: hidden; 273 | opacity: 0; 274 | } 275 | } 276 | 277 | /* uncss:ignore end */ -------------------------------------------------------------------------------- /gulpfile.js: -------------------------------------------------------------------------------- 1 | const gulp = require('gulp'); 2 | const { src, dest } = require('gulp'); 3 | const pug = require('gulp-pug'); 4 | const sass = require('gulp-sass'); 5 | const postcss = require('gulp-postcss'); 6 | const uncss = require('postcss-uncss'); 7 | const autoprefixer = require('autoprefixer'); 8 | const minifyCSS = require('gulp-csso'); 9 | const rename = require('gulp-rename'); 10 | const sourcemaps = require('gulp-sourcemaps'); 11 | const connect = require('gulp-connect'); 12 | const imageMin = require('gulp-imagemin'); 13 | const del = require('del') 14 | const browserify = require("browserify"); 15 | const babelify = require("babelify"); 16 | const source = require("vinyl-source-stream"); 17 | const glob = require('glob'); 18 | const es = require('event-stream'); 19 | const uglify = require('gulp-uglify'); 20 | const buffer = require('vinyl-buffer'); 21 | const svgSprite = require('gulp-svg-sprite'); 22 | const merge = require('merge-stream'); 23 | const gulpif = require('gulp-if'); 24 | const fontmin = require('gulp-fontmin-woff2'); 25 | 26 | // run minfont.js to get this string 27 | const fontText = '\uf028\uf164\uf57d\uf1c0\uf7d9\uf233\uf201\uf3ed\uf126\uf51c\uf06e\uf0c9\uf35d\uf077\uf00c\uf2bd\uf061\uf063\uf062\uf073\uf550\uf14a\uf35a\uf0c5\uf30b\uf09b\uf082\uf23a\uf41b\uf3b8\uf13b\uf38b\uf268\uf457' 28 | const env = process.env.NODE_ENV; 29 | 30 | console.log('--- current mode: ', env); 31 | 32 | const base = { 33 | src: 'src', 34 | dest: 'docs', 35 | } 36 | const paths = { 37 | css: { 38 | src: `${base.src}/scss/*.scss`, 39 | dest: `${base.dest}/css`, 40 | }, 41 | js: { 42 | src: `${base.src}/js/**/*.js`, 43 | dest: `${base.dest}/js`, 44 | }, 45 | html: { 46 | src: `${base.src}/html/*.pug`, 47 | dest: base.dest, 48 | }, 49 | image: { 50 | src: `${base.src}/image/*.+(jpg|jpeg|gif|png|svg)`, 51 | dest: `${base.dest}/image`, 52 | } 53 | }; 54 | 55 | function clean() { 56 | return del([ 57 | `${base.dest}/*`, 58 | `!${base.dest}/.git`, 59 | `!${base.dest}/.gitignore`, 60 | `!${base.dest}/robots.txt`, 61 | ]); 62 | } 63 | 64 | const js = (done) => { 65 | glob('./src/js/bundle/*.js', function (err, files) { 66 | if (err) done(err); 67 | 68 | files.push('src/js/index.js'); 69 | var tasks = files.map(function (entry) { 70 | return browserify({ 71 | entries: [entry], 72 | debug: env === 'development', 73 | transform: [babelify.configure(),] 74 | }) 75 | .bundle() 76 | .pipe(source(entry.match(/[^\\/]+$/)[0])) 77 | .pipe(buffer()) 78 | .pipe(sourcemaps.init({ loadMaps: true })) 79 | .pipe(uglify()) 80 | .pipe(gulpif(env === 'development', sourcemaps.write())) 81 | .pipe(rename({ 82 | extname: '.bundle.js' 83 | })) 84 | .pipe(gulp.dest(paths.js.dest)); 85 | }); 86 | es.merge(tasks).on('end', done) 87 | .pipe(connect.reload()); 88 | }) 89 | } 90 | 91 | function html() { 92 | return src(paths.html.src) 93 | .pipe(pug()) 94 | .pipe(dest(base.dest)) 95 | .pipe(connect.reload()) 96 | } 97 | 98 | function sprite() { 99 | const config = { 100 | shape: { 101 | dimension: { 102 | maxWidth: 300, 103 | maxHeight: 300, 104 | }, 105 | spacing: { 106 | padding: 2, 107 | }, 108 | }, 109 | mode: { 110 | view: { 111 | bust: false, 112 | example: true, 113 | layout: 'vertical', 114 | sprite: 'sprite.svg', 115 | render: { 116 | scss: { dest: '_sprite.scss' } 117 | } 118 | }, 119 | } 120 | }; 121 | return src('src/image/sprite/*.svg') 122 | .pipe(svgSprite(config)) 123 | .pipe(gulp.dest('src/scss/sprite')); 124 | } 125 | 126 | function css() { 127 | const processors = [ 128 | autoprefixer({ overrideBrowserslist: ['last 2 version'] }), 129 | ]; 130 | 131 | if (env === 'production') { 132 | processors.push( 133 | uncss({ 134 | html: ['docs/*.html'], 135 | }) 136 | ) 137 | } 138 | const css = gulp.src(paths.css.src) 139 | .pipe(sourcemaps.init()) 140 | .pipe(sass().on('error', sass.logError)) 141 | .pipe(postcss(processors)) 142 | .pipe(minifyCSS()) 143 | .pipe(gulpif(env === 'development', sourcemaps.write())) 144 | .pipe(rename({ 145 | basename: 'main', 146 | suffix: '.min' 147 | })) 148 | .pipe(dest(paths.css.dest)) 149 | .pipe(connect.reload()) 150 | 151 | const copySprite = gulp.src('src/scss/sprite/view/*.svg') 152 | .pipe(gulp.dest('docs/css/')) 153 | 154 | return merge(css, copySprite); 155 | } 156 | 157 | function font() { 158 | return src(`${base.src}/webfonts/*.ttf`) 159 | .pipe(fontmin({ 160 | text: fontText, 161 | })) 162 | .pipe(dest(`${base.dest}/webfonts`)) 163 | } 164 | 165 | function img() { 166 | return src(paths.image.src) 167 | .pipe(imageMin()) 168 | .pipe(dest(paths.image.dest)) 169 | .pipe(connect.reload()) 170 | } 171 | 172 | function beforeEnd() { 173 | return src(`${base.src}/statics/*`) 174 | .pipe(dest(`${base.dest}`)) 175 | } 176 | 177 | function watch(done) { 178 | if (env !== 'production') { 179 | gulp.watch(`${base.src}/scss/**/*`, css); 180 | gulp.watch(`${base.src}/html/**/*`, html); 181 | gulp.watch(`${base.src}/js/**/*`, js); 182 | gulp.watch(`${base.src}/image/*`, img); 183 | gulp.watch(`${base.src}/image/*`, gulp.series(sprite, css)); 184 | } 185 | done(); 186 | } 187 | 188 | function server(done) { 189 | if (env !== 'production') { 190 | var options = { 191 | root: 'docs', 192 | port: 8080, 193 | livereload: true, 194 | }; 195 | connect.server(options); 196 | } 197 | done(); 198 | }; 199 | 200 | const resource = gulp.series(js, gulp.parallel(html, css, img, font)) 201 | const build = gulp.series(clean, sprite, resource, beforeEnd, gulp.parallel(watch, server)) 202 | 203 | exports.clean = clean; 204 | exports.default = build; 205 | exports.js = js; 206 | exports.css = css 207 | exports.img = img 208 | exports.beforeEnd = beforeEnd 209 | exports.sprite = gulp.series(sprite, css); -------------------------------------------------------------------------------- /src/image/theme_dark_character.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /src/image/img_student_experence.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | -------------------------------------------------------------------------------- /src/image/sprite/img_about_teacher.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | -------------------------------------------------------------------------------- /src/image/sprite/icon_methods_1.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | --------------------------------------------------------------------------------