commit
c5d7f7c93d
@ -0,0 +1,2 @@ |
||||
node_modules/ |
||||
assets/ |
@ -0,0 +1 @@ |
||||
@import "sanitize.css"; |
@ -0,0 +1,48 @@ |
||||
@charset "UTF-8"; |
||||
|
||||
@fonts-dir: "/fonts"; |
||||
@images-dir: "/images"; |
||||
|
||||
@background: #fafafa; |
||||
@text: #212121; |
||||
@root-font-size: 14px; |
||||
|
||||
@phone-width: 600px; |
||||
|
||||
.include-font(@font-family, @font-name, @font-weight: normal, @font-style: normal) { |
||||
@font-face { |
||||
font-family: "@{font-family}"; |
||||
src: |
||||
url("@{fonts-dir}/@{font-name}.woff2") format("woff2"), |
||||
url("@{fonts-dir}/@{font-name}.woff") format("woff"), |
||||
url("@{fonts-dir}/@{font-name}.ttf") format("truetype"); |
||||
|
||||
font-weight: @font-weight; |
||||
font-style: @font-style; |
||||
font-display: block; |
||||
unicode-range: U+00??, U+04??, U+20??, U+226?; |
||||
} |
||||
} |
||||
|
||||
|
||||
.if-min-width(@target, @rules) { |
||||
@media (min-width: @target) { |
||||
@rules(); |
||||
} |
||||
} |
||||
|
||||
.if-max-width(@target, @rules) { |
||||
@media (max-width: @target) { |
||||
@rules(); |
||||
} |
||||
} |
||||
|
||||
.if-width(@target, @rules-min, @rules-max) { |
||||
@media (min-width: @target) { |
||||
@rules-min(); |
||||
} |
||||
|
||||
@media (max-width: @target) { |
||||
@rules-max(); |
||||
} |
||||
} |
@ -0,0 +1,45 @@ |
||||
html { |
||||
font-size: @root-font-size; |
||||
} |
||||
|
||||
body { |
||||
padding: 0; |
||||
font-size: 1rem; |
||||
font-weight: normal; |
||||
letter-spacing: 0.02rem; |
||||
text-align: center; |
||||
color: @text; |
||||
} |
||||
|
||||
|
||||
button, input, textarea { |
||||
font-family: inherit; |
||||
outline: none; |
||||
} |
||||
|
||||
textarea { |
||||
resize: none; |
||||
} |
||||
|
||||
@supports (appearance: none) { |
||||
textarea, button, input { |
||||
appearance: none; |
||||
} |
||||
} |
||||
|
||||
h1, h2, h3 { |
||||
padding-top: 0; |
||||
margin-top: 0; |
||||
padding-bottom: 0; |
||||
font-weight: 500; |
||||
} |
||||
|
||||
h1 { |
||||
font-size: 1.5rem; |
||||
margin-bottom: 1.2rem; |
||||
} |
||||
|
||||
h2 { |
||||
font-size: 1.2rem; |
||||
margin-bottom: .8rem; |
||||
} |
@ -0,0 +1,117 @@ |
||||
.include-font(Roboto, Roboto-Regular, normal, normal); |
||||
.include-font(Roboto, Roboto-Italic, normal, italic); |
||||
.include-font(Roboto, Roboto-Thin, 100, normal); |
||||
.include-font(Roboto, Roboto-ThinItalic, 100, italic); |
||||
.include-font(Roboto, Roboto-Light, 300, normal); |
||||
.include-font(Roboto, Roboto-LightItalic, 300, italic); |
||||
.include-font(Roboto, Roboto-Medium, 500, normal); |
||||
.include-font(Roboto, Roboto-MediumItalic, 500, italic); |
||||
.include-font(Roboto, Roboto-Bold, 700, normal); |
||||
.include-font(Roboto, Roboto-BoldItalic, 700, italic); |
||||
.include-font(Roboto, Roboto-Black, 900, normal); |
||||
.include-font(Roboto, Roboto-BlackItalic, 900, italic); |
||||
|
||||
body { |
||||
font-family: "Roboto", "Segoe UI", Tahoma, sans-serif; |
||||
} |
||||
|
||||
@keyframes spin { |
||||
from { transform: rotateZ(0deg); } |
||||
to { transform: rotateZ(360deg); } |
||||
} |
||||
|
||||
// ff3ce7 |
||||
body > .body-background { |
||||
position: fixed; |
||||
width: 300vmax; height: 300vmax; |
||||
left: -100vmax; top: -100vmax; |
||||
z-index: -1; |
||||
|
||||
background: linear-gradient(-35deg, #004eff, transparent), |
||||
linear-gradient(118deg, #78ff78, transparent), |
||||
radial-gradient(300px 100px ellipse at top, #a3fa9f50, transparent 30%), |
||||
radial-gradient(300px 100px ellipse at bottom, #a3fa9f50, transparent 30%); |
||||
background-blend-mode: screen; |
||||
animation: spin 300s linear infinite; |
||||
} |
||||
|
||||
body > .body-wrapper { |
||||
display: flex; |
||||
min-height: 100vh; |
||||
|
||||
& > .hspacer { |
||||
min-width: 5vw; |
||||
width: 6.5vw; |
||||
max-width: 8vw; |
||||
.if-max-width(600px, { |
||||
min-width: 2vw; |
||||
width: 4vw; |
||||
max-width: 6vw; |
||||
}); |
||||
} |
||||
|
||||
& > .content { |
||||
position: relative; |
||||
height: auto; |
||||
|
||||
display: flex; |
||||
flex-direction: column; |
||||
align-items: center; |
||||
flex-grow: 1; |
||||
|
||||
max-width: 1000px; |
||||
margin: 0 auto; |
||||
padding: 2rem 0; |
||||
.if-max-width(@phone-width, { padding: 1.25rem 0; }); |
||||
|
||||
& > .box { |
||||
display: flex; |
||||
flex-direction: column; |
||||
|
||||
margin: 1.5rem 2rem; |
||||
padding-top: 3rem; |
||||
padding-bottom: 3rem; |
||||
padding-left: 3rem; |
||||
padding-right: 1.5rem; |
||||
|
||||
background-color: #fafafa; |
||||
border-radius: 1rem; |
||||
width: 100%; |
||||
flex-grow: 1; |
||||
max-height: 2000px; |
||||
text-align: left; |
||||
|
||||
& > h1.header { |
||||
text-align: center; |
||||
margin-bottom: 0; |
||||
font-size: 1.75rem; |
||||
} |
||||
|
||||
& > i.header { |
||||
text-align: center; |
||||
margin-bottom: 2.5rem; |
||||
font-size: .9rem; |
||||
} |
||||
|
||||
& ul { |
||||
margin-top: 0.25rem; |
||||
margin-bottom: 1.25rem; |
||||
|
||||
} |
||||
|
||||
& > span.footer { |
||||
margin-bottom: 1rem; |
||||
} |
||||
|
||||
& > h1 { |
||||
|
||||
} |
||||
|
||||
& > p { |
||||
|
||||
} |
||||
|
||||
|
||||
} |
||||
} |
||||
} |
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -0,0 +1,138 @@ |
||||
'use strict'; |
||||
|
||||
const { src, dest, watch, series, parallel } = require('gulp'); |
||||
const del = require('del'); |
||||
const concat = require('gulp-concat'); |
||||
const gulpIf = require('gulp-if'); |
||||
const postcss = require('gulp-postcss'); |
||||
const sourcemaps = require('gulp-sourcemaps'); |
||||
const pug = require('gulp-pug'); |
||||
const favicons = require('gulp-favicons'); |
||||
const inject = require('gulp-inject'); |
||||
|
||||
const appConfig = require('./package.json'); |
||||
|
||||
const production = (process.argv.indexOf('production') > -1); |
||||
|
||||
|
||||
|
||||
function taskInfo(cb) { |
||||
console.log(`Running in ${production ? 'production' : 'development'} mode`); |
||||
cb(); |
||||
} |
||||
|
||||
function taskHTML(cb) { |
||||
return src('./templates/*.pug') |
||||
.pipe(pug({ |
||||
basedir: './templates/includes', |
||||
...(!production && {pretty: true}) |
||||
})) |
||||
.pipe(dest('./assets')); |
||||
} |
||||
|
||||
function taskLESS(cb) { |
||||
return src('./css/*.less') |
||||
.pipe(gulpIf(!production, sourcemaps.init())) |
||||
.pipe(concat('app.css')) |
||||
.pipe(require('gulp-less')({ |
||||
math: 'strict', |
||||
strictUnits: true |
||||
})) |
||||
.pipe(postcss([ |
||||
require('postcss-flexbugs-fixes'), |
||||
require('postcss-preset-env')(), |
||||
require('postcss-normalize')(), |
||||
require('cssnano')() |
||||
])) |
||||
.pipe(gulpIf(!production, sourcemaps.write())) |
||||
.pipe(dest('./assets/css')); |
||||
} |
||||
|
||||
function taskCSS(cb) { |
||||
return src('./css/*.css') |
||||
.pipe(gulpIf(!production, sourcemaps.init())) |
||||
.pipe(concat('vendor.css')) |
||||
.pipe(postcss([ |
||||
require('cssnano')() |
||||
])) |
||||
.pipe(gulpIf(!production, sourcemaps.write())) |
||||
.pipe(dest('./assets/css')); |
||||
} |
||||
|
||||
function taskJS(cb) { |
||||
return src('./js/*.js') |
||||
.pipe(gulpIf(!production, sourcemaps.init())) |
||||
.pipe(concat('app.js')) |
||||
.pipe(require('gulp-uglify')()) |
||||
.pipe(gulpIf(!production, sourcemaps.write())) |
||||
.pipe(dest('./assets/js')); |
||||
} |
||||
|
||||
function taskFonts(cb) { |
||||
return src('./fonts/**/*') |
||||
.pipe(dest('./assets/fonts')); |
||||
} |
||||
|
||||
function taskFavicon(cb) { |
||||
return src('./images/favicon.png') |
||||
.pipe(favicons({ |
||||
path: '/', |
||||
appName: appConfig.appName || appConfig.name || "", |
||||
appDescription: appConfig.description || "", |
||||
logging: false, |
||||
html: 'favicon.html', |
||||
pipeHTML: true, |
||||
replace: true, |
||||
|
||||
...(appConfig.version && {version: appConfig.version}), |
||||
...(appConfig.iconBackgroundColor && {background: appConfig.iconBackgroundColor}), |
||||
...(appConfig.themeColor && {theme_color: appConfig.themeColor}), |
||||
...(appConfig.url && {url: appConfig.url}), |
||||
...(appConfig.scope && {scope: appConfig.scope}), |
||||
|
||||
icons: { |
||||
android: true, |
||||
appleIcon: false, |
||||
appleStartup: false, |
||||
windows: false, |
||||
yandex: false, |
||||
} |
||||
})) |
||||
.pipe(dest('./assets')); |
||||
} |
||||
|
||||
function taskInjectFavicon(cb) { |
||||
return src('./assets/index.html') |
||||
.pipe(inject(src(['./assets/favicon.html']), { |
||||
starttag: '<!-- inject:head:{{ext}} -->', |
||||
transform: function(filePath, file) { |
||||
return file.contents.toString('utf8').replace(/[\n\r]+/g, ''); |
||||
}, |
||||
removeTags: true |
||||
})) |
||||
.pipe(dest('./assets')); |
||||
} |
||||
|
||||
function taskCleanFavicon(cb) { |
||||
return del(['./assets/favicon.html']); |
||||
} |
||||
|
||||
|
||||
function taskClean(cb) { |
||||
return del(['./assets/**/*'], cb); |
||||
} |
||||
|
||||
function taskWatch(cb) { |
||||
taskInfo(() => {}); |
||||
watch(['./templates/**/*.pug'], series(taskFavicon, taskHTML, taskInjectFavicon, taskCleanFavicon)); |
||||
watch(['./css/**/*.css'], taskCSS); |
||||
watch(['./css/**/*.less'], taskLESS); |
||||
watch(['./js/**/*.js'], taskJS); |
||||
watch(['./fonts/**/*'], taskFonts); |
||||
watch(['./images/favicon.png'], series(taskFavicon, taskHTML, taskInjectFavicon, taskCleanFavicon)); |
||||
} |
||||
|
||||
exports.clean = taskClean; |
||||
exports.watch = taskWatch; |
||||
exports.build = series(taskInfo, taskClean, series(taskFavicon, taskHTML, taskInjectFavicon, taskCleanFavicon), parallel(taskLESS, taskCSS, taskJS, taskFonts)); |
||||
exports.default = exports.watch; |
After Width: | Height: | Size: 17 KiB |
@ -0,0 +1 @@ |
||||
'use strict'; |
@ -0,0 +1,3 @@ |
||||
window.addEventListener('load', ev => { |
||||
|
||||
}); |
File diff suppressed because it is too large
Load Diff
@ -0,0 +1,32 @@ |
||||
{ |
||||
"name": "resume", |
||||
"version": "0.1.0", |
||||
"description": "", |
||||
"main": "gulpfile.js", |
||||
"scripts": { |
||||
"build-dev": "gulp build --option development", |
||||
"build-prod": "gulp build --option production" |
||||
}, |
||||
"author": "", |
||||
"license": "ISC", |
||||
"devDependencies": { |
||||
"cssnano": "^5.0.12", |
||||
"del": "^6.0.0", |
||||
"gulp": "*", |
||||
"gulp-concat": "^2.6.1", |
||||
"gulp-favicons": "^3.0.0", |
||||
"gulp-if": "^3.0.0", |
||||
"gulp-inject": "^5.0.5", |
||||
"gulp-less": "^5.0.0", |
||||
"gulp-postcss": "^9.0.1", |
||||
"gulp-pug": "^5.0.0", |
||||
"gulp-sourcemaps": "^3.0.0", |
||||
"gulp-uglify": "^3.0.2", |
||||
"postcss-flexbugs-fixes": "^5.0.2", |
||||
"postcss-normalize": "^10.0.1", |
||||
"postcss-preset-env": "^7.0.1" |
||||
}, |
||||
"private": true, |
||||
"iconBackgroundColor": "#ffffff", |
||||
"themeColor": "#ffffff" |
||||
} |
@ -0,0 +1,3 @@ |
||||
mixin modal(name, ...classes) |
||||
.modal(id=name, class=classes) |
||||
block |
@ -0,0 +1,112 @@ |
||||
doctype html |
||||
|
||||
include includes/mixins.pug |
||||
|
||||
html(lang='ru') |
||||
head |
||||
meta(charset='utf-8') |
||||
meta(name='viewport' content='width=device-width, initial-scale=1, viewport-fit=cover') |
||||
meta(name='referrer' content='strict-origin-when-cross-origin') |
||||
meta(name='color-scheme' content='light dark') |
||||
|
||||
// inject:head:html |
||||
// endinject |
||||
|
||||
title Резюме 🤔 |
||||
|
||||
link(rel='stylesheet' href='/css/app.css') |
||||
block styles |
||||
|
||||
script(src='/js/app.js') |
||||
block scripts |
||||
body |
||||
.body-background |
||||
|
||||
.body-wrapper |
||||
.hspacer |
||||
.content |
||||
.box |
||||
h1.header Резюме, которое не совсем резюме |
||||
i.header (ну или что-то типа того) |
||||
h1 Немного о себе |
||||
span Системный администратор "широкого профиля": |
||||
ul |
||||
li DevOps |
||||
li веб-разработка |
||||
li реверс-инжирининг |
||||
li собственно сисадминство |
||||
h1 Что умею и с чем работал: |
||||
ul |
||||
li администрирование Windows/Windows Server/Hyper-V Server: |
||||
ul |
||||
li достаточно хорошие знания AD |
||||
li развертывание и обслуживание тенантов AAD/O365 |
||||
li отличные навыки работы с PowerShell |
||||
li настройка и поддержка кластера на Hyper-V Server |
||||
li Windows Core <3 |
||||
li |
||||
s переустановка Windows |
||||
| ? eventvwr.msc, Procmon, WinDbg, ну и так далее |
||||
li опыт работы практически со всеми ролями/возможностями Windows Server |
||||
li администрирование Linux: |
||||
ul |
||||
li на любой вкус: bare-metal, VM, CT, embedded, ... |
||||
li любые дистрибутивы |
||||
li есть опыт работы (и сертификат) Astra Linux |
||||
li :q! |
||||
li сетевые технологии |
||||
ul |
||||
li DNS, DHCP, ARP, NAT, IPsec, SSH, BGP, OSPF, VLAN, GRE, EoIP, IPIP, L2TP, PPTP, VRRP и другие 3/4-буквенные акронимы |
||||
li |
||||
i в IPsec 5 букв, но не будем об этом |
||||
li а еще такие штуки, как DNSSEC, TLSA, IPv6, ND, IKEv2... |
||||
li прекрасно разбираюсь в Mikrotik и RouterOS (есть сертификат MTCNA) |
||||
li "защелка на кабеле для интернета" называется не RJ-45, а 8P8C |
||||
li развертывание сервисов: |
||||
ul |
||||
li системы виртуализации и гиперконвергентные решения (Hyper-V, Proxmox) |
||||
li веб-серверы и реверс-прокси (nginx, haproxy, caddy) |
||||
li электронная почта (postfix/dovecot/rspamd) |
||||
li базы данных (mariadb/postgres/mongodb) |
||||
li телефония (Asterisk/FreePBX) |
||||
li и еще всякие разные сервисы - спросите, может, вспомню |
||||
li автоматизация: |
||||
ul |
||||
li Ansible ван лав 🥰 |
||||
li все, что только можно, стараюсь деплоить через Ansible |
||||
li а также DSR/GPO |
||||
li программирование/скриптинг: |
||||
ul |
||||
li PowerShell |
||||
li ECMAScript/NodeJS |
||||
li ANSI C11 |
||||
li x86/x86-64 asm |
||||
li железяки: |
||||
ul |
||||
li разборка/починка/сборка всего, что только возможно |
||||
li на счету уже 6 или 7 паяльник |
||||
|
||||
|
||||
span.footer |
||||
| Если что, я написал эту штуку за пару часов, поэтому это не то, чтобы резюме, а так, просто |
||||
| показать стек технологий, с которыми умею работать |
||||
|
||||
span.footer |
||||
| Может, через несколько дней доведу это все до более-менее красивого состояния. Но, наверное, |
||||
| не придется 😄 |
||||
|
||||
span.footer Да, и если интересно, на чем это все крутится: |
||||
ul |
||||
li мини-неттоп за 6000р с Авито |
||||
li Proxmox VE 7 |
||||
li 4 LXC-контейнера: |
||||
ul |
||||
li web: nginx - reverse proxy с HTTPS termination |
||||
li resume: nginx - хостит непосредственно этот "фронтэнд" |
||||
li nse1: nsd - авторитативный (авторитарный? как его правильно назвать?) DNS-сервер для зоны pootis.network |
||||
li |
||||
| ansible: конечно же, все развертывается через Ansible, даже записи в DNS-зоне, даже TLS-сертификаты |
||||
li Сам фронтэнд написан на pug+less, собирается через gulp |
||||
|
||||
span.footer Ну вот как-то так 😅 |
||||
.hspacer |
Loading…
Reference in new issue