diff options
Diffstat (limited to 'htdocs')
-rw-r--r-- | htdocs/ahrefs_73b56e4c8d3bca4f4712e71f638a499c464e3faf55dd02ed02dbb5649850b8f3 | 1 | ||||
-rw-r--r-- | htdocs/favicon.ico | bin | 0 -> 1150 bytes | |||
-rw-r--r-- | htdocs/img/attachment.svg | 1 | ||||
-rw-r--r-- | htdocs/img/contact.gif | bin | 0 -> 164 bytes | |||
-rw-r--r-- | htdocs/img/contact@2x.gif | bin | 0 -> 386 bytes | |||
-rw-r--r-- | htdocs/img/enter.svg | 1 | ||||
-rw-r--r-- | htdocs/index.php | 28 | ||||
-rw-r--r-- | htdocs/js/admin.js | 193 | ||||
-rw-r--r-- | htdocs/js/common.js | 392 | ||||
-rw-r--r-- | htdocs/openpgp-pubkey.txt | 51 | ||||
-rw-r--r-- | htdocs/sass.php | 48 | ||||
-rw-r--r-- | htdocs/scss/admin.scss | 3 | ||||
-rw-r--r-- | htdocs/scss/blog.scss | 383 | ||||
-rw-r--r-- | htdocs/scss/common-bundle.scss | 9 | ||||
-rw-r--r-- | htdocs/scss/common.scss | 415 | ||||
-rw-r--r-- | htdocs/scss/form.scss | 59 | ||||
-rw-r--r-- | htdocs/scss/hljs.scss | 1 | ||||
-rw-r--r-- | htdocs/scss/hljs/github.scss | 99 | ||||
-rw-r--r-- | htdocs/scss/mobile.scss | 41 | ||||
-rw-r--r-- | htdocs/scss/pages.scss | 14 | ||||
-rw-r--r-- | htdocs/scss/vars.scss | 71 | ||||
-rw-r--r-- | htdocs/yandex_3512181a57932602.html | 6 |
22 files changed, 1816 insertions, 0 deletions
diff --git a/htdocs/ahrefs_73b56e4c8d3bca4f4712e71f638a499c464e3faf55dd02ed02dbb5649850b8f3 b/htdocs/ahrefs_73b56e4c8d3bca4f4712e71f638a499c464e3faf55dd02ed02dbb5649850b8f3 new file mode 100644 index 0000000..cdf5a84 --- /dev/null +++ b/htdocs/ahrefs_73b56e4c8d3bca4f4712e71f638a499c464e3faf55dd02ed02dbb5649850b8f3 @@ -0,0 +1 @@ +ahrefs-site-verification_73b56e4c8d3bca4f4712e71f638a499c464e3faf55dd02ed02dbb5649850b8f3
\ No newline at end of file diff --git a/htdocs/favicon.ico b/htdocs/favicon.ico Binary files differnew file mode 100644 index 0000000..d5ff579 --- /dev/null +++ b/htdocs/favicon.ico diff --git a/htdocs/img/attachment.svg b/htdocs/img/attachment.svg new file mode 100644 index 0000000..9026687 --- /dev/null +++ b/htdocs/img/attachment.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" height="680" viewBox="-25 0 510 510.257" width="680"><path d="M32.39 314.484l37.74-37.738 169.815-169.808c31.297-31.063 81.817-30.97 112.997.21 31.18 31.18 31.273 81.7.21 112.997L183.345 390.004c-6.945 6.95-18.211 6.95-25.16 0-6.946-6.95-6.946-18.211 0-25.16l169.808-169.86c17.368-17.367 17.368-45.52 0-62.886-17.367-17.368-45.52-17.368-62.886 0L95.246 301.906l-37.738 37.735c-31.266 31.277-31.254 81.976.02 113.238 31.277 31.262 81.972 31.254 113.238-.023l31.441-31.454L378.31 245.301l12.582-12.578c43.976-45.352 43.418-117.602-1.25-162.274-44.672-44.668-116.922-45.226-162.274-1.25L38.687 257.883a17.797 17.797 0 0 1-29.765-7.977 17.796 17.796 0 0 1 4.606-17.183l188.68-188.68c59.09-58.82 154.64-58.711 213.593.246 58.957 58.953 59.066 154.504.246 213.594l-188.68 188.68-31.488 31.453c-45.41 43.617-117.375 42.89-161.89-1.641-44.52-44.527-45.227-116.492-1.598-161.89zm0 0" fill="#888"/></svg>
\ No newline at end of file diff --git a/htdocs/img/contact.gif b/htdocs/img/contact.gif Binary files differnew file mode 100644 index 0000000..f4695c1 --- /dev/null +++ b/htdocs/img/contact.gif diff --git a/htdocs/img/contact@2x.gif b/htdocs/img/contact@2x.gif Binary files differnew file mode 100644 index 0000000..ab79cd3 --- /dev/null +++ b/htdocs/img/contact@2x.gif diff --git a/htdocs/img/enter.svg b/htdocs/img/enter.svg new file mode 100644 index 0000000..6fe49ed --- /dev/null +++ b/htdocs/img/enter.svg @@ -0,0 +1 @@ +<svg xmlns="http://www.w3.org/2000/svg" width="15" height="9.474"><path d="M0 4.737l4.737 4.737 1.105-1.106L3 5.526h12V.79h-1.579v3.158H3l2.842-2.842L4.737 0z"/></svg> diff --git a/htdocs/index.php b/htdocs/index.php new file mode 100644 index 0000000..a1199da --- /dev/null +++ b/htdocs/index.php @@ -0,0 +1,28 @@ +<?php + +require_once __DIR__.'/../init.php'; + +$r = (new Router()) + // route handler input + // ----- ------- ----- + ->add('/', 'index') + ->add('contacts/', 'contacts') + ->add('projects.html', 'projects') + ->add('blog/(\d+)/', 'post_id id=$(1)') + ->add('([a-z0-9-]+)/', 'auto name=$(1)') + + ->add('feed.rss', 'RSS') + + ->add('admin/', 'admin/index') + ->add('admin/{login,logout,log}/', 'admin/${1}') + + ->add('([a-z0-9-]+)/{delete,edit}/', 'admin/auto_${1} short_name=$(1)') + ->add('([a-z0-9-]+)/create/', 'admin/page_add short_name=$(1)') + ->add('write/', 'admin/post_add') + ->add('admin/markdown-preview.ajax', 'admin/markdown_preview') + + ->add('uploads/', 'admin/uploads') + ->add('uploads/{edit_note,delete}/(\d+)/','admin/upload_${1} id=$(1)') +; + +(new RequestDispatcher($r))->dispatch();
\ No newline at end of file diff --git a/htdocs/js/admin.js b/htdocs/js/admin.js new file mode 100644 index 0000000..a717d5c --- /dev/null +++ b/htdocs/js/admin.js @@ -0,0 +1,193 @@ +var LS = window.localStorage; + +var Draft = { + get: function() { + if (!LS) return null; + + var title = LS.getItem('draft_title') || null; + var text = LS.getItem('draft_text') || null; + + return { + title: title, + text: text + }; + }, + + setTitle: function(text) { + if (!LS) return null; + LS.setItem('draft_title', text); + }, + + setText: function(text) { + if (!LS) return null; + LS.setItem('draft_text', text); + }, + + reset: function() { + if (!LS) return; + LS.removeItem('draft_title'); + LS.removeItem('draft_text'); + } +}; + +var AdminWriteForm = { + form: null, + previewTimeout: null, + previewRequest: null, + + init: function(opts) { + opts = opts || {}; + + this.opts = opts; + this.form = document.forms[opts.pages ? 'pageForm' : 'postForm']; + this.isFixed = false; + + addEvent(this.form, 'submit', this.onSubmit); + if (!opts.pages) + addEvent(this.form.title, 'input', this.onInput); + + addEvent(this.form.text, 'input', this.onInput); + addEvent(ge('toggle_wrap'), 'click', this.onToggleWrapClick); + + if (this.form.text.value !== '') + this.showPreview(); + + // TODO make it more clever and context-aware + /*var draft = Draft.get(); + if (draft.title) + this.form.title.value = draft.title; + if (draft.text) + this.form.text.value = draft.text;*/ + + addEvent(window, 'scroll', this.onScroll); + addEvent(window, 'resize', this.onResize); + }, + + showPreview: function() { + if (this.previewRequest !== null) { + this.previewRequest.abort(); + } + this.previewRequest = ajax.post('/admin/markdown-preview.ajax', { + title: this.form.elements.title.value, + md: this.form.elements.text.value, + use_image_previews: this.opts.pages ? 1 : 0 + }, function(err, response) { + if (err) + return console.error(err); + ge('preview_html').innerHTML = response.html; + }); + }, + + onSubmit: function(event) { + try { + var fields = ['title', 'text']; + if (!this.opts.pages) + fields.push('tags'); + if (this.opts.edit) { + fields.push('new_short_name'); + } else { + fields.push('short_name'); + } + for (var i = 0; i < fields.length; i++) { + var field = fields[i]; + if (event.target.elements[field].value.trim() === '') + throw 'no_'+field + } + + // Draft.reset(); + } catch (e) { + var error = typeof e == 'string' ? lang((this.opts.pages ? 'err_pages_' : 'err_blog_')+e) : e.message; + alert(error); + console.error(e); + return cancelEvent(event); + } + }, + + onToggleWrapClick: function(e) { + var textarea = this.form.elements.text; + if (!hasClass(textarea, 'nowrap')) { + addClass(textarea, 'nowrap'); + } else { + removeClass(textarea, 'nowrap'); + } + return cancelEvent(e); + }, + + onInput: function(e) { + if (this.previewTimeout !== null) { + clearTimeout(this.previewTimeout); + } + this.previewTimeout = setTimeout(function() { + this.previewTimeout = null; + this.showPreview(); + + // Draft[e.target.name === 'title' ? 'setTitle' : 'setText'](e.target.value); + }.bind(this), 300); + }, + + onScroll: function() { + var ANCHOR_TOP = 10; + + var y = window.pageYOffset; + var form = this.form; + var td = ge('form_first_cell'); + var ph = ge('form_placeholder'); + + var rect = td.getBoundingClientRect(); + + if (rect.top <= ANCHOR_TOP && !this.isFixed) { + ph.style.height = form.getBoundingClientRect().height+'px'; + + var w = (rect.width - (parseInt(getComputedStyle(td).paddingRight, 10) || 0)); + form.style.display = 'block'; + form.style.width = w+'px'; + form.style.position = 'fixed'; + form.style.top = ANCHOR_TOP+'px'; + + this.isFixed = true; + } else if (rect.top > ANCHOR_TOP && this.isFixed) { + form.style.display = ''; + form.style.width = ''; + form.style.position = ''; + form.style.position = ''; + ph.style.height = ''; + + this.isFixed = false; + } + }, + + onResize: function() { + if (this.isFixed) { + var form = this.form; + var td = ge('form_first_cell'); + var ph = ge('form_placeholder'); + + var rect = td.getBoundingClientRect(); + var pr = parseInt(getComputedStyle(td).paddingRight, 10) || 0; + + ph.style.height = form.getBoundingClientRect().height+'px'; + form.style.width = (rect.width - pr) + 'px'; + } + } +}; +bindEventHandlers(AdminWriteForm); + +var BlogUploadList = { + submitNoteEdit: function(action, note) { + if (note === null) + return; + + var form = document.createElement('form'); + form.setAttribute('method', 'post'); + form.setAttribute('action', action); + + var input = document.createElement('input'); + input.setAttribute('type', 'hidden'); + input.setAttribute('name', 'note'); + input.setAttribute('value', note); + + form.appendChild(input); + document.body.appendChild(form); + form.submit(); + } +}; diff --git a/htdocs/js/common.js b/htdocs/js/common.js new file mode 100644 index 0000000..4e4199c --- /dev/null +++ b/htdocs/js/common.js @@ -0,0 +1,392 @@ +if (!String.prototype.startsWith) { + String.prototype.startsWith = function(search, pos) { + pos = !pos || pos < 0 ? 0 : +pos; + return this.substring(pos, pos + search.length) === search; + }; +} + +if (!String.prototype.endsWith) { + String.prototype.endsWith = function(search, this_len) { + if (this_len === undefined || this_len > this.length) { + this_len = this.length; + } + return this.substring(this_len - search.length, this_len) === search; + }; +} + +// +// AJAX +// +(function() { + + var defaultOpts = { + json: true + }; + + function createXMLHttpRequest() { + if (window.XMLHttpRequest) { + return new XMLHttpRequest(); + } + + var xhr; + try { + xhr = new ActiveXObject('Msxml2.XMLHTTP'); + } catch (e) { + try { + xhr = new ActiveXObject('Microsoft.XMLHTTP'); + } catch (e) {} + } + if (!xhr) { + console.error('Your browser doesn\'t support XMLHttpRequest.'); + } + return xhr; + } + + function request(method, url, data, optarg1, optarg2) { + data = data || null; + + var opts, callback; + if (optarg2 !== undefined) { + opts = optarg1; + callback = optarg2; + } else { + callback = optarg1; + } + + opts = opts || {}; + + if (typeof callback != 'function') { + throw new Error('callback must be a function'); + } + + if (!url) { + throw new Error('no url specified'); + } + + switch (method) { + case 'GET': + if (isObject(data)) { + for (var k in data) { + if (data.hasOwnProperty(k)) { + url += (url.indexOf('?') == -1 ? '?' : '&')+encodeURIComponent(k)+'='+encodeURIComponent(data[k]) + } + } + } + break; + + case 'POST': + if (isObject(data)) { + var sdata = []; + for (var k in data) { + if (data.hasOwnProperty(k)) { + sdata.push(encodeURIComponent(k)+'='+encodeURIComponent(data[k])); + } + } + data = sdata.join('&'); + } + break; + } + + opts = extend({}, defaultOpts, opts); + + var xhr = createXMLHttpRequest(); + xhr.open(method, url); + + xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest'); + if (method == 'POST') { + xhr.setRequestHeader('Content-type', 'application/x-www-form-urlencoded'); + } + + xhr.onreadystatechange = function() { + if (xhr.readyState == 4) { + if ('status' in xhr && !/^2|1223/.test(xhr.status)) { + throw new Error('http code '+xhr.status) + } + if (opts.json) { + var resp = JSON.parse(xhr.responseText) + if (!isObject(resp)) { + throw new Error('ajax: object expected') + } + if (resp.error) { + throw new Error(resp.error) + } + callback(null, resp.response); + } else { + callback(null, xhr.responseText); + } + } + }; + + xhr.onerror = function(e) { + callback(e); + }; + + xhr.send(method == 'GET' ? null : data); + + return xhr; + } + + window.ajax = { + get: request.bind(request, 'GET'), + post: request.bind(request, 'POST') + } + +})(); + +function bindEventHandlers(obj) { + for (var k in obj) { + if (obj.hasOwnProperty(k) + && typeof obj[k] == 'function' + && k.length > 2 + && k.startsWith('on') + && k[2].charCodeAt(0) >= 65 + && k[2].charCodeAt(0) <= 90) { + obj[k] = obj[k].bind(obj) + } + } +} + +// +// DOM helpers +// +function ge(id) { + return document.getElementById(id) +} + +function hasClass(el, name) { + return el && el.nodeType === 1 && (" " + el.className + " ").replace(/[\t\r\n\f]/g, " ").indexOf(" " + name + " ") >= 0 +} + +function addClass(el, name) { + if (!el) { + return console.warn('addClass: el is', el) + } + if (!hasClass(el, name)) { + el.className = (el.className ? el.className + ' ' : '') + name + } +} + +function removeClass(el, name) { + if (!el) { + return console.warn('removeClass: el is', el) + } + if (isArray(name)) { + for (var i = 0; i < name.length; i++) { + removeClass(el, name[i]); + } + return; + } + el.className = ((el.className || '').replace((new RegExp('(\\s|^)' + name + '(\\s|$)')), ' ')).trim() +} + +function addEvent(el, type, f, useCapture) { + if (!el) { + return console.warn('addEvent: el is', el, stackTrace()) + } + + if (isArray(type)) { + for (var i = 0; i < type.length; i++) { + addEvent(el, type[i], f, useCapture); + } + return; + } + + if (el.addEventListener) { + el.addEventListener(type, f, useCapture || false); + return true; + } else if (el.attachEvent) { + return el.attachEvent('on' + type, f); + } + + return false; +} + +function removeEvent(el, type, f, useCapture) { + if (isArray(type)) { + for (var i = 0; i < type.length; i++) { + var t = type[i]; + removeEvent(el, type[i], f, useCapture); + } + return; + } + + if (el.removeEventListener) { + el.removeEventListener(type, f, useCapture || false); + } else if (el.detachEvent) { + return el.detachEvent('on' + type, f); + } + + return false; +} + +function cancelEvent(evt) { + if (!evt) { + return console.warn('cancelEvent: event is', evt) + } + + if (evt.preventDefault) evt.preventDefault(); + if (evt.stopPropagation) evt.stopPropagation(); + + evt.cancelBubble = true; + evt.returnValue = false; + + return false; +} + + +// +// Cookies +// +function setCookie(name, value, days) { + var expires = ""; + if (days) { + var date = new Date(); + date.setTime(date.getTime() + (days*24*60*60*1000)); + expires = "; expires=" + date.toUTCString(); + } + document.cookie = name + "=" + (value || "") + expires + "; path=/"; +} + +function unsetCookie(name) { + document.cookie = name+'=; Max-Age=-99999999;'; +} + +function getCookie(name) { + var nameEQ = name + "="; + var ca = document.cookie.split(';'); + for (var i = 0; i < ca.length; i++) { + var c = ca[i]; + while (c.charAt(0) === ' ') + c = c.substring(1, c.length); + if (c.indexOf(nameEQ) === 0) + return c.substring(nameEQ.length, c.length); + } + return null; +} + +// +// Misc +// +function isObject(o) { + return Object.prototype.toString.call(o) === '[object Object]'; +} + +function isArray(a) { + return Object.prototype.toString.call(a) === '[object Array]'; +} + +function extend(dst, src) { + if (!isObject(dst)) { + return console.error('extend: dst is not an object'); + } + if (!isObject(src)) { + return console.error('extend: src is not an object'); + } + for (var key in src) { + dst[key] = src[key]; + } + return dst; +} + +function stackTrace(split) { + if (split === undefined) { + split = true; + } + try { + o.lo.lo += 0; + } catch(e) { + if (e.stack) { + var stack = split ? e.stack.split('\n') : e.stack; + stack.shift(); + stack.shift(); + return stack.join('\n'); + } + } + return null; +} + +function escape(str) { + var pre = document.createElement('pre'); + var text = document.createTextNode(str); + pre.appendChild(text); + return pre.innerHTML; +} + +// +// + +function lang(key) { + return __lang[key] !== undefined ? __lang[key] : '{'+key+'}'; +} + +var DynamicLogo = { + dynLink: null, + afr: null, + afrUrl: null, + + init: function() { + this.dynLink = ge('head_dyn_link'); + this.cdText = ge('head_cd_text'); + + if (!this.dynLink) { + return console.warn('DynamicLogo.init: !this.dynLink'); + } + + var spans = this.dynLink.querySelectorAll('span.head-logo-path'); + for (var i = 0; i < spans.length; i++) { + var span = spans[i]; + addEvent(span, 'mouseover', this.onSpanOver); + addEvent(span, 'mouseout', this.onSpanOut); + } + }, + + setUrl: function(url) { + if (this.afr !== null) { + cancelAnimationFrame(this.afr); + } + this.afrUrl = url; + this.afr = requestAnimationFrame(this.onAnimationFrame); + }, + + onAnimationFrame: function() { + var url = this.afrUrl; + + // update link + this.dynLink.setAttribute('href', url); + + // update console text + if (this.afrUrl === '/') { + url = '~'; + } else { + url = '~'+url.replace(/\/$/, ''); + } + this.cdText.innerHTML = escape(url); + + this.afr = null; + }, + + onSpanOver: function() { + var span = event.target; + this.setUrl(span.getAttribute('data-url')); + cancelEvent(event); + }, + + onSpanOut: function() { + var span = event.target; + this.setUrl('/'); + cancelEvent(event); + } +}; +bindEventHandlers(DynamicLogo); + +window.__lang = {}; + +// set/remove retina cookie +(function() { + var isRetina = window.devicePixelRatio >= 1.5; + if (isRetina) { + setCookie('is_retina', 1, 365); + } else { + unsetCookie('is_retina'); + } +})(); diff --git a/htdocs/openpgp-pubkey.txt b/htdocs/openpgp-pubkey.txt new file mode 100644 index 0000000..5a96ec0 --- /dev/null +++ b/htdocs/openpgp-pubkey.txt @@ -0,0 +1,51 @@ +-----BEGIN PGP PUBLIC KEY BLOCK----- + +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 +=cgca +-----END PGP PUBLIC KEY BLOCK----- diff --git a/htdocs/sass.php b/htdocs/sass.php new file mode 100644 index 0000000..eb24962 --- /dev/null +++ b/htdocs/sass.php @@ -0,0 +1,48 @@ +<?php + +require __DIR__.'/../init.php'; +global $config; + +$name = $_REQUEST['name'] ?? ''; +if (!$config['is_dev'] || !$name || !file_exists($path = ROOT.'/htdocs/scss/'.$name.'.scss')) { + // logError(__FILE__.': access denied'); + http_response_code(403); + exit; +} + +// logInfo(__FILE__.': continuing, path='.$path); + +$cmd = 'sassc -t expanded '.escapeshellarg($path); +$descriptorspec = [ + 0 => ['pipe', 'r'], // stdin + 1 => ['pipe', 'w'], // stdout + 2 => ['pipe', 'w'], // stderr +]; + +$process = proc_open($cmd, $descriptorspec, $pipes, ROOT); +if (!is_resource($process)) { + http_response_code(500); + logError('could not open sassc process'); + exit; +} + +$stdout = stream_get_contents($pipes[1]); +fclose($pipes[1]); + +$stderr = stream_get_contents($pipes[2]); +fclose($pipes[2]); + +$code = proc_close($process); +if ($code) { + http_response_code(500); + logError('sassc('.$path.') returned '.$code); + logError($stderr); + exit; +} + +header('Content-Type: text/css'); +header("Cache-Control: no-store, no-cache, must-revalidate, max-age=0"); +header("Cache-Control: post-check=0, pre-check=0", false); +header("Pragma: no-cache"); + +echo $stdout; diff --git a/htdocs/scss/admin.scss b/htdocs/scss/admin.scss new file mode 100644 index 0000000..06808d0 --- /dev/null +++ b/htdocs/scss/admin.scss @@ -0,0 +1,3 @@ +.admin-page { + line-height: 155%; +} diff --git a/htdocs/scss/blog.scss b/htdocs/scss/blog.scss new file mode 100644 index 0000000..7641683 --- /dev/null +++ b/htdocs/scss/blog.scss @@ -0,0 +1,383 @@ +@import 'vars'; + +.blog-write-link-wrap { + margin-bottom: $base-padding; +} +.blog-write-table { + table-layout: fixed; + border-collapse: collapse; + border: 0; + width: 100%; + + > tbody > tr > td { + text-align: left; + vertical-align: top; + } + > tbody > tr > td:first-child { + padding-right: 8px; + width: 45%; + } + > tbody > tr > td:last-child { + padding-left: 8px; + } +} + +.blog-write-form { + .form-field-input { + width: 100%; + } + textarea.form-field-input { + height: 400px; + font-family: $ffMono; + font-size: 12px; + } + textarea.form-field-input.nowrap { + white-space: pre; + overflow-wrap: normal; + } +} +.blog-write-options-table { + width: 100%; + border-collapse: collapse; + table-layout: fixed; + + td { + padding-top: 12px; + } + td:nth-child(1) { + width: 70%; + } + td:nth-child(2) { + width: 30%; + padding-left: 10px; + } + tr:first-child td { + padding-top: 0px; + } + button[type="submit"] { + margin-left: 3px; + } +} + +.blog-write-form-toggle-link { + margin-top: 3px; + display: inline-block; +} + +.blog-upload-form { + padding-bottom: $base-padding; +} + +.blog-upload-list {} +.blog-upload-item { + border-top: 1px $border-color solid; + padding: 10px 0; +} +.blog-upload-item-actions { + float: right; +} +.blog-upload-item-name { + font-weight: bold; + margin-bottom: 2px; +} +.blog-upload-item-info { + color: #888; + font-size: $fs - 2px; +} +.blog-upload-item-note { + padding: 0 0 4px; +} +.blog-upload-item-md { + margin-top: 3px; +} + +.blog-post-title { + margin: 0 0 16px; +} +.blog-post-title h1 { + font-size: 22px; + font-weight: bold; + padding: 0; + margin: 0; +} + +.blog-post-date { + color: #888; + margin-top: 5px; + font-size: $fs - 1px; + > a { + margin-left: 5px; + } +} + +.blog-post-tags { + margin-top: 16px; + margin-bottom: -1px; +} +.blog-post-tags > a { + display: block; + float: left; + font-size: $fs - 1px; + margin-right: 8px; + cursor: pointer; +} +.blog-post-tags > a:last-child { + margin-right: 0; +} +.blog-post-tags > a > span { + opacity: 0.5; +} + +.blog-post-text {} +.blog-post-text { + li { + margin: 13px 0; + } + + p { + margin-top: 13px; + margin-bottom: 13px; + } + p:first-child { + margin-top: 0; + } + p:last-child { + margin-bottom: 0; + } + + pre { + background-color: $code-block-bg; + font-family: $ffMono; + //font-size: $fsMono; + overflow: auto; + @include radius(3px); + } + + code { + background-color: $inline-code-block-bg; + font-family: $ffMono; + font-size: $fsMono; + padding: 3px 5px; + @include radius(3px); + } + + pre code { + display: block; + padding: 12px; + line-height: 145%; + background-color: $code-block-bg; + + span.term-prompt { + color: #999; + @include user-select(none); + } + } + + blockquote { + border-left: 3px #e0e0e0 solid; + margin-left: 0; + padding: 5px 0 5px 12px; + color: #888; + } + + table.table-100 { + border-collapse: collapse; + border: 0; + margin: 0; + width: 100%; + table-layout: fixed; + } + table.table-100 td { + padding: 0; + border: 0; + vertical-align: top; + text-align: left; + padding: 0 4px; + } + table.table-100 td:first-child { + padding-left: 0; + } + table.table-100 td:last-child { + padding-right: 0; + } + td > pre:first-child { + margin-top: 0; + } + td > pre:last-child { + margin-bottom: 0; + } + + h1 { + margin: 40px 0 16px; + font-weight: 600; + font-size: 30px; + border-bottom: 1px $border-color solid; + padding-bottom: 8px; + } + + h2 { + margin: 35px 0 16px; + font-weight: 500; + font-size: 25px; + border-bottom: 1px $border-color solid; + padding-bottom: 6px; + } + + h3 { + margin: 27px 0 16px; + font-size: 24px; + font-weight: 500; + } + + h4 { + font-size: 18px; + margin: 24px 0 16px; + } + + h5 { + font-size: 15px; + margin: 24px 0 16px; + } + + h6 { + font-size: 13px; + margin: 24px 0 16px; + color: #666; + } + + h3:first-child, + h4:first-child, + h5:first-child, + h6:first-child { + margin-top: 0; + } + h1:first-child, + h2:first-child { + margin-top: 5px; + } + + hr { + height: 1px; + border: 0; + background: $border-color; + margin: 17px 0; + } +} +.blog-post-comments { + margin-top: $base-padding; + padding: 12px 15px; + border: 1px #e0e0e0 solid; + @include radius(3px); +} +.blog-post-comments img { + vertical-align: middle; + position: relative; + top: -1px; + margin-left: 2px; +} + +$blog-tags-width: 175px; + +.index-blog-block { + margin-top: 23px; +} + +.blog-list {} +.blog-list.withtags { + margin-right: $blog-tags-width + $base-padding*2; +} +.blog-list-title { + font-size: 22px; + margin-bottom: 15px; + > span { + margin-left: 2px; + > a { + font-size: 16px; + margin-left: 2px; + } + } +} +.blog-list-table-wrap { + padding: 5px 0; +} +.blog-list-table { + border-collapse: collapse; +} +.blog-list-table td { + vertical-align: top; + padding: 0 0 13px; +} +.blog-list-table tr:last-child td { + padding-bottom: 0; +} +td.blog-item-date-cell { + width: 1px; + white-space: nowrap; + text-align: right; + padding-right: 10px; +} +.blog-item-date { + color: #777; + //text-transform: lowercase; +} +td.blog-item-title-cell { + text-align: left; +} +.blog-item-title { + //font-weight: bold; +} +.blog-item-row { + font-size: $fs; + line-height: 140%; +} +.blog-item-row.ishidden a.blog-item-title { + color: $fg; +} +.blog-item-row-year { + td { + padding-top: 10px; + text-align: right; + font-size: 20px; + letter-spacing: -0.5px; + } + &:first-child td { + padding-top: 0; + } +} +a.blog-item-view-all-link { + display: inline-block; + padding: 4px 17px; + @include radius(5px); + background-color: #f4f4f4; + color: #555; + margin-top: 2px; +} +a.blog-item-view-all-link:hover { + text-decoration: none; + background-color: #ededed; +} + + +.blog-tags { + float: right; + width: $blog-tags-width; + padding-left: $base-padding - 10px; + border-left: 1px $border-color solid; +} +.blog-tags-title { + margin-bottom: 15px; + font-size: 22px; + padding: 0 7px; +} +.blog-tag-item { + padding: 6px 10px; + font-size: $fs - 1px; +} +.blog-tag-item > a { + color: #222; +} +.blog-tag-item-count { + color: #aaa; + margin-left: 6px; + text-decoration: none !important; +} diff --git a/htdocs/scss/common-bundle.scss b/htdocs/scss/common-bundle.scss new file mode 100644 index 0000000..397f0c3 --- /dev/null +++ b/htdocs/scss/common-bundle.scss @@ -0,0 +1,9 @@ +@import "./common.scss"; +@import "./blog.scss"; +@import "./form.scss"; +@import "./hljs/github.scss"; +@import "./pages.scss"; + +@media screen and (max-width: 600px) { + @import "./mobile.scss"; +} diff --git a/htdocs/scss/common.scss b/htdocs/scss/common.scss new file mode 100644 index 0000000..644a080 --- /dev/null +++ b/htdocs/scss/common.scss @@ -0,0 +1,415 @@ +@import "vars"; + +.clearfix:after { + content: "."; + display: block; + clear: both; + visibility: hidden; + line-height: 0; + height: 0; +} + +html, body { + padding: 0; + margin: 0; + border: 0; + //background-color: $bg; + color: $fg; + height: 100%; + min-height: 100%; +} +body { + font-family: $ff; + font-size: $fs; +} + +.base-width { + max-width: $base-width; + margin: 0 auto; + position: relative; +} + +body.full-width .base-width { + max-width: 100%; + margin-left: auto; + margin-right: auto; +} + +input[type="text"], textarea { + -webkit-appearance: none; + -moz-appearance: none; + appearance: none; + box-sizing: border-box; + border: 1px $input-border solid; + border-radius: 0px; + background-color: $input-bg; + color: $fg; + font-family: $ff; + font-size: $fs; + padding: 6px; + outline: none; + @include radius(3px); +} +textarea { + resize: vertical; +} +input[type="text"]:focus, +textarea:focus { + border-color: $input-border-focused; +} +//input[type="checkbox"] { +// margin-left: 0; +//} + +//button { +// border-radius: 2px; +// background-color: $light-bg; +// color: $fg; +// padding: 7px 12px; +// border: none; +// /*box-shadow: 0 1px 4px rgba(0, 0, 0, 0.1);*/ +// font-family: $ff; +// font-size: $fs - 1px; +// outline: none; +// cursor: pointer; +// position: relative; +//} +//button:hover { +// box-shadow: 0 1px 9px rgba(0, 0, 0, 0.2); +//} +//button:active { +// top: 1px; +//} + +a { + text-decoration: none; + color: $link-color; + outline: none; +} +a:hover { + text-decoration: underline; +} + +p, p code { + line-height: 150%; +} + +.unicode { font-family: sans-serif; } + +.ff_ms { font-family: $ffMono } +.fl_r { float: right } +.fl_l { float: left } +.pos_rel { position: relative } +.pos_abs { position: absolute } +.pos_fxd { position: fixed } + +.page-content { + padding: 0 $side-padding; +} +.page-content-inner { + padding: $base-padding 0; +} + +.head { + padding: 0 $side-padding; +} +.head-inner { + //padding: 13px 0; + position: relative; + border-bottom: 2px $border-color solid; +} +.head-logo { + padding: 4px 0; + font-family: $ffMono; + font-size: 15px; + display: inline-block; + position: absolute; + left: 0; + background-color: transparent; + @include transition(background-color, 0.03s); +} +.head-logo { + padding: 16px 0; + background-color: #fff; +} +.head-logo:after { + content: ''; + display: block; + width: 40px; + position: absolute; + right: -40px; + top: 0; + bottom: 0; + border-left: 8px #fff solid; + box-sizing: border-box; + background: linear-gradient(to left, rgba(255, 255, 255, 0) 0%, rgba(255, 255, 255, 1) 100%); /* W3C */ +} +.head-logo > a { + color: $fg; + font-size: 14px; +} +.head-logo > a:hover { + text-decoration: none; +} +.head-logo-enter { + display: inline; + opacity: 0; + font-size: 11px; + position: relative; + background: #eee; + padding: 2px 5px; + color: #333; + font-weight: normal; + vertical-align: middle; + top: -1px; + @include transition(opacity, 0.03s); +} +.head-logo-enter-icon { + width: 12px; + height: 7px; + display: inline-block; + background: url(/img/enter.svg) 0 0 no-repeat; + background-size: 12px 7px; + margin-right: 5px; +} +.head-logo > a:hover .head-logo-enter { + opacity: 1; +} +.head-logo-path { + color: $fg; + font-weight: bold; + -webkit-font-smoothing: antialiased; + @include transition(color, 0.03s); +} +.head-logo > a:hover .head-logo-path:not(.alwayshover) { + color: #aaa; +} +.head-logo-path:not(.neverhover):hover { + color: #000 !important; +} +.head-logo-dolsign { + color: $head-green-color; + font-weight: normal; + &.is_root { + color: $head-red-color; + } +} +.head-logo-cd { + display: none; +} +.head-logo > a:hover .head-logo-cd { + display: inline; +} +.head-logo-path-mapped { + padding: 3px 5px; + background: #f1f1f1; + pointer-events: none; + @include radius(3px); + margin: 0 2px; +} + +.head-items { + float: right; + color: #777; // color of separators + //padding: 8px 0; +} +a.head-item { + color: $fg; + font-size: $fs - 1px; + display: block; + float: left; + padding: 16px 0; +} +a.head-item > span { + padding: 0 12px; + border-right: 1px #d0d0d0 solid; +} +a.head-item > span > span { + padding: 2px 0; +} +a.head-item:last-child > span { + border-right: 0; + padding-right: 1px; +} +/*a.head-item:first-child > span { + padding-left: 2px; +}*/ +a.head-item:hover { + //color: $link-color; + text-decoration: none; +} +a.head-item:hover > span > span { + border-bottom: 1px #d0d0d0 solid; +} + +table.contacts { + border: 0; + border-collapse: collapse; + margin: 8px auto 0; + //width: 100%; + //table-layout: fixed; +} +table.contacts td { + white-space: nowrap; + padding-bottom: 15px; + vertical-align: top; +} +table.contacts td.label { + text-align: right; + width: 30%; + color: #777; +} +table.contacts td.value { + text-align: left; + padding-left: 8px; +} +table.contacts td.value span { + background: #eee; + padding: 3px 7px 4px; + border-radius: 3px; + color: #333; + font-family: $ffMono; + font-size: $fs - 1px; +} +table.contacts td b { + font-weight: 600; +} +table.contacts td pre { + padding: 0; + margin: 0; + font-size: 12px; +} + +table.contacts div.note { + font-size: $fs - 3px; + padding-top: 2px; + color: #777; + > a { + color: #777; + border-bottom: 1px #ccc solid; + &:hover { + text-decoration: none; + border-bottom-color: #999; + } + } +} + +.pt { + margin: 5px 0 20px; + color: $dark-fg; + padding-bottom: 7px; + border-bottom: 2px rgba(255, 255, 255, 0.12) solid; +} +.pt h3 { + margin: 0; + display: inline-block; + font-weight: bold; + font-size: $fs; + color: $fg; +} +.pt h3:not(:first-child) { + margin-left: 5px; +} +.pt a { + margin-right: 5px; +} +.pt a:not(:first-child) { + margin-left: 5px; +} +.pt a, .pt h3 { + position: relative; + top: 1px; +} +.pt_r { margin-top: 5px } + +.empty { + text-align: center; + padding: 40px 20px; + color: $dark-fg; + @include radius(3px); + background-color: #f7f7f7; +} + +.contact-img { + display: inline-block; + width: 77px; + height: 12px; + background: transparent url(/img/contact.gif?1) no-repeat; + background-size: 77px 12px; +} +@media (-o-min-device-pixel-ratio:3/2), (-webkit-min-device-pixel-ratio:1.5), (min--moz-device-pixel-ratio:1.5), (min-resolution:1.5dppx) { +.contact-img { + background-image: url(/img/contact@2x.gif?1); +} +} + +.md-file-attach { + padding: 3px 0; +} +.md-file-attach-icon { + width: 14px; + height: 14px; + background: transparent url(/img/attachment.svg) no-repeat center center; + background-size: 14px 14px; + display: inline-block; + margin-right: 5px; + position: relative; + top: 1px; +} +.md-file-attach > a { + //font-weight: bold; +} +.md-file-attach-size { + color: #888; + margin-left: 2px; +} +.md-file-attach-note { + color: #000; + margin-left: 2px; +} + +.md-image { + padding: 3px 0; + line-height: 0; + max-width: 100%; +} +.md-images { + margin-bottom: -8px; + padding: 3px 0; + max-width: 100%; +} +.md-images .md-image { + padding-top: 0; + padding-bottom: 0; +} +.md-images > span { + display: block; + float: left; + margin: 0 8px 8px 0; + max-width: 100%; +} +.md-image.align-center { text-align: center; } +.md-image.align-left { text-align: left; } +.md-image.align-right { text-align: right; } +.md-image-wrap { + display: inline-block; + max-width: 100%; + overflow: hidden; +} +.md-image-wrap > a { + display: block; + max-width: 100%; +} +.md-image-note { + line-height: 150%; + color: #777; + padding: 2px 0 4px; +} + +.md-video video { + max-width: 100%; +} + +.language-ascii { + line-height: 125% !important; +} diff --git a/htdocs/scss/form.scss b/htdocs/scss/form.scss new file mode 100644 index 0000000..4faa4d1 --- /dev/null +++ b/htdocs/scss/form.scss @@ -0,0 +1,59 @@ +@import 'vars'; + +$form-field-label-width: 120px; + +form { display: block; margin: 0; } + +.form-layout-h { + .form-field-wrap { + padding: 8px 0; + } + .form-field-label { + float: left; + width: $form-field-label-width; + text-align: right; + padding: 7px 0 0; + } + .form-field { + margin-left: $form-field-label-width + 10px; + } +} + +.form-layout-v { + .form-field-wrap { + padding: 6px 0; + } + .form-field-wrap:first-child { + padding-top: 0; + } + .form-field-wrap:last-child { + padding-bottom: 0; + } + .form-field-label { + padding: 0 0 4px 4px; + font-weight: bold; + font-size: 12px; + letter-spacing: 0.5px; + text-transform: uppercase; + color: #888; + } + .form-field { + //margin-left: $form-field-label-width + 10px; + } +} + +.form-error { + padding: 10px 13px; + margin-bottom: $base-padding; + background-color: $error-block-bg; + color: $error-block-fg; + @include radius(3px); +} + +.form-success { + padding: 10px 13px; + margin-bottom: $base-padding; + background-color: $success-block-bg; + color: $success-block-fg; + @include radius(3px); +} diff --git a/htdocs/scss/hljs.scss b/htdocs/scss/hljs.scss new file mode 100644 index 0000000..36f52de --- /dev/null +++ b/htdocs/scss/hljs.scss @@ -0,0 +1 @@ +@import "./hljs/github.css"; diff --git a/htdocs/scss/hljs/github.scss b/htdocs/scss/hljs/github.scss new file mode 100644 index 0000000..791932b --- /dev/null +++ b/htdocs/scss/hljs/github.scss @@ -0,0 +1,99 @@ +/* + +github.com style (c) Vasily Polovnyov <vast@whiteants.net> + +*/ + +.hljs { + display: block; + overflow-x: auto; + padding: 0.5em; + color: #333; + background: #f8f8f8; +} + +.hljs-comment, +.hljs-quote { + color: #998; + font-style: italic; +} + +.hljs-keyword, +.hljs-selector-tag, +.hljs-subst { + color: #333; + font-weight: bold; +} + +.hljs-number, +.hljs-literal, +.hljs-variable, +.hljs-template-variable, +.hljs-tag .hljs-attr { + color: #008080; +} + +.hljs-string, +.hljs-doctag { + color: #d14; +} + +.hljs-title, +.hljs-section, +.hljs-selector-id { + color: #900; + font-weight: bold; +} + +.hljs-subst { + font-weight: normal; +} + +.hljs-type, +.hljs-class .hljs-title { + color: #458; + font-weight: bold; +} + +.hljs-tag, +.hljs-name, +.hljs-attribute { + color: #000080; + font-weight: normal; +} + +.hljs-regexp, +.hljs-link { + color: #009926; +} + +.hljs-symbol, +.hljs-bullet { + color: #990073; +} + +.hljs-built_in, +.hljs-builtin-name { + color: #0086b3; +} + +.hljs-meta { + color: #999; + font-weight: bold; +} + +.hljs-deletion { + background: #fdd; +} + +.hljs-addition { + background: #dfd; +} + +.hljs-emphasis { + font-style: italic; +} + +.hljs-strong { + font-weight: bold; +} diff --git a/htdocs/scss/mobile.scss b/htdocs/scss/mobile.scss new file mode 100644 index 0000000..d4d0d25 --- /dev/null +++ b/htdocs/scss/mobile.scss @@ -0,0 +1,41 @@ +@import 'vars'; + +textarea { + -webkit-overflow-scrolling: touch; +} + +// header +.head-logo { + position: static; + display: block; + //padding-bottom: 6px; + // not very good fix: + overflow: hidden; + white-space: nowrap; + padding-bottom: 0; +} +.head-logo::after { + display: none; +} +.head-items { + float: none; +} +a.head-item:hover, +a.head-item:active { + -webkit-tap-highlight-color: rgba(0, 0, 0, 0) !important; +} +a.head-item:last-child > span { + border-right: 0; + padding-right: 12px; +} +a.head-item:first-child > span { + padding-left: 1px; +} + +// blog +.blog-tags { + display: none; +} +.blog-list.withtags { + margin-right: 0; +} diff --git a/htdocs/scss/pages.scss b/htdocs/scss/pages.scss new file mode 100644 index 0000000..873a6ae --- /dev/null +++ b/htdocs/scss/pages.scss @@ -0,0 +1,14 @@ +.page { + +} +.page-edit-links { + display: none; + float: right; + font-size: 15px; + > a { + margin-left: 5px; + } +} +.page-content-inner:hover .page-edit-links { + display: block; +} diff --git a/htdocs/scss/vars.scss b/htdocs/scss/vars.scss new file mode 100644 index 0000000..e056740 --- /dev/null +++ b/htdocs/scss/vars.scss @@ -0,0 +1,71 @@ +$fs: 16px; +$fsMono: 85%; +$ff: -apple-system, BlinkMacSystemFont, Segoe UI, Helvetica, Arial, sans-serif; +$ffMono: SFMono-Regular, Consolas, Liberation Mono, Menlo, Courier, monospace; + +$base-width: 900px; +//$sb-width: 120px; +$side-padding: 25px; +$base-padding: 18px; + +$footer-height: 64px; +$head-green-color: #0bad19; +$head-red-color: #ce1a1a; +$link-color: #116fd4; + +$bg: #f7f7f7; +$content-bg: #fff; +$code-block-bg: #f3f3f3; +$inline-code-block-bg: #f1f1f1; + +$fg: #222; +$blue1: #729fcf; +$blue2: #3465a4; +$blue3: #204a87; +$orange1: #fcaf3e; +$orange2: #f57900; +$orange3: #ce5c00; + +$light-bg: #464c4e; +$dark-bg: #272C2D; +$dark-fg: #999; + +$input-border: #e0e0e0; +$input-border-focused: #e0e0e0; +$input-bg: #f7f7f7; +$border-color: #e0e0e0; + +$error-block-bg: #f9eeee; +$error-block-fg: #d13d3d; + +$success-block-bg: #eff5f0; +$success-block-fg: #2a6f34; + +@mixin radius($radius) { + -o-border-radius: $radius; + -ms-border-radius: $radius; + -moz-border-radius: $radius; + -webkit-border-radius: $radius; + border-radius: $radius; +} + +@mixin transition($property, $duration, $easing: linear) { + transition: $property $duration $easing; + -webkit-transition: $property $duration $easing; + -moz-transition: $property $duration $easing; +} + +@mixin linearGradient($top, $bottom){ + background: -moz-linear-gradient(top, $top 0%, $bottom 100%); /* FF3.6+ */ + background: -webkit-gradient(linear, left top, left bottom, color-stop(0%,$top), color-stop(100%,$bottom)); /* Chrome,Safari4+ */ + background: -webkit-linear-gradient(top, $top 0%,$bottom 100%); /* Chrome10+,Safari5.1+ */ + background: -o-linear-gradient(top, $top 0%,$bottom 100%); /* Opera 11.10+ */ + background: -ms-linear-gradient(top, $top 0%,$bottom 100%); /* IE10+ */ + background: linear-gradient(to bottom, $top 0%,$bottom 100%); /* W3C */ +} + +@mixin user-select($value) { + -moz-user-select: $value; + -webkit-user-select: $value; + user-select: $value; +} diff --git a/htdocs/yandex_3512181a57932602.html b/htdocs/yandex_3512181a57932602.html new file mode 100644 index 0000000..07384d2 --- /dev/null +++ b/htdocs/yandex_3512181a57932602.html @@ -0,0 +1,6 @@ +<html> + <head> + <meta http-equiv="Content-Type" content="text/html; charset=UTF-8"> + </head> + <body>Verification: 3512181a57932602</body> +</html> |