Compare commits

..

47 Commits

Author SHA1 Message Date
0e80f4e4d7
Updated styles build config
All checks were successful
Test / test (pull_request) Successful in 52s
Test / test (push) Successful in 59s
2024-09-18 00:41:02 +00:00
b9d8d5ca28
Fixed visited link 2024-09-18 00:38:54 +00:00
61e7f5d5b4
Refactor Footer and Header components, update layout styles, and adjust Analytics placement
All checks were successful
Test / test (push) Successful in 52s
Test / test (pull_request) Successful in 50s
2024-09-18 00:35:18 +00:00
9ff6f2cd0e
Added footer component 2024-09-17 23:24:24 +00:00
cf85f10724
Update launch configuration and enhance PostSummary component layout 2024-09-17 22:27:55 +00:00
43f80a7b6e
Update dependencies and add Cloudflare adapter in configuration
All checks were successful
Test / test (push) Successful in 51s
Test / test (pull_request) Successful in 48s
2024-09-17 21:33:49 +00:00
5217bcb24c
Refactor Pagination component to update page size in getStaticPaths
All checks were successful
Test / test (push) Successful in 39s
Test / test (pull_request) Successful in 36s
2024-09-13 00:26:08 +00:00
4a821edd50
Refactor Footer component and remove it from BaseLayout
All checks were successful
Test / test (push) Successful in 40s
Test / test (pull_request) Successful in 37s
2024-09-13 00:16:37 +00:00
d4a6772ec5
Refactor Footer component and add Analytics and Footer components to BaseLayout
All checks were successful
Test / test (push) Successful in 38s
Test / test (pull_request) Successful in 37s
2024-09-13 00:06:02 +00:00
b8fd186801
Refactor Analytics component to encode URI parameters
All checks were successful
Test / test (push) Successful in 39s
Test / test (pull_request) Successful in 37s
2024-09-12 23:33:43 +00:00
33c9464dad
Refactor Analytics and Head components 2024-09-12 22:57:55 +00:00
b16d8ce36c
Add Analytics component to BaseLayout 2024-09-12 22:42:08 +00:00
65ee69c645
Refactor Pagination component and add Next and Prev components 2024-09-12 22:38:34 +00:00
fd054f0fa4
Update config to use "advanced" preset for cssnano 2024-09-12 22:26:48 +00:00
de1885fe8f
Added Pagination component 2024-09-12 22:10:31 +00:00
3591bebabf
Sort blog posts by publication date 2024-09-12 21:02:35 +00:00
4ac7da1231
Refactor deployment workflow
All checks were successful
Test / test (push) Successful in 38s
Test / test (pull_request) Successful in 39s
2024-09-12 16:39:57 +00:00
a93400f090
Refactor Astro components and layouts 2024-09-12 16:39:06 +00:00
3376c53b2e
Refactor Astro components and layouts 2024-09-12 16:36:57 +00:00
0b57b888ca
Add PostPagination component for blog post navigation
Some checks failed
Test / test (push) Failing after 38s
Test / test (pull_request) Failing after 38s
2024-09-12 14:06:44 +00:00
4ba339984d
Updated the main page and page structures
All checks were successful
Test / test (push) Successful in 38s
Test / test (pull_request) Successful in 36s
2024-09-12 13:11:16 +00:00
70fa9c2033
Update postcss.config.cjs to include cssnano preset
All checks were successful
Test / test (push) Successful in 42s
Test / test (pull_request) Successful in 40s
2024-09-12 11:39:16 +00:00
c5affebc6f
Added global styles 2024-09-12 11:31:39 +00:00
dc6c24e56a
Update Comments component to include inline Giscus script
All checks were successful
Test / test (push) Successful in 38s
Test / test (pull_request) Successful in 35s
2024-09-11 22:17:56 +00:00
6494405a04
Remove blog link from header component 2024-09-11 22:06:08 +00:00
c89ed0f7f9
Update default title and description 2024-09-11 22:03:55 +00:00
97aa90a605
Add Renovate configuration files
All checks were successful
Test / test (push) Successful in 37s
Test / test (pull_request) Successful in 37s
2024-09-11 21:00:35 +00:00
d3034596b7
Update deploy workflow to include build step and testing Gitea Action
All checks were successful
Test / test (push) Successful in 35s
2024-09-11 20:25:20 +00:00
be3616d2d6
Update deploy workflow to include RenovateBot job 2024-09-11 20:10:22 +00:00
e2f0aecf95
Update deploy workflow to use rsync with --archive flag 2024-09-11 20:09:29 +00:00
af70075588
Update deploy workflow to use rsync with --delete-after flag
All checks were successful
Deploy / build (push) Successful in 43s
Deploy / deploy (push) Successful in 2s
2024-09-11 19:49:31 +00:00
97ba8666c8
Update deploy workflow to include rsync command for website deployment
Some checks failed
Deploy / build (push) Successful in 45s
Deploy / deploy (push) Failing after 3s
2024-09-11 19:46:19 +00:00
49c2ffa583
Update deploy workflow to include build step and testing Gitea Action
All checks were successful
Deploy / build (push) Successful in 46s
Deploy / deploy (push) Successful in 21s
2024-09-11 19:36:58 +00:00
1a67c77d9d
Update node version in deploy workflow
Some checks failed
Deploy / deploy (push) Failing after 1s
Deploy / build (push) Successful in 58s
2024-09-11 19:33:47 +00:00
2b8ddeda4f
Update actions/download-artifact version in deploy workflow
Some checks failed
Deploy / deploy (push) Failing after 15s
Deploy / build (push) Failing after 44s
2024-09-11 19:31:06 +00:00
b9f5d65559
Update node version in deploy workflow
Some checks failed
Deploy / deploy (push) Failing after 3s
Deploy / build (push) Failing after 45s
2024-09-11 19:26:51 +00:00
492d4965c8
Added build step
Some checks failed
Deploy / deploy (push) Failing after 14s
Deploy / build (push) Failing after 1m12s
2024-09-11 19:22:49 +00:00
396f3dcc30
Added testing Gitea Action
Some checks failed
Deploy / build_and_deploy (push) Failing after 24s
2024-09-11 19:14:15 +00:00
2a86fd34f6
Added comments 2024-09-06 08:36:02 +00:00
9829c0e5fa
Added title 2024-09-06 08:26:14 +00:00
6fbdcc94b6
Added author and datetime 2024-09-06 08:25:35 +00:00
2f362eaf09
Added reading time timer 2024-09-06 08:21:27 +00:00
17c3115a06
Added basic structure 2024-09-05 15:01:13 +00:00
7ba2de7148
Added sitemap 2024-09-05 14:55:42 +00:00
7770a0852c
Added RSS 2024-09-04 21:45:53 +00:00
536956f0f3
Added canonical URL 2024-09-04 21:23:21 +00:00
7eff3fde57
Initial Astro project 2024-09-04 21:16:37 +00:00
81 changed files with 11635 additions and 2154 deletions

View File

@ -1,14 +0,0 @@
FROM mcr.microsoft.com/devcontainers/base:bookworm
RUN apt-get update && apt-get install -y \
curl \
tar \
&& apt-get clean \
&& rm -rf /var/lib/apt/lists/*
ENV ZOLA_VERSION=0.19.1
RUN curl -L https://github.com/getzola/zola/releases/download/v${ZOLA_VERSION}/zola-v${ZOLA_VERSION}-x86_64-unknown-linux-gnu.tar.gz -o zola.tar.gz \
&& tar -xzf zola.tar.gz \
&& mv zola /bin/zola \
&& rm zola.tar.gz

View File

@ -1,15 +1,15 @@
{ {
"name": "Zola Dev Container", "image": "mcr.microsoft.com/devcontainers/javascript-node:22",
"build": { "forwardPorts": [4321],
"dockerfile": "Dockerfile"
},
"forwardPorts": [
1111
],
"portsAttributes": { "portsAttributes": {
"1111": { "4321": {
"label": "Application", "label": "Application",
"onAutoForward": "notify" "onAutoForward": "notify"
} }
},
"customizations": {
"vscode": {
"extensions": ["astro-build.astro-vscode", "esbenp.prettier-vscode"]
}
} }
} }

2
.env Normal file
View File

@ -0,0 +1,2 @@
DEFAULT_TITLE=Valentin Popovs Technology Blog
DEFAULT_DESCRIPTION=Tech insights and coding best practices from an OpenSource enthusiast and ethical hacker.

14
.gitea/workflows/main.yml Normal file
View File

@ -0,0 +1,14 @@
name: Test
on: [push, pull_request]
jobs:
test:
container: gitea/runner-images:ubuntu-latest
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- uses: actions/setup-node@v4
with:
node-version: 22
- run: npm ci
- run: npm run check

View File

@ -1,26 +1,16 @@
name: RenovateBot name: RenovateBot
on: on:
schedule: schedule:
- cron: "@daily" - cron: "@daily"
push:
branches:
- master
jobs: jobs:
renovate: renovate:
container: ghcr.io/renovatebot/renovate:37 container: ghcr.io/renovatebot/renovate:38
runs-on: ubuntu-latest runs-on: ubuntu-latest
steps: steps:
- name: Checkout code - uses: actions/checkout@v4
uses: actions/checkout@v4 - run: renovate
- name: Run renovate
run: |
renovate
env: env:
LOG_LEVEL: debug
RENOVATE_CONFIG_FILE: renovate.config.cjs RENOVATE_CONFIG_FILE: renovate.config.cjs
RENOVATE_REPOSITORIES: ${{ gitea.repository }} RENOVATE_REPOSITORIES: ${{ gitea.repository }}
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }} RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}

29
.gitignore vendored
View File

@ -1,5 +1,24 @@
_site # build output
.sass-cache dist/
.jekyll-cache # generated types
.jekyll-metadata .astro/
vendor
# dependencies
node_modules/
# logs
npm-debug.log*
yarn-debug.log*
yarn-error.log*
pnpm-debug.log*
# environment variables
.env
.env.production
# macOS-specific files
.DS_Store
# jetbrains setting folder
.idea/

44
.prettierrc.mjs Normal file
View File

@ -0,0 +1,44 @@
export default {
arrowParens: "always",
bracketSameLine: false,
bracketSpacing: true,
embeddedLanguageFormatting: "auto",
endOfLine: "lf",
htmlWhitespaceSensitivity: "ignore",
insertPragma: false,
jsxSingleQuote: false,
overrides: [
{
files: "*.astro",
options: {
parser: "astro",
},
},
{
files: "*.json",
options: {
tabWidth: 2,
useTabs: false,
},
},
{
files: "*.yml",
options: {
tabWidth: 2,
useTabs: false,
},
},
],
plugins: ["prettier-plugin-astro"],
printWidth: 120,
proseWrap: "never",
quoteProps: "consistent",
requirePragma: false,
semi: true,
singleAttributePerLine: false,
singleQuote: false,
tabWidth: 4,
trailingComma: "es5",
useTabs: true,
vueIndentScriptAndStyle: false,
};

View File

@ -1,24 +1,24 @@
{ {
"assignees": [ "assignees": [
"valentineus" "valentineus"
], ],
"extends": [ "extends": [
"config:recommended", "config:recommended",
":disableDependencyDashboard" ":disableDependencyDashboard"
], ],
"packageRules": [ "packageRules": [
{ {
"groupName": "all digest updates", "groupName": "all digest updates",
"groupSlug": "all-digest", "groupSlug": "all-digest",
"matchPackagePatterns": [ "matchPackagePatterns": [
"*" "*"
], ],
"matchUpdateTypes": [ "matchUpdateTypes": [
"minor", "minor",
"patch", "patch",
"pin", "pin",
"digest" "digest"
] ]
} }
] ]
} }

4
.vscode/extensions.json vendored Normal file
View File

@ -0,0 +1,4 @@
{
"recommendations": ["astro-build.astro-vscode"],
"unwantedRecommendations": []
}

11
.vscode/launch.json vendored Normal file
View File

@ -0,0 +1,11 @@
{
"version": "0.2.0",
"configurations": [
{
"command": "./node_modules/.bin/astro dev --host 0.0.0.0",
"name": "Development server",
"request": "launch",
"type": "node-terminal"
}
]
}

1
CNAME
View File

@ -1 +0,0 @@
popov.link

41
Gemfile
View File

@ -1,41 +0,0 @@
source "https://rubygems.org"
# Hello! This is where you manage which Jekyll version is used to run.
# When you want to use a different version, change it below, save the
# file and run `bundle install`. Run Jekyll with `bundle exec`, like so:
#
# bundle exec jekyll serve
#
# This will help ensure the proper Jekyll version is running.
# Happy Jekylling!
# If you want to use GitHub Pages, remove the "gem "jekyll"" above and
# uncomment the line below. To upgrade, run `bundle update github-pages`.
# gem "github-pages", group: :jekyll_plugins
gem "github-pages", "~> 231", group: :jekyll_plugins
# If you have any plugins, put them here!
group :jekyll_plugins do
gem "jekyll-feed", "~> 0.17"
gem "jekyll-sitemap", "~> 1.4"
end
# Windows and JRuby does not include zoneinfo files, so bundle the tzinfo-data gem
# and associated library.
platforms :mingw, :x64_mingw, :mswin, :jruby do
gem "tzinfo", ">= 1", "< 3"
gem "tzinfo-data"
end
# Performance-booster for watching directories on Windows
gem "wdm", "~> 0.1", :platforms => [:mingw, :x64_mingw, :mswin]
# Lock `http_parser.rb` gem to `v0.6.x` on JRuby builds since newer versions of the gem
# do not have a Java counterpart.
gem "http_parser.rb", "~> 0.6", :platforms => [:jruby]
# Starting with Ruby version 3.0.0, "webrick" is no longer included in the default
# set of Ruby libraries. This addition ensures compatibility with Ruby 3.0.0 and
# above by explicitly adding "webrick" to your dependencies, preventing potential
# errors when running the Jekyll server without webrick specified in the Gemfile.
gem "webrick", "~> 1.8"

View File

@ -1,297 +0,0 @@
GEM
remote: https://rubygems.org/
specs:
activesupport (7.1.3)
base64
bigdecimal
concurrent-ruby (~> 1.0, >= 1.0.2)
connection_pool (>= 2.2.5)
drb
i18n (>= 1.6, < 2)
minitest (>= 5.1)
mutex_m
tzinfo (~> 2.0)
addressable (2.8.6)
public_suffix (>= 2.0.2, < 6.0)
base64 (0.2.0)
bigdecimal (3.1.6)
coffee-script (2.4.1)
coffee-script-source
execjs
coffee-script-source (1.12.2)
colorator (1.1.0)
commonmarker (0.23.10)
concurrent-ruby (1.2.3)
connection_pool (2.4.1)
dnsruby (1.70.0)
simpleidn (~> 0.2.1)
drb (2.2.0)
ruby2_keywords
em-websocket (0.5.3)
eventmachine (>= 0.12.9)
http_parser.rb (~> 0)
ethon (0.16.0)
ffi (>= 1.15.0)
eventmachine (1.2.7)
execjs (2.9.1)
faraday (2.9.0)
faraday-net_http (>= 2.0, < 3.2)
faraday-net_http (3.1.0)
net-http
ffi (1.16.3)
forwardable-extended (2.6.0)
gemoji (4.1.0)
github-pages (230)
github-pages-health-check (= 1.18.2)
jekyll (= 3.9.5)
jekyll-avatar (= 0.8.0)
jekyll-coffeescript (= 1.2.2)
jekyll-commonmark-ghpages (= 0.4.0)
jekyll-default-layout (= 0.1.5)
jekyll-feed (= 0.17.0)
jekyll-gist (= 1.5.0)
jekyll-github-metadata (= 2.16.1)
jekyll-include-cache (= 0.2.1)
jekyll-mentions (= 1.6.0)
jekyll-optional-front-matter (= 0.3.2)
jekyll-paginate (= 1.1.0)
jekyll-readme-index (= 0.3.0)
jekyll-redirect-from (= 0.16.0)
jekyll-relative-links (= 0.7.0)
jekyll-remote-theme (= 0.4.3)
jekyll-sass-converter (= 1.5.2)
jekyll-seo-tag (= 2.8.0)
jekyll-sitemap (= 1.4.0)
jekyll-swiss (= 1.0.0)
jekyll-theme-architect (= 0.2.0)
jekyll-theme-cayman (= 0.2.0)
jekyll-theme-dinky (= 0.2.0)
jekyll-theme-hacker (= 0.2.0)
jekyll-theme-leap-day (= 0.2.0)
jekyll-theme-merlot (= 0.2.0)
jekyll-theme-midnight (= 0.2.0)
jekyll-theme-minimal (= 0.2.0)
jekyll-theme-modernist (= 0.2.0)
jekyll-theme-primer (= 0.6.0)
jekyll-theme-slate (= 0.2.0)
jekyll-theme-tactile (= 0.2.0)
jekyll-theme-time-machine (= 0.2.0)
jekyll-titles-from-headings (= 0.5.3)
jemoji (= 0.13.0)
kramdown (= 2.4.0)
kramdown-parser-gfm (= 1.1.0)
liquid (= 4.0.4)
mercenary (~> 0.3)
minima (= 2.5.1)
nokogiri (>= 1.13.6, < 2.0)
rouge (= 3.30.0)
terminal-table (~> 1.4)
github-pages-health-check (1.18.2)
addressable (~> 2.3)
dnsruby (~> 1.60)
octokit (>= 4, < 8)
public_suffix (>= 3.0, < 6.0)
typhoeus (~> 1.3)
html-pipeline (2.14.3)
activesupport (>= 2)
nokogiri (>= 1.4)
http_parser.rb (0.8.0)
i18n (1.14.1)
concurrent-ruby (~> 1.0)
jekyll (3.9.5)
addressable (~> 2.4)
colorator (~> 1.0)
em-websocket (~> 0.5)
i18n (>= 0.7, < 2)
jekyll-sass-converter (~> 1.0)
jekyll-watch (~> 2.0)
kramdown (>= 1.17, < 3)
liquid (~> 4.0)
mercenary (~> 0.3.3)
pathutil (~> 0.9)
rouge (>= 1.7, < 4)
safe_yaml (~> 1.0)
jekyll-avatar (0.8.0)
jekyll (>= 3.0, < 5.0)
jekyll-coffeescript (1.2.2)
coffee-script (~> 2.2)
coffee-script-source (~> 1.12)
jekyll-commonmark (1.4.0)
commonmarker (~> 0.22)
jekyll-commonmark-ghpages (0.4.0)
commonmarker (~> 0.23.7)
jekyll (~> 3.9.0)
jekyll-commonmark (~> 1.4.0)
rouge (>= 2.0, < 5.0)
jekyll-default-layout (0.1.5)
jekyll (>= 3.0, < 5.0)
jekyll-feed (0.17.0)
jekyll (>= 3.7, < 5.0)
jekyll-gist (1.5.0)
octokit (~> 4.2)
jekyll-github-metadata (2.16.1)
jekyll (>= 3.4, < 5.0)
octokit (>= 4, < 7, != 4.4.0)
jekyll-include-cache (0.2.1)
jekyll (>= 3.7, < 5.0)
jekyll-mentions (1.6.0)
html-pipeline (~> 2.3)
jekyll (>= 3.7, < 5.0)
jekyll-optional-front-matter (0.3.2)
jekyll (>= 3.0, < 5.0)
jekyll-paginate (1.1.0)
jekyll-readme-index (0.3.0)
jekyll (>= 3.0, < 5.0)
jekyll-redirect-from (0.16.0)
jekyll (>= 3.3, < 5.0)
jekyll-relative-links (0.7.0)
jekyll (>= 3.3, < 5.0)
jekyll-remote-theme (0.4.3)
addressable (~> 2.0)
jekyll (>= 3.5, < 5.0)
jekyll-sass-converter (>= 1.0, <= 3.0.0, != 2.0.0)
rubyzip (>= 1.3.0, < 3.0)
jekyll-sass-converter (1.5.2)
sass (~> 3.4)
jekyll-seo-tag (2.8.0)
jekyll (>= 3.8, < 5.0)
jekyll-sitemap (1.4.0)
jekyll (>= 3.7, < 5.0)
jekyll-swiss (1.0.0)
jekyll-theme-architect (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-cayman (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-dinky (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-hacker (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-leap-day (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-merlot (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-midnight (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-minimal (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-modernist (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-primer (0.6.0)
jekyll (> 3.5, < 5.0)
jekyll-github-metadata (~> 2.9)
jekyll-seo-tag (~> 2.0)
jekyll-theme-slate (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-tactile (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-theme-time-machine (0.2.0)
jekyll (> 3.5, < 5.0)
jekyll-seo-tag (~> 2.0)
jekyll-titles-from-headings (0.5.3)
jekyll (>= 3.3, < 5.0)
jekyll-watch (2.2.1)
listen (~> 3.0)
jemoji (0.13.0)
gemoji (>= 3, < 5)
html-pipeline (~> 2.2)
jekyll (>= 3.0, < 5.0)
kramdown (2.4.0)
rexml
kramdown-parser-gfm (1.1.0)
kramdown (~> 2.0)
liquid (4.0.4)
listen (3.8.0)
rb-fsevent (~> 0.10, >= 0.10.3)
rb-inotify (~> 0.9, >= 0.9.10)
mercenary (0.3.6)
minima (2.5.1)
jekyll (>= 3.5, < 5.0)
jekyll-feed (~> 0.9)
jekyll-seo-tag (~> 2.1)
minitest (5.22.2)
mutex_m (0.2.0)
net-http (0.4.1)
uri
nokogiri (1.16.5-aarch64-linux)
racc (~> 1.4)
nokogiri (1.16.5-arm-linux)
racc (~> 1.4)
nokogiri (1.16.5-arm64-darwin)
racc (~> 1.4)
nokogiri (1.16.5-x86-linux)
racc (~> 1.4)
nokogiri (1.16.5-x86_64-darwin)
racc (~> 1.4)
nokogiri (1.16.5-x86_64-linux)
racc (~> 1.4)
octokit (4.25.1)
faraday (>= 1, < 3)
sawyer (~> 0.9)
pathutil (0.16.2)
forwardable-extended (~> 2.6)
public_suffix (5.0.4)
racc (1.7.3)
rb-fsevent (0.11.2)
rb-inotify (0.10.1)
ffi (~> 1.0)
rexml (3.2.8)
strscan (>= 3.0.9)
rouge (3.30.0)
ruby2_keywords (0.0.5)
rubyzip (2.3.2)
safe_yaml (1.0.5)
sass (3.7.4)
sass-listen (~> 4.0.0)
sass-listen (4.0.0)
rb-fsevent (~> 0.9, >= 0.9.4)
rb-inotify (~> 0.9, >= 0.9.7)
sawyer (0.9.2)
addressable (>= 2.3.5)
faraday (>= 0.17.3, < 3)
simpleidn (0.2.1)
unf (~> 0.1.4)
strscan (3.1.0)
terminal-table (1.8.0)
unicode-display_width (~> 1.1, >= 1.1.1)
typhoeus (1.4.1)
ethon (>= 0.9.0)
tzinfo (2.0.6)
concurrent-ruby (~> 1.0)
unf (0.1.4)
unf_ext
unf_ext (0.0.9.1)
unicode-display_width (1.8.0)
uri (0.13.0)
webrick (1.8.1)
PLATFORMS
aarch64-linux
arm-linux
arm64-darwin
x86-linux
x86_64-darwin
x86_64-linux
DEPENDENCIES
github-pages (~> 230)
http_parser.rb (~> 0.6)
jekyll-feed (~> 0.17)
jekyll-sitemap (~> 1.4)
tzinfo (>= 1, < 3)
tzinfo-data
wdm (~> 0.1)
webrick (~> 1.8)
BUNDLED WITH
2.5.6

View File

@ -1,7 +0,0 @@
Copyright 2017, 2018 Valentin Popov
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

View File

@ -1,22 +1,16 @@
# Personal site # Personal site
This is my main site. This is my main site. The site publishes articles, useful information and notes. Also, the site serves as a hosting of free and personal images.
The site publishes articles, useful information and notes.
Also, the site serves as a hosting of free and personal images.
Principles of site development: Principles of site development:
* Lightness and minimalism. - Lightness and minimalism. The site is designed to store information, it's not a heavy application;
The site is designed to store information, it's not a heavy application;
* Maximum cross-platform. - Maximum cross-platform. Information should be read from any device and software;
Information should be read from any device and software;
* Focusing on content perception. - Focusing on content perception. Only useful information, nothing superfluous;
Only useful information, nothing superfluous;
* No JS on the site. - No JS on the site. The site should be completely safe for the user;
The site should be completely safe for the user;
## Development ## Development
@ -52,6 +46,4 @@ Material on the site is published on the CC BY-NC 3.0 license.
<img width="256px" alt="MIT License" src="https://raw.githubusercontent.com/valentineus/valentineus.github.io/master/assets/images/7d05cad0-d553-42c7-be1f-7007926ba720.png" /> <img width="256px" alt="MIT License" src="https://raw.githubusercontent.com/valentineus/valentineus.github.io/master/assets/images/7d05cad0-d553-42c7-be1f-7007926ba720.png" />
[MIT](LICENSE.txt). [MIT](LICENSE.txt). Copyright (c) [Valentin Popov](https://valentineus.link/).
Copyright (c)
[Valentin Popov](https://valentineus.link/).

View File

@ -1,58 +0,0 @@
# Permalinks
permalink: /blog/:title/
# Time Zone
timezone: Europe/Moscow
# Catalogs
include:
- _pages
# Parsers
highlighter: rouge
markdown: kramdown
# Markdown
kramdown:
input: GFM
hard_wrap: false
syntax_highlighter: rouge
# SASS/SCSS
sass:
sass_dir: _scss
sourcemap: never
style: :compressed
# Compress HTML
compress_html:
blanklines: false
clippings: all
comments: ["<!-- ", " -->"]
endings: all
profile: false
startings: []
# Website address
url: "https://popov.link"
baseurl: ""
# Site description
title: Valentin Popov's Technology Blog
description: Tech insights and coding best practices from an OpenSource enthusiast and ethical hacker.
email: valentin@popov.link
rss: /feed.xml
lang: ru
# Plugins
plugins:
- jekyll-feed
- jekyll-sitemap
# Exceptions
exclude:
- .*
- Gemfile
- Gemfile.lock
- LICENSE.txt
- README.md

View File

@ -1,7 +0,0 @@
adrianhenke:
name: Adrian Henke
email: ""
valentineus:
name: Valentin Popov
email: valentin@popov.link

View File

@ -1,5 +0,0 @@
- title: "Home"
path: "/"
- title: "Blog"
path: "/blog/"

View File

@ -1,166 +0,0 @@
---
description: "Howdy! This is an example blog post that shows several types of HTML content supported in this theme."
title: "Example Content"
layout: post
---
Cum sociis natoque penatibus et magnis <a href="#">dis parturient montes</a>, nascetur ridiculus mus.
*Aenean eu leo quam.*
Pellentesque ornare sem lacinia quam venenatis vestibulum.
Sed posuere consectetur est at lobortis.
Cras mattis consectetur purus sit amet fermentum.
> Curabitur blandit tempus porttitor.
Nullam quis risus eget urna mollis ornare vel eu leo.
Nullam id dolor id nibh ultricies vehicula ut id elit.
Etiam porta **sem malesuada magna** mollis euismod.
Cras mattis consectetur purus sit amet fermentum.
Aenean lacinia bibendum nulla sed consectetur.
## Inline HTML elements
HTML defines a long list of available inline tags, a complete list of which can be found on the
[Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
- **To bold text**, use `<strong>`.
- *To italicize text*, use `<em>`.
- Abbreviations, like <abbr title="HyperText Markup Langage">HTML</abbr> should use `<abbr>`, with an optional `title` attribute for the full phrase.
- Citations, like <cite>&mdash; Mark otto</cite>, should use `<cite>`.
- <del>Deleted</del> text should use `<del>` and <ins>inserted</ins> text should use `<ins>`.
- Superscript <sup>text</sup> uses `<sup>` and subscript <sub>text</sub> uses `<sub>`.
Most of these elements are styled by browsers with few modifications on our part.
## Heading
Vivamus sagittis lacus vel augue rutrum faucibus dolor auctor.
Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
### Code
Cum sociis natoque penatibus et magnis dis `code element` montes, nascetur ridiculus mus.
```js
// Example can be run directly in your JavaScript console
// Create a function that takes two arguments and returns the sum of those arguments
var adder = new Function("a", "b", "return a + b");
// Call the function
adder(2, 6);
// > 8
```
Aenean lacinia bibendum nulla sed consectetur.
Etiam porta sem malesuada magna mollis euismod.
Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.
### Gists via GitHub Pages
Vestibulum id ligula porta felis euismod semper.
Nullam quis risus eget urna mollis ornare vel eu leo.
Donec sed odio dui.
{% gist 5555251 gist.md %}
Aenean eu leo quam.
Pellentesque ornare sem lacinia quam venenatis vestibulum.
Nullam quis risus eget urna mollis ornare vel eu leo.
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Donec sed odio dui.
Vestibulum id ligula porta felis euismod semper.
### Lists
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
Aenean lacinia bibendum nulla sed consectetur.
Etiam porta sem malesuada magna mollis euismod.
Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
* Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
* Donec id elit non mi porta gravida at eget metus.
* Nulla vitae elit libero, a pharetra augue.
Donec ullamcorper nulla non metus auctor fringilla.
Nulla vitae elit libero, a pharetra augue.
1. Vestibulum id ligula porta felis euismod semper.
2. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
3. Maecenas sed diam eget risus varius blandit sit amet non magna.
Cras mattis consectetur purus sit amet fermentum.
Sed posuere consectetur est at lobortis.
<dl>
<dt>HyperText Markup Language (HTML)</dt>
<dd>The language used to describe and define the content of a Web page</dd>
<dt>Cascading Style Sheets (CSS)</dt>
<dd>Used to describe the appearance of Web content</dd>
<dt>JavaScript (JS)</dt>
<dd>The programming language used to build advanced Web sites and applications</dd>
</dl>
Integer posuere erat a ante venenatis dapibus posuere velit aliquet.
Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
Nullam quis risus eget urna mollis ornare vel eu leo.
### Images
Quisque consequat sapien eget quam rhoncus, sit amet laoreet diam tempus.
Aliquam aliquam metus erat, a pulvinar turpis suscipit at.
![placeholder](http://placehold.it/800x400 "Large example image")
![placeholder](http://placehold.it/400x200 "Medium example image")
![placeholder](http://placehold.it/200x200 "Small example image")
### Tables
Aenean lacinia bibendum nulla sed consectetur.
Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Upvotes</th>
<th>Downvotes</th>
</tr>
</thead>
<tfoot>
<tr>
<td>Totals</td>
<td>21</td>
<td>23</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Alice</td>
<td>10</td>
<td>11</td>
</tr>
<tr>
<td>Bob</td>
<td>4</td>
<td>3</td>
</tr>
<tr>
<td>Charlie</td>
<td>7</td>
<td>9</td>
</tr>
</tbody>
</table>
Nullam id dolor id nibh ultricies vehicula ut id elit.
Sed posuere consectetur est at lobortis.
Nullam quis risus eget urna mollis ornare vel eu leo.
-----
Want to see something else added?
<a href="https://github.com/poole/poole/issues/new">Open an issue.</a>

View File

@ -1,17 +0,0 @@
{%- assign author = site.data.authors[page.author] -%}
{%- if author -%}
&nbsp;by&nbsp;
{%- unless author.email == empty -%}
<a href="mailto:{{- author.email | strip | url_encode -}}?subject={{- page.title | default: site.title | strip | normalize_whitespace | uri_escape -}}">{{- author.name | strip | normalize_whitespace | xml_escape -}}</a>
{%- endunless -%}
{%- if author.email == empty -%}
{{- author.name | strip | normalize_whitespace | xml_escape -}}
{%- endif -%}
{%- endif -%}
&nbsp;

View File

@ -1 +0,0 @@
<script defer src="https://giscus.app/client.js" data-repo="valentineus/valentineus.github.io" data-repo-id="R_kgDOJfmscg" data-category="Announcements" data-category-id="DIC_kwDOJfmscs4CdNE6" data-mapping="title" data-strict="1" data-reactions-enabled="1" data-emit-metadata="0" data-input-position="bottom" data-theme="transparent_dark" data-lang="en" crossorigin="anonymous"></script>

View File

@ -1,8 +0,0 @@
<!-- AppMetrix Web Analytics -->
<script defer src="https://appmetrix.com/pixel/T5X0z12SoASBV8Dv"></script>
<!-- GoatCounter Analytics -->
<script defer data-goatcounter="https://analytics.popov.link/count" src="/assets/javascript/count.js"></script>
<noscript>
<img src="https://analytics.popov.link/count?p={{- page.url | relative_url | url_escape -}}&t={{- page.title | default: site.title | strip | normalize_whitespace | url_encode -}}" alt="pixel">
</noscript>

View File

@ -1,25 +0,0 @@
<head>
<!-- Meta tags -->
<meta content="IE=edge" http-equiv="X-UA-Compatible">
<meta content="text/html; charset=utf-8" http-equiv="content-type">
<meta content="width=device-width, initial-scale=1" name="viewport">
<meta content="index, follow" name="robots">
<!-- Title / Description -->
<meta content="{{- page.description | default: site.description | strip | normalize_whitespace | xml_escape -}}" name="description">
<title>{{- page.title | default: site.title | strip | normalize_whitespace | xml_escape -}}</title>
<!-- RSS -->
<link href="{{- site.rss | absolute_url | url_escape -}}" rel="alternate" title="RSS" type="application/atom+xml">
<!-- Canonical URL -->
<link href="{{- page.url | absolute_url | url_escape | replace: 'index.html', '' -}}" rel="canonical">
<!-- CSS -->
{%- include styles.html -%}
<!--[if lte IE 9]>
<script type="text/javascript" src="{{- '/assets/javascript/html5shiv-3.7.3.min.js' | relative_url | url_escape -}}"></script>
<script type="text/javascript" src="{{- '/assets/javascript/respond-1.4.2.min.js' | relative_url | url_escape -}}"></script>
<![endif]-->
</head>

View File

@ -1,6 +0,0 @@
<nav>
{%- for link in site.data.navbar -%}
<a href="{{- link.path | relative_url | url_escape -}}">{{- link.title | strip | normalize_whitespace | xml_escape -}}</a>
{%- endfor -%}
<span><span>|</span><a href="{{- site.rss | absolute_url | url_escape -}}">RSS</a></span>
</nav>

View File

@ -1,11 +0,0 @@
{%- capture words -%}
{{- content | number_of_words | minus: 180 -}}
{%- endcapture -%}
{%- if words contains '-' -%}
{{- '1 min read' | strip | normalize_whitespace | xml_escape -}}
{%- endif -%}
{%- unless words contains '-' -%}
{{- words | plus: 150 | divided_by: 150 | append: ' min read' | strip | normalize_whitespace | xml_escape -}}
{%- endunless -%}

View File

@ -1,5 +0,0 @@
{%- capture styles -%}
{%- include styles.scss -%}
{%- endcapture -%}
<style>{{- styles | scssify -}}</style>

View File

@ -1,10 +0,0 @@
// Base
@import "reset";
@import "variables";
@import "framework";
@import "print";
// Modules
@import "highlighter";
@import "navbar";
@import "welcome";

View File

@ -1,6 +0,0 @@
---
layout: null
---
{% capture _LINE_FEED %}
{% endcapture %}{% if site.compress_html.ignore.envs contains jekyll.environment or site.compress_html.ignore.envs == "all" %}{{ content }}{% else %}{% capture _content %}{{ content }}{% endcapture %}{% assign _profile = site.compress_html.profile %}{% if site.compress_html.endings == "all" %}{% assign _endings = "html head body li dt dd optgroup option colgroup caption thead tbody tfoot tr td th" | split: " " %}{% else %}{% assign _endings = site.compress_html.endings %}{% endif %}{% for _element in _endings %}{% capture _end %}</{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _end %}{% endfor %}{% if _profile and _endings %}{% assign _profile_endings = _content | size | plus: 1 %}{% endif %}{% for _element in site.compress_html.startings %}{% capture _start %}<{{ _element }}>{% endcapture %}{% assign _content = _content | remove: _start %}{% endfor %}{% if _profile and site.compress_html.startings %}{% assign _profile_startings = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.comments == "all" %}{% assign _comments = "<!-- -->" | split: " " %}{% else %}{% assign _comments = site.compress_html.comments %}{% endif %}{% if _comments.size == 2 %}{% capture _comment_befores %}.{{ _content }}{% endcapture %}{% assign _comment_befores = _comment_befores | split: _comments.first %}{% for _comment_before in _comment_befores %}{% if forloop.first %}{% continue %}{% endif %}{% capture _comment_outside %}{% if _carry %}{{ _comments.first }}{% endif %}{{ _comment_before }}{% endcapture %}{% capture _comment %}{% unless _carry %}{{ _comments.first }}{% endunless %}{{ _comment_outside | split: _comments.last | first }}{% if _comment_outside contains _comments.last %}{{ _comments.last }}{% assign _carry = false %}{% else %}{% assign _carry = true %}{% endif %}{% endcapture %}{% assign _content = _content | remove_first: _comment %}{% endfor %}{% if _profile %}{% assign _profile_comments = _content | size | plus: 1 %}{% endif %}{% endif %}{% assign _pre_befores = _content | split: "<pre" %}{% assign _content = "" %}{% for _pre_before in _pre_befores %}{% assign _pres = _pre_before | split: "</pre>" %}{% assign _pres_after = "" %}{% if _pres.size != 0 %}{% if site.compress_html.blanklines %}{% assign _lines = _pres.last | split: _LINE_FEED %}{% capture _pres_after %}{% for _line in _lines %}{% assign _trimmed = _line | split: " " | join: " " %}{% if _trimmed != empty or forloop.last %}{% unless forloop.first %}{{ _LINE_FEED }}{% endunless %}{{ _line }}{% endif %}{% endfor %}{% endcapture %}{% else %}{% assign _pres_after = _pres.last | split: " " | join: " " %}{% endif %}{% endif %}{% capture _content %}{{ _content }}{% if _pre_before contains "</pre>" %}<pre{{ _pres.first }}</pre>{% endif %}{% unless _pre_before contains "</pre>" and _pres.size == 1 %}{{ _pres_after }}{% endunless %}{% endcapture %}{% endfor %}{% if _profile %}{% assign _profile_collapse = _content | size | plus: 1 %}{% endif %}{% if site.compress_html.clippings == "all" %}{% assign _clippings = "html head title base link meta style body article section nav aside h1 h2 h3 h4 h5 h6 hgroup header footer address p hr blockquote ol ul li dl dt dd figure figcaption main div table caption colgroup col tbody thead tfoot tr td th" | split: " " %}{% else %}{% assign _clippings = site.compress_html.clippings %}{% endif %}{% for _element in _clippings %}{% assign _edges = " <e;<e; </e>;</e>;</e> ;</e>" | replace: "e", _element | split: ";" %}{% assign _content = _content | replace: _edges[0], _edges[1] | replace: _edges[2], _edges[3] | replace: _edges[4], _edges[5] %}{% endfor %}{% if _profile and _clippings %}{% assign _profile_clippings = _content | size | plus: 1 %}{% endif %}{{ _content }}{% if _profile %} <table id="compress_html_profile_{{ site.time | date: "%Y%m%d" }}" class="compress_html_profile"> <thead> <tr> <td>Step <td>Bytes <tbody> <tr> <td>raw <td>{{ content | size }}{% if _profile_endings %} <tr> <td>endings <td>{{ _profile_endings }}{% endif %}{% if _profile_startings %} <tr> <td>startings <td>{{ _profile_startings }}{% endif %}{% if _profile_comments %} <tr> <td>comments <td>{{ _profile_comments }}{% endif %}{% if _profile_collapse %} <tr> <td>collapse <td>{{ _profile_collapse }}{% endif %}{% if _profile_clippings %} <tr> <td>clippings <td>{{ _profile_clippings }}{% endif %} </table>{% endif %}{% endif %}

View File

@ -1,22 +0,0 @@
---
layout: compress
---
<!DOCTYPE html>
<html lang="{{- site.lang | strip | slugify | xml_escape -}}">
{%- include head.html -%}
<body>
<header>
{%- include navbar.html -%}
</header>
<article>
{{- content -}}
</article>
{%- include counter.html -%}
</body>
</html>

View File

@ -1,5 +0,0 @@
---
layout: default
---
{{- content -}}

View File

@ -1,21 +0,0 @@
---
layout: default
---
<div style="text-align: center;">
<h1>{{- page.title | default: site.title | strip | normalize_whitespace | xml_escape -}}</h1>
<p>
<small>
Posted
<time datetime="{{- page.date | date_to_xmlschema | xml_escape -}}">{{- page.date | date: '%B %e, %Y' | strip | normalize_whitespace | xml_escape -}}</time>
{%- include author.html -%}
&hyphen;
<strong>{%- include reading-time.html -%}</strong>
</small>
</p>
</div>
{{- content -}}
{%- include comments.html -%}

View File

@ -1,10 +0,0 @@
---
layout: page
permalink: /404.html
---
<div style="text-align:center;">
<h1>404</h1>
<p><strong>Page not found.</strong></p>
<p><small>If you see this message, please <a href="mailto:{{- site.email | strip | url_encode -}}?subject={{- 'I found a broken page' | strip | normalize_whitespace | uri_escape -}}">let me know</a>.</small></p>
</div>

View File

@ -1,16 +0,0 @@
---
layout: page
permalink: /blog/index.html
---
<h1>Latest posts</h1>
<ul>
{%- for post in site.posts -%}
<li>
<time datetime="{{- post.date | date_to_xmlschema | xml_escape -}}">{{- post.date | date: '%Y/%m/%d' | strip | normalize_whitespace | xml_escape -}}</time>
<span>&mdash;</span>
<a href="{{- post.url | relative_url | url_escape -}}">{{- post.title | strip | normalize_whitespace | xml_escape -}}</a>
</li>
{%- endfor -%}
</ul>

View File

@ -1,35 +0,0 @@
---
layout: page
permalink: /index.html
---
<div class="welcome">
<h1>Valentin Popov</h1>
<p>Software Engineer // Mathematician</p>
<div>
<a href="mailto:{{- site.email | strip | url_encode -}}" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M4 4h16c1.1 0 2 .9 2 2v12c0 1.1-.9 2-2 2H4c-1.1 0-2-.9-2-2V6c0-1.1.9-2 2-2z"></path><polyline points="22,6 12,13 2,6"></polyline></svg>
</a>
<a href="https://t.me/valentineus" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><line x1="22" y1="2" x2="11" y2="13"></line><polygon points="22 2 15 22 11 13 2 9 22 2"></polygon></svg>
</a>
<a href="https://git.popov.link/" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round" class="feather feather-git-pull-request"><circle cx="18" cy="18" r="3"></circle><circle cx="6" cy="6" r="3"></circle><path d="M13 6h3a2 2 0 0 1 2 2v7"></path><line x1="6" y1="9" x2="6" y2="21"></line></svg>
</a>
<a href="https://github.com/valentineus/" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M9 19c-5 1.5-5-2.5-7-3m14 6v-3.87a3.37 3.37 0 0 0-.94-2.61c3.14-.35 6.44-1.54 6.44-7A5.44 5.44 0 0 0 20 4.77 5.07 5.07 0 0 0 19.91 1S18.73.65 16 2.48a13.38 13.38 0 0 0-7 0C6.27.65 5.09 1 5.09 1A5.07 5.07 0 0 0 5 4.77a5.44 5.44 0 0 0-1.5 3.78c0 5.42 3.3 6.61 6.44 7A3.37 3.37 0 0 0 9 18.13V22"></path></svg>
</a>
<a href="https://www.linkedin.com/in/valentineus/" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2" stroke-linecap="round" stroke-linejoin="round"><path d="M16 8a6 6 0 0 1 6 6v7h-4v-7a2 2 0 0 0-2-2 2 2 0 0 0-2 2v7h-4v-7a6 6 0 0 1 6-6z"></path><rect x="2" y="9" width="4" height="12"></rect><circle cx="4" cy="4" r="2"></circle></svg>
</a>
<a href="https://keys.openpgp.org/vks/v1/by-fingerprint/84CC1892159C001CD6D6FED6AE3CE523DAAA8401" target="_blank">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="currentColor" stroke="none"><path d="M2.968 11.583h1.274v-3.82A7.76 7.76 0 0 1 12.005 0a7.76 7.76 0 0 1 7.762 7.763v3.783c-.018.01-.037.028-.056.037l-.01.01-.008.009h-.01l-.01.01-.009.009H19.636l-.018.018h-.02l-.018.01h-.01l-.009.01-.009.009h-.01l-.009.009-.009.01-.01.009-.009.009-.028.019-.019.01-.028.018-.018.01-.02.009-.027.018-.019.01-.01.009-.027.019-.02.01-.046.027-.019.01-.018.009-.02.01h-.008l-.057.027h-.019c-.018.01-.037.02-.065.038h-.01l-.009.01-.028.018-.018.01-.029.018-.018.01h-.01l-.028.018-.018.01-.02.009c-.018.01-.046.019-.065.028l-.018.01-.02.009-.037.018-.037.02-.047.018-.047.019-.019.009-.037.019-.019.01c-1.545.739-4.017 1.516-8.708 1.853-3.362.244-5.403 1.723-6.724 3.502zm4.842 0h8.371v-3.82a4.184 4.184 0 0 0-4.186-4.186A4.184 4.184 0 0 0 7.81 7.763zm13.222 1.461V24H5.572c1.704-.946 2.968-.852 5.075-.787 2.865.094 6.03-1.105 7.585-2.696 1.554-1.592-.14-.375-1.901.074-1.76.45-5.17.497-7.454-.103 7.173.094 9.973-2.219 11.555-4.307 1.583-2.079-.683-.365-2.153.356-1.47.72-4.036 1.227-6.864.852 4.27-.01 7.52-2.144 9.607-4.345z"></path></svg>
</a>
</div>
</div>

View File

@ -1,9 +0,0 @@
---
layout: null
permalink: /robots.txt
---
User-agent: *
Disallow: {{ "/404.html" | relative_url | url_escape }}
Allow: /
Sitemap: {{ "sitemap.xml" | absolute_url | url_escape }}

View File

@ -1,225 +0,0 @@
---
description: >-
Изучение исходных кодов Chromium: подготовка системы и установка необходимых программных компонентов. Руководство для начинающих разработчиков. Получите инструкции по установке Microsoft Visual Studio, Cygwin, Python и других инструментов. Действительно на январь-февраль 2012 года.
title: Получение исходного кода "Chromium Projects"
author: valentineus
layout: post
---
> Перенос [оригинальной статьи](https://adeptus-mechanicus.blogspot.com/2012/01/chromium-projects.html) 2012 года из моего [старого блога](https://adeptus-mechanicus.blogspot.com/) ([зеркало](https://web.archive.org/web/20160217052148/http://adeptus-mechanicus.blogspot.com/)).
__Добрый день, уважаемые читатели!__
В последние дни выдалось свободное время, и я решил изучить исходные коды "[The Chromium Projects](http://www.chromium.org/)".
Чтобы посмотреть исходники, оказалось недостаточным просто скачать архив с исходным кодом и начать работать с ним в "Visual Studio 2010".
Я был крайне опечален отсутствием нормальной русской документации для начинающих, поэтому восполню пробел и переведу всю инструкцию по получению исходных кодов.
___P.S.__ Chromium является быстроразвивающимся Open Sources проектом._
анная инструкция актуальна на январь-февраль 2012 года._
Для начала немного введения.
Весь процесс от подготовки системы, до работы с исходными кодами я условно разделю на четыре пункта, это:
- Подготовка операционной системы, установка стандартных программных комплектов разработчика;
- Установка и настройка программы "Cygwin";
- Установка и настройка пакета "depot\_tools";
- Получение и подготовка для работы исходных кодов "Chromium";
## Подготовка начального набора программ
Ниже приведу список и краткое описание программного обеспечения, которое требуется установить перед работой с исходными кодами:
- "__Microsoft Visual Studio 2010__" — Среда разработки, требуется для работы с исходным кодом. Имеется возможность использовать Microsoft Visual Studio 2008 и Microsoft Visual C++ Express 2010'го и 2008'го годов соответственно. Бесплатные Express версии продуктов можно взять на [официальном сайте](http://www.microsoft.com/express) Microsoft.
- "__Microsoft Windows SDK__" — Пакет для предоставления заголовочных файлов, библиотек, компиляторов и пр. для разработчиков программного обеспечения под операционную систему Windows. Требуется для успешной сборки и компиляции проекта под Windows систему. Бесплатно можно скачать с [официальной страницы](https://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b).
- "__Microsoft DirectX SDK__" — Пакет с библиотеками мультимедийной подсистемы DirectX. Требуется для успешной сборки и компиляции проекта. Бесплатно доступен на [официальном сайте](http://msdn.microsoft.com/en-us/directx/default.aspx).
- "__Python 2.x__" — Высокоуровневый язык программирования. Требуется для начальной подготовки исходных кодов. Установка не обязательная, но желательная. Про третью версию Python официальной информации нет, у меня установлены обе версии для опытов и "Path" системы направлен на вторую версию. Установку Python коротко разберу ниже. Python бесплатно можно взять на [официальном сайте](http://python.org/).
- "__Cygwin__" — Unix-подобная среда и интерфейс командной строки для систем Microsoft Windows. Требуется для работы с исходными кодами, их подготовки, обновлением и проверки на ошибки. Сам инструмент бесплатно доступен на [официальной странице](http://www.cygwin.com/). Его установку я распишу в следующих пунктах.
- "__TortoiseSVN__" — Клиент Subversion под систему Windows. Установка не обязательная, но желательная. Требуется для более простого обновления пакета "depot\_tools" из официального репозитория SVN от корпорации Google. Бесплатно доступен на [официальной странице](http://tortoisesvn.net/).
Над установкой Microsoft Visual Studio, Microsoft Windows SDK и Microsoft DirectX SDK я подробно останавливаться не буду.
Установка данных программных комплектов проста, и особой сложности вызывать не должна.
В случае возникновения каких-либо проблем, имеются огромные сообщества разработчиков, которые помогут с установкой.
__На установке пакета Python'а я остановлюсь поподробнее:__
Во-первых, путь установки Python'а не должен содержать русскоязычный текст, это может вызвать много ошибок.
Во-вторых, после установки основного пакета, не забудьте добавить имя каталога в список путей, по которому операционная система ищет исполняемые файлы.
Чтобы это сделать, требуется:
1. Запустите "_Панель Управления_" и выберите пиктограмму "_Система_";
2. Выберите "_Дополнительные настройки системы_";
3. Перейдите во вкладку "_Дополнительно_" и щёлкните на кнопке "_Переменные среды_";
4. В содержимом окна "_Системные переменные_" найдите строку "_Path_";
5. Добавьте туда путь до вашего каталога Python.
В моём случае этот путь выглядел так:
`C:\Program Files (x86)\Python2`.
Пути каталогов должны разделяться знаком `;`, по этому не забудьте перед последним записанным каталогом дописать `;` (без кавычек);
Чтобы проверить работоспособность языка Python в Вашей системе сразу после установки, откройте командную строку Windows и введите команду:
```bash
python --version
```
На экране должно появиться сообщение с версией Python, которая используется в Вашей системе по-умолчанию.
__Теперь подготовим каталоги.__
Каталог исходных кодов в моём случае располагается на диске `C:\`, потому что желательно не использовать пробелы в пути адреса до исходных кодов и мой пользователь в операционной системе состоит из русскоязычных символов.
На диске `C:\` я создал каталог `OpenSource`, в нём я создал каталог `ChromiumProjects`, в котором появилось два подкаталога `depot_tools` и `trunk`.
Т.е. система каталогов выглядит так:
- `C:\OpenSource\ChromiumProjects\depot_tools` — Пакет для работы с исходным кодом;
- `C:\OpenSource\ChromiumProjects\trunk` — Место хранения исходных кодов;
В случае использование других каталогов в вашей системе, используйте собственные пути, подставляя их в мои примеры.
Так же крайне рекомендуется отключить индексирование системы в данных каталогах, потому что это вызовет фатальные ошибки работы пакета "depot\_tools".
Чтобы это сделать, откройте "_Панель управления_", выберите пиктограмму "_Параметры индексирования_", нажмите на кнопку "_Изменить_" и снимите галочку с каталога, содержащий утилиту "depot\_tools".
Первоначальную установку и настройку системы можно считать оконченной.
Переходим к следующему шагу.
## Установка программы "Cygwin"
Первым делом получите установочный файл последней версии по этой [ссылке](http://cygwin.com/setup.exe).
Установочный файл во время установки скачивает необходимые пакеты из интернета.
Когда запустите файл, следуйте инструкциям.
После выбор зеркала пакетов, Вам покажут список доступных пакетов с зеркала.
Требуется найти и отметить для установки следующие пакеты:
- `apache`;
- `bc`;
- `bison`;
- `curl`;
- `diffutils`;
- `e2fsprogs`;
- `emacs`;
- `flex`;
- `gcc`;
- `gperf`;
- `keychain`;
- `make`;
- `nano`;
- `openssh`;
- `patch`;
- `perl`;
- `perl-libwin32`;
- `python`;
- `rebase`;
- `rsync`;
- `ruby`;
- `subversion`;
- `unzip`;
- `vim`;
- `zip`;
Имена пакетов должны полностью совпадать.
Воспользуйтесь поиском по пакетам, включённым в саму программу установки.
Это должно сильно облегчить задачу.
Актуальный список пакетов, требующихся для установки, Вы всегда можете найти в [официальном скрипте](http://trac.webkit.org/browser/trunk/Tools/CygwinDownloader/cygwin-downloader.py) установки, в поле `required_packages`.
После установки приложения, требуется внести путь до папки с исполняемыми файлами в переменную "Path".
Сделать это можно в точности, как после установки пакета Python'а, описанного чуть выше в данной статье.
Только в отличии от Python'а, требуется указать путь до папки `bin`, находящейся в корневом каталоге приложения "Cygwin".
В моём случае этот путь выглядел так:
`C:\Program Files (x86)\Cygwin\bin`.
После установки и проверки приложения "Cygwin", можно переходить к следующему шагу, настройке и установки пакета "depot\_tools".
## Установка пакета "depot\_tools"
1. Перейдите в каталог, который Вы определили для хранения пакета "depot\_tools";
2. Находясь в папке, нажмите правую кнопку мыши в любом свободном месте и контекстном меню выберите пункт "_SVN Checkout_";
3. В пути URL репозитория, указывайте путь: `http://src.chromium.org/svn/trunk/tools/depot_tools`;
Если проблем не возникнет, пойдёт установка последней ревизии данного пакета.
По окончанию скачивания пакета, путь до исполняемых файлов пакета следует указать в переменной "Path", по аналогии с программой "Cygwin" и пакетом "Python".
В моём случае, путь выглядел так:
`C:\OpenSource\ChromiumProjects\depot_tools`.
Если всё прошло успешно, можно перейти к заключительной части статьи, получения и подготовка исходных кодов браузера "Chromium".
## Получение и подготовка исходных кодов
Перейдите по данной [ссылке](http://chromium-browser-source.commondatastorage.googleapis.com/chromium_tarball.html) и скачайте архив с исходными кодами.
Вы получите архив с именем "_chromium.r**XXXXX**.tgz_", где __XXXXX__ — номер стабильной последней версии.
Распакуйте из архива папку `src` в наш каталог `trunk`.
Процесс займёт продолжительное время, потому что объём исходных кодов ~4 Гб.
По окончанию распаковки, откройте терминал "Cygwin".
В открытом терминале теперь необходимо пройти в каталог `src`, который получится после распаковки исходных кодов.
Переход по каталогам в терминале осуществляется программой `cd`.
Чтобы попасть на диск `C:\`, требуется в терминале набрать команду:
```bash
cd "C:/"
```
Чтобы вернуться на каталог выше, требуется набрать команду:
```bash
cd ..
```
В Unix-терминалах для работы с каталогами используется обратная косая черта.
По этому, чтобы перейти в требуемый каталог, на моём примере, команда будет выглядеть так:
```bash
cd "C:/OpenSource/ChromiumProjects/trunk/src"
```
Теперь, когда мы в требуемой папке, надо применить команду для первоначальной настройки исходных кодов.
Для этого ведите команду:
```bash
gclient sync --force
```
После выполнения данной команды, требуется подготовить исходные коды для работы с "_Visual Studio 2010_".
Для этого вводим команду:
```bash
gclient runhooks --force
```
По окончанию выполнения данной команды, мы получаем готовые к работе исходные коды.
Чтобы начать с ними работу, откройте Вашу "Visual Studio", выберите "_Открыть проект_" и откройте файл `chrome.sln`, который находится в папке `chrome`, находящейся в папке исходных кодов.
В моём случае, полный путь до файла выглядит так:
`C:\OpenSource\ChromiumProjects\trunk\src\chrome\chrome.sln`.
На этом работу можно считать законченной.
## Обновление
Чтобы обновить пакет "depot\_tools", требуется зайти в каталог, содержащий данный пакет, щёлкнуть правой кнопкой мыши и в контекстном меню выбрать "_SVN Update_".
"TortoiseSVN" обновит данные каталога до последней ревизии пакета.
Для обновления исходных кодов "Chromium", требуется открыть терминал "Cygwin", перейти в каталог с исходными кодами и ввести команду:
```bash
gclient sync
```
## Заключение
Спасибо, что прочитали и большое спасибо, если воспользовались моей инструкцией.
Я всегда рад Вашим комментариям с вопросами, уточнениями и предложениями.
## Полезные ссылки
- [http://dev.chromium.org/Home](http://dev.chromium.org/Home) — Официальная страница проекта "The Chromium Projects";
- [http://dev.chromium.org/developers/how-tos/build-instructions-windows](http://dev.chromium.org/developers/how-tos/build-instructions-windows) — Официальная страница по подготовке операционной системы Windows, перед работой с исходными кодами;
- [http://dev.chromium.org/developers/how-tos/get-the-code](http://dev.chromium.org/developers/how-tos/get-the-code) — Официальная инструкция по получению, настройке и подготовке исходных кодов проекта "The Chromium Projects";
- [http://dev.chromium.org/developers/how-tos/install-depot-tools](http://dev.chromium.org/developers/how-tos/install-depot-tools) — Официальная инструкция по установке и настройке пакета "depot\_tools";
- [http://dev.chromium.org/developers/how-tos/cygwin](http://dev.chromium.org/developers/how-tos/cygwin) — Страница по установки и настройке терминала "Cygwin";
- [http://groups.google.com/a/chromium.org/group/chromium-discuss/topics](http://groups.google.com/a/chromium.org/group/chromium-discuss/topics) — Официальная дискуссия разработчиков браузера "Chromium";

View File

@ -1,26 +0,0 @@
---
description: >-
Решение проблем установки Moodle из-за SELinux: как настроить правила доступа для устранения ошибок в веб-интерфейсе и при работе с cURL. Практические советы и команды.
title: Установка Moodle в Fedora
author: valentineus
layout: post
---
Во время установки Moodle, сталкиваешься со следующими проблемами:
- Веб-интерфейс не продолжает установку после настройки базы данных;
- Если установить через консольный интерфейс, проявляются артефакты;
- Нет доступа к сети, появляется ошибка `unexpected cURL error`.
Главная причина, это
[SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux).
Решение, это настроить правила доступа:
```bash
# Доступ к сторонним каталогам и сети
/usr/sbin/setsebool -P httpd_can_network_connect true
/usr/sbin/setsebool -P httpd_enable_homedirs true
# Смена контекста безопасности
/usr/bin/chcon -R -h -t httpd_sys_content_t /path/to/moodle
/usr/bin/chcon -R -h -t httpd_sys_script_rw_t /path/to/moodle_data
```

View File

@ -1,60 +0,0 @@
---
description: >-
Learn how to generate a *.lib file from a *.dll with this comprehensive guide. Using the Visual Studio Command Prompt and Microsoft's recommended tools, this article walks you through the steps for a seamless process. Perfect for developers working with 3rd party win dll's.
title: Create ".lib" file from ".dll" (archive)
author: adrianhenke
layout: post
---
> This's a copy of a non-my post.
> The original article [is here](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) ([archive](https://web.archive.org/web/20161118122539/https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/)).
When working with 3rd party win dll's you sometimes miss the according to the `*.lib` file required to compile against it.
There is an [Microsoft KB-Q131313](http://support.microsoft.com/?scid=kb%3Ben-us%3B131313&x=1&y=15) ([archive](https://jeffpar.github.io/kbarchive/kb/131/Q131313/)) article showing how to generate a `*.lib` file from a `*.dll` however the required steps are not described detailed enough I think.
So here is my quick guide.
Open the "Visual Studio Command Prompt", you find its shortcut in "_Start_" -> "_Programs_" -> "_Microsoft Visual Studio Tools_".
Now run the `dumpbin` command to get a list of all exported functions of your dll:
```bash
dumpbin /exports C:\\yourpath\\yourlib.dll
```
This will print quite a bit of text to the console.
However, we are only interested in the functions:
```
ordinal hint RVA name
1 0 00017770 jcopy_block_row
2 1 00017710 jcopy_sample_rows
3 2 000176C0 jdiv_round_up
4 3 000156D0 jinit_1pass_quantizer
5 4 00016D90 jinit_2pass_quantizer
6 5 00005750 jinit_c_coef_controller
...etc
```
Now copy all those function names (only the names!) and paste them into a new text file.
Name the next file `yourlib.def` and put the line "EXPORTS" at its top.
My `yourlib.def` file looks like this:
```
EXPORTS
jcopy_block_row
jcopy_sample_rows
jdiv_round_up
jinit_1pass_quantizer
jinit_2pass_quantizer
jinit_c_coef_controller
...
```
Now from that definition file, we can finally create the `*.lib` file.
We use the `lib` tool for this, so run this command in your "Visual Studio Command Prompt":
```bash
lib /def:C:\\mypath\\mylib.def /OUT:C:\\mypath\\mylib.lib
```
That's it, happy coding 🙂

View File

@ -1,242 +0,0 @@
*,
*::after,
*::before {
box-sizing: border-box;
text-size-adjust: 100%;
}
html {
font-family: $font-family-base;
font-size: 62.5%;
min-height: 100%;
overflow-y: scroll;
}
body {
background-color: $color-bg;
color: $color-text;
font-size: $font-size-base;
font-synthesis: weight style small-caps;
font-weight: 400;
line-height: 1.5;
margin: auto;
max-width: 52em;
min-height: 100vh;
padding: 6em 4em 4em;
text-rendering: optimizelegibility;
}
@media (width <=684px) {
body {
font-size: $font-size-base * 0.85;
padding: 4em 1em 2em;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 700;
line-height: 1.1;
margin-bottom: 1.5rem;
margin-top: 3rem;
overflow-wrap: break-word;
word-break: break-word;
word-wrap: break-word;
}
h1 {
font-size: 2.35em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.75em;
}
h4 {
font-size: 1.5em;
}
h5 {
font-size: 1.25em;
}
h6 {
font-size: 1em;
}
p {
margin-bottom: 2.5rem;
margin-top: 0;
}
small,
sub,
sup {
font-size: 75%;
}
hr {
border-color: $color-blossom;
}
a {
color: $color-blossom;
text-decoration: inherit;
transition: color 0.25s;
&:visited {
color: $color-blossom;
}
&:active,
&:focus,
&:hover {
opacity: .5;
}
}
ul {
margin-bottom: 2.5rem;
margin-top: 0;
padding-left: 1.4em;
}
li {
margin-bottom: 0.4em;
}
blockquote {
background-color: $color-bg-alt;
border-left: 5px solid $color-blossom;
margin-bottom: 2.5rem;
margin-left: 0;
margin-right: 0;
padding: 0.8em 0.8em 0.8em 1em;
}
blockquote p {
margin-bottom: 0;
}
img,
video {
display: block;
height: auto;
margin-bottom: 2.5rem;
margin-top: 0;
max-width: 100%;
}
pre {
background-color: $color-bg-alt;
border-radius: 4px;
border: 1px solid $color-bg-alt;
display: block;
font-size: 0.9em;
margin-bottom: 2.5rem;
margin-top: 0;
overflow-x: auto;
padding: 1em;
}
code,
kbd,
samp {
background-color: $color-bg-code;
border-radius: 4px;
font-size: 0.9em;
padding: 0 0.2em;
white-space: pre-wrap;
}
pre>code {
background-color: transparent;
font-size: 1em;
padding: 0;
white-space: pre;
}
table {
border-collapse: collapse;
text-align: justify;
width: 100%;
}
td,
th {
border-bottom: 1px dashed $color-blossom;
padding: 0.5em;
}
textarea {
width: 100%;
}
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
background-color: $color-blossom;
border: 1px solid $color-blossom;
border-radius: 1px;
box-sizing: border-box;
color: $color-bg;
cursor: pointer;
display: inline-block;
padding: 5px 10px;
text-align: center;
text-decoration: none;
white-space: nowrap;
&[disabled] {
cursor: default;
opacity: 0.5;
}
&:focus:enabled,
&:hover:enabled {
background-color: $color-fade;
border-color: $color-fade;
color: $color-bg;
outline: 0;
}
}
textarea,
select,
input {
background-color: $color-bg-alt;
border: 1px solid $color-bg-alt;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
color: $color-text;
margin-bottom: 10px;
padding: 6px 10px;
&:focus {
border: 1px solid $color-blossom;
outline: 0;
}
}
input[type="checkbox"]:focus {
outline: 1px dotted $color-blossom;
}
label,
legend,
fieldset {
display: block;
font-weight: 600;
margin-bottom: 0.5rem;
}

View File

@ -1,136 +0,0 @@
.highlight table td {
padding: 5px;
}
.highlight table pre {
margin: 0;
}
.highlight,
.highlight .w {
background-color: $color-bg-alt;
color: $color-text;
}
.highlight .err {
background-color: #ac4142;
color: $color-bg-alt;
}
.highlight .c,
.highlight .ch,
.highlight .cd,
.highlight .cm,
.highlight .cpf,
.highlight .c1,
.highlight .cs {
color: #505050;
}
.highlight .cp {
color: #f4bf75;
}
.highlight .nt {
color: #f4bf75;
}
.highlight .o,
.highlight .ow {
color: $color-text;
}
.highlight .p,
.highlight .pi {
color: $color-text;
}
.highlight .gi {
color: #90a959;
}
.highlight .gd {
color: #ac4142;
}
.highlight .gh {
background-color: $color-bg-alt;
color: #6a9fb5;
font-weight: bold;
}
.highlight .k,
.highlight .kn,
.highlight .kp,
.highlight .kr,
.highlight .kv {
color: #aa759f;
}
.highlight .kc {
color: #d28445;
}
.highlight .kt {
color: #d28445;
}
.highlight .kd {
color: #d28445;
}
.highlight .s,
.highlight .sa,
.highlight .sb,
.highlight .sc,
.highlight .dl,
.highlight .sd,
.highlight .s2,
.highlight .sh,
.highlight .sx,
.highlight .s1 {
color: #90a959;
}
.highlight .sr {
color: #75b5aa;
}
.highlight .si {
color: #8f5536;
}
.highlight .se {
color: #8f5536;
}
.highlight .nn {
color: #f4bf75;
}
.highlight .nc {
color: #f4bf75;
}
.highlight .no {
color: #f4bf75;
}
.highlight .na {
color: #6a9fb5;
}
.highlight .m,
.highlight .mb,
.highlight .mf,
.highlight .mh,
.highlight .mi,
.highlight .il,
.highlight .mo,
.highlight .mx {
color: #90a959;
}
.highlight .ss {
color: #90a959;
}

View File

@ -1,41 +0,0 @@
header {
background-color: $color-bg;
border-bottom: 1px solid $color-header;
box-shadow: 0 5px 5px $color-bg;
left: 0;
line-height: 3.5em;
opacity: .975;
position: fixed;
right: 0;
top: 0;
}
nav {
margin: auto;
max-width: 60em;
padding: 0 4em;
text-align: right;
a {
color: $color-text;
padding: 0 1em;
&:visited {
color: $color-text;
}
}
}
@media (width <=684px) {
header {
box-shadow: none;
}
nav {
padding: 0 2em;
span {
display: none;
}
}
}

View File

@ -1,21 +0,0 @@
@media print {
body {
padding: 0;
}
audio,
embed,
footer,
form,
header,
iframe,
nav,
object,
video {
display: none;
}
img {
max-width: 500px;
}
}

View File

@ -1,179 +0,0 @@
html {
line-height: 1.15;
-webkit-text-size-adjust: 100%;
}
body {
margin: 0;
}
main {
display: block;
}
h1 {
font-size: 2em;
margin: 0.67em 0;
}
hr {
box-sizing: content-box;
height: 0;
overflow: visible;
}
pre {
font-family: monospace, monospace;
font-size: 1em;
}
a {
background-color: transparent;
}
abbr[title] {
border-bottom: none;
text-decoration: underline;
text-decoration: underline dotted;
}
b,
strong {
font-weight: bolder;
}
code,
kbd,
samp {
font-family: monospace, monospace;
font-size: 1em;
}
small {
font-size: 80%;
}
sub,
sup {
font-size: 75%;
line-height: 0;
position: relative;
vertical-align: baseline;
}
sub {
bottom: -0.25em;
}
sup {
top: -0.5em;
}
img {
border-style: none;
}
button,
input,
optgroup,
select,
textarea {
font-family: inherit;
font-size: 100%;
line-height: 1.15;
margin: 0;
}
button,
input {
overflow: visible;
}
button,
select {
text-transform: none;
}
button,
[type="button"],
[type="reset"],
[type="submit"] {
-webkit-appearance: button;
}
button::-moz-focus-inner,
[type="button"]::-moz-focus-inner,
[type="reset"]::-moz-focus-inner,
[type="submit"]::-moz-focus-inner {
border-style: none;
padding: 0;
}
button:-moz-focusring,
[type="button"]:-moz-focusring,
[type="reset"]:-moz-focusring,
[type="submit"]:-moz-focusring {
outline: 1px dotted ButtonText;
}
fieldset {
padding: 0.35em 0.75em 0.625em;
}
legend {
box-sizing: border-box;
color: inherit;
display: table;
max-width: 100%;
padding: 0;
white-space: normal;
}
progress {
vertical-align: baseline;
}
textarea {
overflow: auto;
}
[type="checkbox"],
[type="radio"] {
box-sizing: border-box;
padding: 0;
}
[type="number"]::-webkit-inner-spin-button,
[type="number"]::-webkit-outer-spin-button {
height: auto;
}
[type="search"] {
-webkit-appearance: textfield;
outline-offset: -2px;
}
[type="search"]::-webkit-search-decoration {
-webkit-appearance: none;
}
::-webkit-file-upload-button {
-webkit-appearance: button;
font: inherit;
}
details {
display: block;
}
summary {
display: list-item;
}
template {
display: none;
}
[hidden] {
display: none;
}

View File

@ -1,9 +0,0 @@
$color-bg: #212529;
$color-bg-alt: hwb(0deg 0% 100% / 20%);
$color-bg-code: #3b3d42;
$color-blossom: #6da13f;
$color-fade: #598332;
$color-header: #1b1f22;
$color-text: #dee2e6;
$font-family-base: "Jost", -apple-system, blinkmacsystemfont, "Segoe UI", roboto, "Helvetica Neue", arial, "Noto Sans", sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol", "Noto Color Emoji";
$font-size-base: 1.8rem;

View File

@ -1,19 +0,0 @@
.welcome {
left: 50%;
position: absolute;
text-align: center;
top: 40%;
transform: translate(-50%, -50%);
white-space: nowrap;
div {
a {
color: $color-text;
padding: 0 .5em;
&:visited {
color: $color-text;
}
}
}
}

Binary file not shown.

Before

Width:  |  Height:  |  Size: 5.0 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 20 KiB

View File

@ -1,254 +0,0 @@
// GoatCounter: https://www.goatcounter.com
// This file is released under the ISC license: https://opensource.org/licenses/ISC
;(function() {
'use strict';
if (window.goatcounter && window.goatcounter.vars) // Compatibility with very old version; do not use.
window.goatcounter = window.goatcounter.vars
else
window.goatcounter = window.goatcounter || {}
// Load settings from data-goatcounter-settings.
var s = document.querySelector('script[data-goatcounter]')
if (s && s.dataset.goatcounterSettings) {
try { var set = JSON.parse(s.dataset.goatcounterSettings) }
catch (err) { console.error('invalid JSON in data-goatcounter-settings: ' + err) }
for (var k in set)
if (['no_onload', 'no_events', 'allow_local', 'allow_frame', 'path', 'title', 'referrer', 'event'].indexOf(k) > -1)
window.goatcounter[k] = set[k]
}
var enc = encodeURIComponent
// Get all data we're going to send off to the counter endpoint.
var get_data = function(vars) {
var data = {
p: (vars.path === undefined ? goatcounter.path : vars.path),
r: (vars.referrer === undefined ? goatcounter.referrer : vars.referrer),
t: (vars.title === undefined ? goatcounter.title : vars.title),
e: !!(vars.event || goatcounter.event),
s: [window.screen.width, window.screen.height, (window.devicePixelRatio || 1)],
b: is_bot(),
q: location.search,
}
var rcb, pcb, tcb // Save callbacks to apply later.
if (typeof(data.r) === 'function') rcb = data.r
if (typeof(data.t) === 'function') tcb = data.t
if (typeof(data.p) === 'function') pcb = data.p
if (is_empty(data.r)) data.r = document.referrer
if (is_empty(data.t)) data.t = document.title
if (is_empty(data.p)) data.p = get_path()
if (rcb) data.r = rcb(data.r)
if (tcb) data.t = tcb(data.t)
if (pcb) data.p = pcb(data.p)
return data
}
// Check if a value is "empty" for the purpose of get_data().
var is_empty = function(v) { return v === null || v === undefined || typeof(v) === 'function' }
// See if this looks like a bot; there is some additional filtering on the
// backend, but these properties can't be fetched from there.
var is_bot = function() {
// Headless browsers are probably a bot.
var w = window, d = document
if (w.callPhantom || w._phantom || w.phantom)
return 150
if (w.__nightmare)
return 151
if (d.__selenium_unwrapped || d.__webdriver_evaluate || d.__driver_evaluate)
return 152
if (navigator.webdriver)
return 153
return 0
}
// Object to urlencoded string, starting with a ?.
var urlencode = function(obj) {
var p = []
for (var k in obj)
if (obj[k] !== '' && obj[k] !== null && obj[k] !== undefined && obj[k] !== false)
p.push(enc(k) + '=' + enc(obj[k]))
return '?' + p.join('&')
}
// Show a warning in the console.
var warn = function(msg) {
if (console && 'warn' in console)
console.warn('goatcounter: ' + msg)
}
// Get the endpoint to send requests to.
var get_endpoint = function() {
var s = document.querySelector('script[data-goatcounter]')
if (s && s.dataset.goatcounter)
return s.dataset.goatcounter
return (goatcounter.endpoint || window.counter) // counter is for compat; don't use.
}
// Get current path.
var get_path = function() {
var loc = location,
c = document.querySelector('link[rel="canonical"][href]')
if (c) { // May be relative or point to different domain.
var a = document.createElement('a')
a.href = c.href
if (a.hostname.replace(/^www\./, '') === location.hostname.replace(/^www\./, ''))
loc = a
}
return (loc.pathname + loc.search) || '/'
}
// Run function after DOM is loaded.
var on_load = function(f) {
if (document.body === null)
document.addEventListener('DOMContentLoaded', function() { f() }, false)
else
f()
}
// Filter some requests that we (probably) don't want to count.
goatcounter.filter = function() {
if ('visibilityState' in document && document.visibilityState === 'prerender')
return 'visibilityState'
if (!goatcounter.allow_frame && location !== parent.location)
return 'frame'
if (!goatcounter.allow_local && location.hostname.match(/(localhost$|^127\.|^10\.|^172\.(1[6-9]|2[0-9]|3[0-1])\.|^192\.168\.|^0\.0\.0\.0$)/))
return 'localhost'
if (!goatcounter.allow_local && location.protocol === 'file:')
return 'localfile'
if (localStorage && localStorage.getItem('skipgc') === 't')
return 'disabled with #toggle-goatcounter'
return false
}
// Get URL to send to GoatCounter.
window.goatcounter.url = function(vars) {
var data = get_data(vars || {})
if (data.p === null) // null from user callback.
return
data.rnd = Math.random().toString(36).substr(2, 5) // Browsers don't always listen to Cache-Control.
var endpoint = get_endpoint()
if (!endpoint)
return warn('no endpoint found')
return endpoint + urlencode(data)
}
// Count a hit.
window.goatcounter.count = function(vars) {
var f = goatcounter.filter()
if (f)
return warn('not counting because of: ' + f)
var url = goatcounter.url(vars)
if (!url)
return warn('not counting because path callback returned null')
navigator.sendBeacon(url)
}
// Get a query parameter.
window.goatcounter.get_query = function(name) {
var s = location.search.substr(1).split('&')
for (var i = 0; i < s.length; i++)
if (s[i].toLowerCase().indexOf(name.toLowerCase() + '=') === 0)
return s[i].substr(name.length + 1)
}
// Track click events.
window.goatcounter.bind_events = function() {
if (!document.querySelectorAll) // Just in case someone uses an ancient browser.
return
var send = function(elem) {
return function() {
goatcounter.count({
event: true,
path: (elem.dataset.goatcounterClick || elem.name || elem.id || ''),
title: (elem.dataset.goatcounterTitle || elem.title || (elem.innerHTML || '').substr(0, 200) || ''),
referrer: (elem.dataset.goatcounterReferrer || elem.dataset.goatcounterReferral || ''),
})
}
}
Array.prototype.slice.call(document.querySelectorAll("*[data-goatcounter-click]")).forEach(function(elem) {
if (elem.dataset.goatcounterBound)
return
var f = send(elem)
elem.addEventListener('click', f, false)
elem.addEventListener('auxclick', f, false) // Middle click.
elem.dataset.goatcounterBound = 'true'
})
}
// Add a "visitor counter" frame or image.
window.goatcounter.visit_count = function(opt) {
on_load(function() {
opt = opt || {}
opt.type = opt.type || 'html'
opt.append = opt.append || 'body'
opt.path = opt.path || get_path()
opt.attr = opt.attr || {width: '200', height: (opt.no_branding ? '60' : '80')}
opt.attr['src'] = get_endpoint() + 'er/' + enc(opt.path) + '.' + enc(opt.type) + '?'
if (opt.no_branding) opt.attr['src'] += '&no_branding=1'
if (opt.style) opt.attr['src'] += '&style=' + enc(opt.style)
if (opt.start) opt.attr['src'] += '&start=' + enc(opt.start)
if (opt.end) opt.attr['src'] += '&end=' + enc(opt.end)
var tag = {png: 'img', svg: 'img', html: 'iframe'}[opt.type]
if (!tag)
return warn('visit_count: unknown type: ' + opt.type)
if (opt.type === 'html') {
opt.attr['frameborder'] = '0'
opt.attr['scrolling'] = 'no'
}
var d = document.createElement(tag)
for (var k in opt.attr)
d.setAttribute(k, opt.attr[k])
var p = document.querySelector(opt.append)
if (!p)
return warn('visit_count: append not found: ' + opt.append)
p.appendChild(d)
})
}
// Make it easy to skip your own views.
if (location.hash === '#toggle-goatcounter') {
if (localStorage.getItem('skipgc') === 't') {
localStorage.removeItem('skipgc', 't')
alert('GoatCounter tracking is now ENABLED in this browser.')
}
else {
localStorage.setItem('skipgc', 't')
alert('GoatCounter tracking is now DISABLED in this browser until ' + location + ' is loaded again.')
}
}
if (!goatcounter.no_onload)
on_load(function() {
// 1. Page is visible, count request.
// 2. Page is not yet visible; wait until it switches to 'visible' and count.
// See #487
if (!('visibilityState' in document) || document.visibilityState === 'visible')
goatcounter.count()
else {
var f = function(e) {
if (document.visibilityState !== 'visible')
return
document.removeEventListener('visibilitychange', f)
goatcounter.count()
}
document.addEventListener('visibilitychange', f)
}
if (!goatcounter.no_events)
goatcounter.bind_events()
})
})();

View File

@ -1 +0,0 @@
!function(a,b){function c(a,b){var c=a.createElement("p"),d=a.getElementsByTagName("head")[0]||a.documentElement;return c.innerHTML="x<style>"+b+"</style>",d.insertBefore(c.lastChild,d.firstChild)}function d(){var a=t.elements;return"string"==typeof a?a.split(" "):a}function e(a,b){var c=t.elements;"string"!=typeof c&&(c=c.join(" ")),"string"!=typeof a&&(a=a.join(" ")),t.elements=c+" "+a,j(b)}function f(a){var b=s[a[q]];return b||(b={},r++,a[q]=r,s[r]=b),b}function g(a,c,d){if(c||(c=b),l)return c.createElement(a);d||(d=f(c));var e;return e=d.cache[a]?d.cache[a].cloneNode():p.test(a)?(d.cache[a]=d.createElem(a)).cloneNode():d.createElem(a),!e.canHaveChildren||o.test(a)||e.tagUrn?e:d.frag.appendChild(e)}function h(a,c){if(a||(a=b),l)return a.createDocumentFragment();c=c||f(a);for(var e=c.frag.cloneNode(),g=0,h=d(),i=h.length;i>g;g++)e.createElement(h[g]);return e}function i(a,b){b.cache||(b.cache={},b.createElem=a.createElement,b.createFrag=a.createDocumentFragment,b.frag=b.createFrag()),a.createElement=function(c){return t.shivMethods?g(c,a,b):b.createElem(c)},a.createDocumentFragment=Function("h,f","return function(){var n=f.cloneNode(),c=n.createElement;h.shivMethods&&("+d().join().replace(/[\w\-:]+/g,function(a){return b.createElem(a),b.frag.createElement(a),'c("'+a+'")'})+");return n}")(t,b.frag)}function j(a){a||(a=b);var d=f(a);return!t.shivCSS||k||d.hasCSS||(d.hasCSS=!!c(a,"article,aside,dialog,figcaption,figure,footer,header,hgroup,main,nav,section{display:block}mark{background:#FF0;color:#000}template{display:none}")),l||i(a,d),a}var k,l,m="3.7.3",n=a.html5||{},o=/^<|^(?:button|map|select|textarea|object|iframe|option|optgroup)$/i,p=/^(?:a|b|code|div|fieldset|h1|h2|h3|h4|h5|h6|i|label|li|ol|p|q|span|strong|style|table|tbody|td|th|tr|ul)$/i,q="_html5shiv",r=0,s={};!function(){try{var a=b.createElement("a");a.innerHTML="<xyz></xyz>",k="hidden"in a,l=1==a.childNodes.length||function(){b.createElement("a");var a=b.createDocumentFragment();return"undefined"==typeof a.cloneNode||"undefined"==typeof a.createDocumentFragment||"undefined"==typeof a.createElement}()}catch(c){k=!0,l=!0}}();var t={elements:n.elements||"abbr article aside audio bdi canvas data datalist details dialog figcaption figure footer header hgroup main mark meter nav output picture progress section summary template time video",version:m,shivCSS:n.shivCSS!==!1,supportsUnknownElements:l,shivMethods:n.shivMethods!==!1,type:"default",shivDocument:j,createElement:g,createDocumentFragment:h,addElements:e};a.html5=t,j(b),"object"==typeof module&&module.exports&&(module.exports=t)}("undefined"!=typeof window?window:this,document);

View File

@ -1 +0,0 @@
!function(a){"use strict";a.matchMedia=a.matchMedia||function(a){var b,c=a.documentElement,d=c.firstElementChild||c.firstChild,e=a.createElement("body"),f=a.createElement("div");return f.id="mq-test-1",f.style.cssText="position:absolute;top:-100em",e.style.background="none",e.appendChild(f),function(a){return f.innerHTML='&shy;<style media="'+a+'"> #mq-test-1 { width: 42px; }</style>',c.insertBefore(e,d),b=42===f.offsetWidth,c.removeChild(e),{matches:b,media:a}}}(a.document)}(this),function(a){"use strict";function b(){u(!0)}var c={};a.respond=c,c.update=function(){};var d=[],e=function(){var b=!1;try{b=new a.XMLHttpRequest}catch(c){b=new a.ActiveXObject("Microsoft.XMLHTTP")}return function(){return b}}(),f=function(a,b){var c=e();c&&(c.open("GET",a,!0),c.onreadystatechange=function(){4!==c.readyState||200!==c.status&&304!==c.status||b(c.responseText)},4!==c.readyState&&c.send(null))};if(c.ajax=f,c.queue=d,c.regex={media:/@media[^\{]+\{([^\{\}]*\{[^\}\{]*\})+/gi,keyframes:/@(?:\-(?:o|moz|webkit)\-)?keyframes[^\{]+\{(?:[^\{\}]*\{[^\}\{]*\})+[^\}]*\}/gi,urls:/(url\()['"]?([^\/\)'"][^:\)'"]+)['"]?(\))/g,findStyles:/@media *([^\{]+)\{([\S\s]+?)$/,only:/(only\s+)?([a-zA-Z]+)\s?/,minw:/\([\s]*min\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/,maxw:/\([\s]*max\-width\s*:[\s]*([\s]*[0-9\.]+)(px|em)[\s]*\)/},c.mediaQueriesSupported=a.matchMedia&&null!==a.matchMedia("only all")&&a.matchMedia("only all").matches,!c.mediaQueriesSupported){var g,h,i,j=a.document,k=j.documentElement,l=[],m=[],n=[],o={},p=30,q=j.getElementsByTagName("head")[0]||k,r=j.getElementsByTagName("base")[0],s=q.getElementsByTagName("link"),t=function(){var a,b=j.createElement("div"),c=j.body,d=k.style.fontSize,e=c&&c.style.fontSize,f=!1;return b.style.cssText="position:absolute;font-size:1em;width:1em",c||(c=f=j.createElement("body"),c.style.background="none"),k.style.fontSize="100%",c.style.fontSize="100%",c.appendChild(b),f&&k.insertBefore(c,k.firstChild),a=b.offsetWidth,f?k.removeChild(c):c.removeChild(b),k.style.fontSize=d,e&&(c.style.fontSize=e),a=i=parseFloat(a)},u=function(b){var c="clientWidth",d=k[c],e="CSS1Compat"===j.compatMode&&d||j.body[c]||d,f={},o=s[s.length-1],r=(new Date).getTime();if(b&&g&&p>r-g)return a.clearTimeout(h),h=a.setTimeout(u,p),void 0;g=r;for(var v in l)if(l.hasOwnProperty(v)){var w=l[v],x=w.minw,y=w.maxw,z=null===x,A=null===y,B="em";x&&(x=parseFloat(x)*(x.indexOf(B)>-1?i||t():1)),y&&(y=parseFloat(y)*(y.indexOf(B)>-1?i||t():1)),w.hasquery&&(z&&A||!(z||e>=x)||!(A||y>=e))||(f[w.media]||(f[w.media]=[]),f[w.media].push(m[w.rules]))}for(var C in n)n.hasOwnProperty(C)&&n[C]&&n[C].parentNode===q&&q.removeChild(n[C]);n.length=0;for(var D in f)if(f.hasOwnProperty(D)){var E=j.createElement("style"),F=f[D].join("\n");E.type="text/css",E.media=D,q.insertBefore(E,o.nextSibling),E.styleSheet?E.styleSheet.cssText=F:E.appendChild(j.createTextNode(F)),n.push(E)}},v=function(a,b,d){var e=a.replace(c.regex.keyframes,"").match(c.regex.media),f=e&&e.length||0;b=b.substring(0,b.lastIndexOf("/"));var g=function(a){return a.replace(c.regex.urls,"$1"+b+"$2$3")},h=!f&&d;b.length&&(b+="/"),h&&(f=1);for(var i=0;f>i;i++){var j,k,n,o;h?(j=d,m.push(g(a))):(j=e[i].match(c.regex.findStyles)&&RegExp.$1,m.push(RegExp.$2&&g(RegExp.$2))),n=j.split(","),o=n.length;for(var p=0;o>p;p++)k=n[p],l.push({media:k.split("(")[0].match(c.regex.only)&&RegExp.$2||"all",rules:m.length-1,hasquery:k.indexOf("(")>-1,minw:k.match(c.regex.minw)&&parseFloat(RegExp.$1)+(RegExp.$2||""),maxw:k.match(c.regex.maxw)&&parseFloat(RegExp.$1)+(RegExp.$2||"")})}u()},w=function(){if(d.length){var b=d.shift();f(b.href,function(c){v(c,b.href,b.media),o[b.href]=!0,a.setTimeout(function(){w()},0)})}},x=function(){for(var b=0;b<s.length;b++){var c=s[b],e=c.href,f=c.media,g=c.rel&&"stylesheet"===c.rel.toLowerCase();e&&g&&!o[e]&&(c.styleSheet&&c.styleSheet.rawCssText?(v(c.styleSheet.rawCssText,e,f),o[e]=!0):(!/^([a-zA-Z:]*\/\/)/.test(e)&&!r||e.replace(RegExp.$1,"").split("/")[0]===a.location.host)&&("//"===e.substring(0,2)&&(e=a.location.protocol+e),d.push({href:e,media:f})))}w()};x(),c.update=x,c.getEmValue=t,a.addEventListener?a.addEventListener("resize",b,!1):a.attachEvent&&a.attachEvent("onresize",b)}}(this);

26
astro.config.mjs Normal file
View File

@ -0,0 +1,26 @@
import { defineConfig } from "astro/config";
import { remarkReadingTime } from "./src/plugins/remarkReadingTime";
import cloudflare from "@astrojs/cloudflare";
import icon from "astro-icon";
import sitemap from "@astrojs/sitemap";
export default defineConfig({
site: "https://popov.link",
output: "hybrid",
adapter: cloudflare({
imageService: "compile",
}),
integrations: [icon(), sitemap()],
build: {
inlineStylesheets: "always",
},
markdown: {
remarkPlugins: [remarkReadingTime],
},
redirects: {
"/blog": {
destination: "/",
status: 301,
},
},
});

10242
package-lock.json generated Normal file

File diff suppressed because it is too large Load Diff

35
package.json Normal file
View File

@ -0,0 +1,35 @@
{
"name": "proto-planet",
"type": "module",
"version": "0.0.1",
"scripts": {
"format": "prettier --write .",
"dev": "astro dev",
"start": "astro dev",
"check": "astro check",
"build": "astro check && astro build",
"preview": "astro preview",
"astro": "astro"
},
"dependencies": {
"@astrojs/check": "^0.9.3",
"@astrojs/cloudflare": "^11.0.4",
"@astrojs/rss": "^4.0.7",
"@astrojs/sitemap": "^3.1.6",
"@iconify-json/hugeicons": "^1.2.0",
"astro": "^4.15.6",
"astro-icon": "^1.1.1",
"autoprefixer": "^10.4.20",
"cssnano": "^7.0.6",
"cssnano-preset-advanced": "^7.0.6",
"dayjs": "^1.11.13",
"mdast-util-to-string": "^4.0.0",
"reading-time": "^1.5.0",
"sass": "^1.78.0",
"typescript": "^5.6.2"
},
"devDependencies": {
"prettier": "^3.3.3",
"prettier-plugin-astro": "^0.14.1"
}
}

8
postcss.config.cjs Normal file
View File

@ -0,0 +1,8 @@
module.exports = {
plugins: [
require("autoprefixer"),
require("cssnano")({
preset: "advanced",
}),
],
};

9
public/favicon.svg Normal file
View File

@ -0,0 +1,9 @@
<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 128 128">
<path d="M50.4 78.5a75.1 75.1 0 0 0-28.5 6.9l24.2-65.7c.7-2 1.9-3.2 3.4-3.2h29c1.5 0 2.7 1.2 3.4 3.2l24.2 65.7s-11.6-7-28.5-7L67 45.5c-.4-1.7-1.6-2.8-2.9-2.8-1.3 0-2.5 1.1-2.9 2.7L50.4 78.5Zm-1.1 28.2Zm-4.2-20.2c-2 6.6-.6 15.8 4.2 20.2a17.5 17.5 0 0 1 .2-.7 5.5 5.5 0 0 1 5.7-4.5c2.8.1 4.3 1.5 4.7 4.7.2 1.1.2 2.3.2 3.5v.4c0 2.7.7 5.2 2.2 7.4a13 13 0 0 0 5.7 4.9v-.3l-.2-.3c-1.8-5.6-.5-9.5 4.4-12.8l1.5-1a73 73 0 0 0 3.2-2.2 16 16 0 0 0 6.8-11.4c.3-2 .1-4-.6-6l-.8.6-1.6 1a37 37 0 0 1-22.4 2.7c-5-.7-9.7-2-13.2-6.2Z" />
<style>
path { fill: #000; }
@media (prefers-color-scheme: dark) {
path { fill: #FFF; }
}
</style>
</svg>

After

Width:  |  Height:  |  Size: 749 B

4
public/robots.txt Normal file
View File

@ -0,0 +1,4 @@
User-agent: *
Allow: /
Sitemap: https://popov.link/sitemap-index.xml

View File

@ -0,0 +1,17 @@
---
type Props = {
readonly title: string;
};
const path = Astro.url.pathname;
const { title } = Astro.props;
---
<!-- AppMetrix -->
<script is:inline src="https://appmetrix.com/pixel/T5X0z12SoASBV8Dv"></script>
<!-- GoatCounter -->
<script is:inline data-goatcounter="https://analytics.popov.link/count" src="//gc.zgo.at/count.js"></script>
<noscript>
<img alt="pixel" src={`https://analytics.popov.link/count?p=${encodeURI(path)}&t=${encodeURI(title)}`} />
</noscript>

View File

@ -0,0 +1,31 @@
---
const category = "Announcements";
const categoryId = "DIC_kwDOJfmscs4CdNE6";
const crossorigin = "anonymous";
const inputPosition = "bottom";
const lang = "en";
const mapping = "title";
const metadata = "0";
const reactions = "1";
const repo = "valentineus/valentineus.github.io";
const repoId = "R_kgDOJfmscg";
const strict = "1";
const theme = "transparent_dark";
---
<script
is:inline
src="https://giscus.app/client.js"
data-category-id={categoryId}
data-category={category}
data-emit-metadata={metadata}
data-input-position={inputPosition}
data-lang={lang}
data-mapping={mapping}
data-reactions-enabled={reactions}
data-repo-id={repoId}
data-repo={repo}
data-strict={strict}
data-theme={theme}
crossorigin={crossorigin}
></script>

View File

@ -0,0 +1,60 @@
---
import { Icon } from "astro-icon/components";
import dayjs from "dayjs";
---
<style lang="scss">
@import "../scss/_variables.scss";
footer {
bottom: 0;
height: 4em;
left: 0;
padding: 1em 4em;
position: absolute;
right: 0;
}
a {
color: $colorText;
&:visited {
color: $colorText;
}
}
.left-nav,
.right-nav {
display: inline-block;
vertical-align: top;
width: 49%;
}
.left-nav {
float: left;
font-size: $fontSizeBase * 0.75;
text-align: left;
}
.right-nav {
float: right;
text-align: right;
}
@media (width <=684px) {
footer {
padding: 4em 1em 2em;
}
}
</style>
<footer>
<div class="left-nav">
<span>&copy; {dayjs().year()} <a href="mailto:valentin@popov.link">Valentin Popov</a></span>
</div>
<div class="right-nav">
<a href="https://github.com/valentineus" target="_blank"><Icon name="hugeicons:github-01" /></a>
<a href="https://analytics.popov.link" target="_blank"><Icon name="hugeicons:analytics-up" /></a>
<a href="/feed.xml" target="_blank"><Icon name="hugeicons:rss" /></a>
</div>
</footer>

24
src/components/Head.astro Normal file
View File

@ -0,0 +1,24 @@
---
type Props = {
readonly description: string;
readonly title: string;
};
const canonicalURL = new URL(Astro.url.pathname, Astro.site);
const { description, title } = Astro.props;
---
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" content={description} />
<meta name="robots" content="index, follow" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link href="/feed.xml" rel="alternate" title="RSS" type="application/atom+xml" />
<link href="/sitemap-index.xml" rel="sitemap" />
<link href={canonicalURL} rel="canonical" />
<title>{title}</title>
</head>

View File

@ -0,0 +1,64 @@
---
import { Icon } from "astro-icon/components";
const { pathname } = Astro.url;
---
<style lang="scss">
@import "../scss/_variables.scss";
[data-icon] {
vertical-align: middle;
}
header {
background-color: $colorBg;
left: 0;
line-height: 3.5em;
opacity: 0.975;
position: absolute;
right: 0;
top: 0;
}
nav {
margin: auto;
max-width: 52em;
padding: 0 4em;
}
a {
color: $colorText;
&:visited {
color: $colorText;
}
}
@media (width <=684px) {
header {
position: fixed;
text-align: center;
}
}
</style>
<header>
<nav>
<a href="/">
{
pathname !== "/" ? (
<>
<Icon name="hugeicons:arrow-left-01" />
<span>{import.meta.env.DEFAULT_TITLE}</span>
</>
) : (
<>
<Icon name="hugeicons:source-code" />
<span>{import.meta.env.DEFAULT_TITLE}</span>
</>
)
}
</a>
</nav>
</header>

View File

@ -0,0 +1,35 @@
---
type Props = {
readonly nextUrl?: string;
readonly prevUrl?: string;
};
const { nextUrl, prevUrl } = Astro.props;
---
<style lang="scss">
div {
text-align: center;
}
span {
margin: 0 2em;
}
</style>
<div>
{
prevUrl && (
<span>
<a href={prevUrl}>&lt; Prev</a>
</span>
)
}
{
nextUrl && (
<span>
<a href={nextUrl}>Next &gt;</a>
</span>
)
}
</div>

View File

@ -0,0 +1,49 @@
---
import { type CollectionEntry } from "astro:content";
import dayjs from "dayjs";
type Props = {
readonly post: CollectionEntry<"blog">;
};
const { post } = Astro.props;
const { remarkPluginFrontmatter } = await post.render();
const formattedDate = dayjs(post.data.pubDate.toString()).format("MMMM DD, YYYY");
---
<style lang="scss">
@import "../scss/_variables.scss";
a {
color: $colorText;
display: block;
padding-bottom: 3rem;
&:visited {
color: $colorText;
}
}
h2 {
color: $colorBlossom;
font-size: 1.25em;
margin: 0.5em 0;
}
div {
font-size: $fontSizeBase * 0.75;
opacity: 0.5;
}
</style>
<a href={`/blog/${post.slug}`}>
<article>
<div>
<time datetime={post.data.pubDate.toISOString()}>{formattedDate}</time>
<span>•</span>
<span>{remarkPluginFrontmatter.minutesRead}</span>
</div>
<h2>{post.data.title}</h2>
<p>{post.data.description}</p>
</article>
</a>

View File

@ -0,0 +1,51 @@
---
title: 'Create ".lib" file from ".dll" (archive)'
author: "Adrian Henke"
pubDate: "2023-05-04"
description: "Learn how to generate a *.lib file from a *.dll with this comprehensive guide. Using the Visual Studio Command Prompt and Microsoft's recommended tools, this article walks you through the steps for a seamless process. Perfect for developers working with 3rd party win dll's."
---
> This's a copy of a non-my post. The original article [is here](https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/) ([archive](https://web.archive.org/web/20161118122539/https://adrianhenke.wordpress.com/2008/12/05/create-lib-file-from-dll/)).
When working with 3rd party win dll's you sometimes miss the according to the `*.lib` file required to compile against it. There is an [Microsoft KB-Q131313](http://support.microsoft.com/?scid=kb%3Ben-us%3B131313&x=1&y=15) ([archive](https://jeffpar.github.io/kbarchive/kb/131/Q131313/)) article showing how to generate a `*.lib` file from a `*.dll` however the required steps are not described detailed enough I think. So here is my quick guide.
Open the "Visual Studio Command Prompt", you find its shortcut in "_Start_" -> "_Programs_" -> "_Microsoft Visual Studio Tools_". Now run the `dumpbin` command to get a list of all exported functions of your dll:
```bash
dumpbin /exports C:\\yourpath\\yourlib.dll
```
This will print quite a bit of text to the console. However, we are only interested in the functions:
```
ordinal hint RVA name
1 0 00017770 jcopy_block_row
2 1 00017710 jcopy_sample_rows
3 2 000176C0 jdiv_round_up
4 3 000156D0 jinit_1pass_quantizer
5 4 00016D90 jinit_2pass_quantizer
6 5 00005750 jinit_c_coef_controller
...etc
```
Now copy all those function names (only the names!) and paste them into a new text file. Name the next file `yourlib.def` and put the line "EXPORTS" at its top. My `yourlib.def` file looks like this:
```
EXPORTS
jcopy_block_row
jcopy_sample_rows
jdiv_round_up
jinit_1pass_quantizer
jinit_2pass_quantizer
jinit_c_coef_controller
...
```
Now from that definition file, we can finally create the `*.lib` file. We use the `lib` tool for this, so run this command in your "Visual Studio Command Prompt":
```bash
lib /def:C:\\mypath\\mylib.def /OUT:C:\\mypath\\mylib.lib
```
That's it, happy coding 🙂

View File

@ -1,17 +1,15 @@
--- ---
description: >- title: "Горячая перезагрузка ElectronJS приложения"
Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса. author: "Valentin Popov"
title: Горячая перезагрузка ElectronJS приложения pubDate: "2019-08-15"
author: valentineus description: "Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса."
layout: post
--- ---
## Main процесс ## Main процесс
Для перезагрузки основного процесса можно использовать готовый пакет [electron-reload]. Или перезагружать приложение средствами пакета [electron-webpack]. Для перезагрузки основного процесса можно использовать готовый пакет [electron-reload]. Или перезагружать приложение средствами пакета [electron-webpack].
Если сборщик кода отличный от WebPack или нет возможности использовать вышеуказанные пакеты, можно обойтись инструментом [nodemon]. Команда запуска будет Если сборщик кода отличный от WebPack или нет возможности использовать вышеуказанные пакеты, можно обойтись инструментом [nodemon]. Команда запуска будет выглядеть следующим образом:
выглядеть следующим образом:
```bash ```bash
nodemon --watch ./assets/main.js --exec 'electron .' nodemon --watch ./assets/main.js --exec 'electron .'
@ -21,49 +19,42 @@ nodemon --watch ./assets/main.js --exec 'electron .'
## Renderer процесс ## Renderer процесс
Для обновления renderer процесса, перезагружать полностью приложение нет необходимости. Достаточно обновить страницу. Самый простой способ, горячие Для обновления renderer процесса, перезагружать полностью приложение нет необходимости. Достаточно обновить страницу. Самый простой способ, горячие клавиши: `Ctrl` + `F5`. Так как рендер процесс по своей сути является обычным окном браузера, можно настроить [HMR] технологию. Конечно, если используются соответствующие инструменты.
клавиши: `Ctrl` + `F5`. Так как рендер процесс по своей сути является обычным окном браузера, можно настроить [HMR] технологию. Конечно, если используются
соответствующие инструменты.
Мне симпатичен способ использования пакета [electron-reload]. В алгоритме пакета лежит простое слежение за каталогом файлов и обновление активных окон Мне симпатичен способ использования пакета [electron-reload]. В алгоритме пакета лежит простое слежение за каталогом файлов и обновление активных окон приложения.
приложения.
Но мною была найдена досадная [проблема], не позволяющая использовать версии `1.5.0` и `1.4.1` со сборщиком WebPack, который используется в проекте. Но мною была найдена досадная [проблема], не позволяющая использовать версии `1.5.0` и `1.4.1` со сборщиком WebPack, который используется в проекте.
Решение было продублировать основной функционал пакета в проекте: Решение было продублировать основной функционал пакета в проекте:
```javascript ```javascript
import { app } from 'electron'; import { app } from "electron";
import chokidar from 'chokidar'; import chokidar from "chokidar";
const browserWindows = []; const browserWindows = [];
app.on('browser-window-created', (event, window) => { app.on("browser-window-created", (event, window) => {
browserWindows.push(window); browserWindows.push(window);
window.on('closed', () => { window.on("closed", () => {
const index = browserWindows.indexOf(window); const index = browserWindows.indexOf(window);
browserWindows.splice(index, 1); browserWindows.splice(index, 1);
}); });
}); });
if (process.env.NODE_ENV !== 'production') { if (process.env.NODE_ENV !== "production") {
const watcher = chokidar.watch(__dirname, { ignored: [/node_modules|[/\\]\./] }); const watcher = chokidar.watch(__dirname, { ignored: [/node_modules|[/\\]\./] });
watcher.on('change', () => { watcher.on("change", () => {
browserWindows.forEach(window => { browserWindows.forEach((window) => {
window.webContents.reloadIgnoringCache(); window.webContents.reloadIgnoringCache();
}); });
}); });
} }
``` ```
[HMR]: https://webpack.js.org/concepts/hot-module-replacement/ [HMR]: https://webpack.js.org/concepts/hot-module-replacement/
[electron-reload]: https://www.npmjs.com/package/electron-reload [electron-reload]: https://www.npmjs.com/package/electron-reload
[electron-webpack]: https://www.npmjs.com/package/electron-webpack [electron-webpack]: https://www.npmjs.com/package/electron-webpack
[nodemon]: https://www.npmjs.com/package/nodemon [nodemon]: https://www.npmjs.com/package/nodemon
[проблема]: https://github.com/yan-foto/electron-reload/issues/66 [проблема]: https://github.com/yan-foto/electron-reload/issues/66

View File

@ -0,0 +1,133 @@
---
title: "Example Content"
author: "Example User"
pubDate: "2018-01-01"
description: "Howdy! This is an example blog post that shows several types of HTML content supported in this theme."
---
Cum sociis natoque penatibus et magnis <a href="#">dis parturient montes</a>, nascetur ridiculus mus. _Aenean eu leo quam._ Pellentesque ornare sem lacinia quam venenatis vestibulum. Sed posuere consectetur est at lobortis. Cras mattis consectetur purus sit amet fermentum.
> Curabitur blandit tempus porttitor. Nullam quis risus eget urna mollis ornare vel eu leo. Nullam id dolor id nibh ultricies vehicula ut id elit.
Etiam porta **sem malesuada magna** mollis euismod. Cras mattis consectetur purus sit amet fermentum. Aenean lacinia bibendum nulla sed consectetur.
## Inline HTML elements
HTML defines a long list of available inline tags, a complete list of which can be found on the [Mozilla Developer Network](https://developer.mozilla.org/en-US/docs/Web/HTML/Element).
- **To bold text**, use `<strong>`.
- _To italicize text_, use `<em>`.
- Abbreviations, like <abbr title="HyperText Markup Langage">HTML</abbr> should use `<abbr>`, with an optional `title` attribute for the full phrase.
- Citations, like <cite>&mdash; Mark otto</cite>, should use `<cite>`.
- <del>Deleted</del> text should use `<del>` and <ins>inserted</ins> text should use `<ins>`.
- Superscript <sup>text</sup> uses `<sup>` and subscript <sub>text</sub> uses `<sub>`.
Most of these elements are styled by browsers with few modifications on our part.
## Heading
Vivamus sagittis lacus vel augue rutrum faucibus dolor auctor. Duis mollis, est non commodo luctus, nisi erat porttitor ligula, eget lacinia odio sem nec elit. Morbi leo risus, porta ac consectetur ac, vestibulum at eros.
### Code
Cum sociis natoque penatibus et magnis dis `code element` montes, nascetur ridiculus mus.
```js
// Example can be run directly in your JavaScript console
// Create a function that takes two arguments and returns the sum of those arguments
var adder = new Function("a", "b", "return a + b");
// Call the function
adder(2, 6);
// > 8
```
Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa.
### Gists via GitHub Pages
Vestibulum id ligula porta felis euismod semper. Nullam quis risus eget urna mollis ornare vel eu leo. Donec sed odio dui.
{% gist 5555251 gist.md %}
Aenean eu leo quam. Pellentesque ornare sem lacinia quam venenatis vestibulum. Nullam quis risus eget urna mollis ornare vel eu leo. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Donec sed odio dui. Vestibulum id ligula porta felis euismod semper.
### Lists
Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus. Aenean lacinia bibendum nulla sed consectetur. Etiam porta sem malesuada magna mollis euismod. Fusce dapibus, tellus ac cursus commodo, tortor mauris condimentum nibh, ut fermentum massa justo sit amet risus.
- Praesent commodo cursus magna, vel scelerisque nisl consectetur et.
- Donec id elit non mi porta gravida at eget metus.
- Nulla vitae elit libero, a pharetra augue.
Donec ullamcorper nulla non metus auctor fringilla. Nulla vitae elit libero, a pharetra augue.
1. Vestibulum id ligula porta felis euismod semper.
2. Cum sociis natoque penatibus et magnis dis parturient montes, nascetur ridiculus mus.
3. Maecenas sed diam eget risus varius blandit sit amet non magna.
Cras mattis consectetur purus sit amet fermentum. Sed posuere consectetur est at lobortis.
<dl>
<dt>HyperText Markup Language (HTML)</dt>
<dd>The language used to describe and define the content of a Web page</dd>
<dt>Cascading Style Sheets (CSS)</dt>
<dd>Used to describe the appearance of Web content</dd>
<dt>JavaScript (JS)</dt>
<dd>The programming language used to build advanced Web sites and applications</dd>
</dl>
Integer posuere erat a ante venenatis dapibus posuere velit aliquet. Morbi leo risus, porta ac consectetur ac, vestibulum at eros. Nullam quis risus eget urna mollis ornare vel eu leo.
### Images
Quisque consequat sapien eget quam rhoncus, sit amet laoreet diam tempus. Aliquam aliquam metus erat, a pulvinar turpis suscipit at.
![placeholder](http://placehold.it/800x400 "Large example image") ![placeholder](http://placehold.it/400x200 "Medium example image") ![placeholder](http://placehold.it/200x200 "Small example image")
### Tables
Aenean lacinia bibendum nulla sed consectetur. Lorem ipsum dolor sit amet, consectetur adipiscing elit.
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Upvotes</th>
<th>Downvotes</th>
</tr>
</thead>
<tfoot>
<tr>
<td>Totals</td>
<td>21</td>
<td>23</td>
</tr>
</tfoot>
<tbody>
<tr>
<td>Alice</td>
<td>10</td>
<td>11</td>
</tr>
<tr>
<td>Bob</td>
<td>4</td>
<td>3</td>
</tr>
<tr>
<td>Charlie</td>
<td>7</td>
<td>9</td>
</tr>
</tbody>
</table>
Nullam id dolor id nibh ultricies vehicula ut id elit. Sed posuere consectetur est at lobortis. Nullam quis risus eget urna mollis ornare vel eu leo.
---
Want to see something else added? <a href="https://github.com/poole/poole/issues/new">Open an issue.</a>

View File

@ -0,0 +1,185 @@
---
title: 'Получение исходного кода "Chromium Projects"'
author: "Valentin Popov"
pubDate: "2012-01-30"
description: "Изучение исходных кодов Chromium: подготовка системы и установка необходимых программных компонентов. Руководство для начинающих разработчиков. Получите инструкции по установке Microsoft Visual Studio, Cygwin, Python и других инструментов. Действительно на январь-февраль 2012 года."
---
> Перенос [оригинальной статьи](https://adeptus-mechanicus.blogspot.com/2012/01/chromium-projects.html) 2012 года из моего [старого блога](https://adeptus-mechanicus.blogspot.com/) ([зеркало](https://web.archive.org/web/20160217052148/http://adeptus-mechanicus.blogspot.com/)).
**Добрый день, уважаемые читатели!**
В последние дни выдалось свободное время, и я решил изучить исходные коды "[The Chromium Projects](http://www.chromium.org/)". Чтобы посмотреть исходники, оказалось недостаточным просто скачать архив с исходным кодом и начать работать с ним в "Visual Studio 2010". Я был крайне опечален отсутствием нормальной русской документации для начинающих, поэтому восполню пробел и переведу всю инструкцию по получению исходных кодов.
**\_P.S.** Chromium является быстроразвивающимся Open Sources проектом.\_ _Данная инструкция актуальна на январь-февраль 2012 года._
Для начала немного введения. Весь процесс от подготовки системы, до работы с исходными кодами я условно разделю на четыре пункта, это:
- Подготовка операционной системы, установка стандартных программных комплектов разработчика;
- Установка и настройка программы "Cygwin";
- Установка и настройка пакета "depot_tools";
- Получение и подготовка для работы исходных кодов "Chromium";
## Подготовка начального набора программ
Ниже приведу список и краткое описание программного обеспечения, которое требуется установить перед работой с исходными кодами:
- "**Microsoft Visual Studio 2010**" — Среда разработки, требуется для работы с исходным кодом. Имеется возможность использовать Microsoft Visual Studio 2008 и Microsoft Visual C++ Express 2010'го и 2008'го годов соответственно. Бесплатные Express версии продуктов можно взять на [официальном сайте](http://www.microsoft.com/express) Microsoft.
- "**Microsoft Windows SDK**" — Пакет для предоставления заголовочных файлов, библиотек, компиляторов и пр. для разработчиков программного обеспечения под операционную систему Windows. Требуется для успешной сборки и компиляции проекта под Windows систему. Бесплатно можно скачать с [официальной страницы](https://www.microsoft.com/downloads/en/details.aspx?FamilyID=6b6c21d2-2006-4afa-9702-529fa782d63b).
- "**Microsoft DirectX SDK**" — Пакет с библиотеками мультимедийной подсистемы DirectX. Требуется для успешной сборки и компиляции проекта. Бесплатно доступен на [официальном сайте](http://msdn.microsoft.com/en-us/directx/default.aspx).
- "**Python 2.x**" — Высокоуровневый язык программирования. Требуется для начальной подготовки исходных кодов. Установка не обязательная, но желательная. Про третью версию Python официальной информации нет, у меня установлены обе версии для опытов и "Path" системы направлен на вторую версию. Установку Python коротко разберу ниже. Python бесплатно можно взять на [официальном сайте](http://python.org/).
- "**Cygwin**" — Unix-подобная среда и интерфейс командной строки для систем Microsoft Windows. Требуется для работы с исходными кодами, их подготовки, обновлением и проверки на ошибки. Сам инструмент бесплатно доступен на [официальной странице](http://www.cygwin.com/). Его установку я распишу в следующих пунктах.
- "**TortoiseSVN**" — Клиент Subversion под систему Windows. Установка не обязательная, но желательная. Требуется для более простого обновления пакета "depot_tools" из официального репозитория SVN от корпорации Google. Бесплатно доступен на [официальной странице](http://tortoisesvn.net/).
Над установкой Microsoft Visual Studio, Microsoft Windows SDK и Microsoft DirectX SDK я подробно останавливаться не буду. Установка данных программных комплектов проста, и особой сложности вызывать не должна. В случае возникновения каких-либо проблем, имеются огромные сообщества разработчиков, которые помогут с установкой.
**На установке пакета Python'а я остановлюсь поподробнее:**
Во-первых, путь установки Python'а не должен содержать русскоязычный текст, это может вызвать много ошибок.
Во-вторых, после установки основного пакета, не забудьте добавить имя каталога в список путей, по которому операционная система ищет исполняемые файлы. Чтобы это сделать, требуется:
1. Запустите "_Панель Управления_" и выберите пиктограмму "_Система_";
2. Выберите "_Дополнительные настройки системы_";
3. Перейдите во вкладку "_Дополнительно_" и щёлкните на кнопке "_Переменные среды_";
4. В содержимом окна "_Системные переменные_" найдите строку "_Path_";
5. Добавьте туда путь до вашего каталога Python.
В моём случае этот путь выглядел так: `C:\Program Files (x86)\Python2`. Пути каталогов должны разделяться знаком `;`, по этому не забудьте перед последним записанным каталогом дописать `;` (без кавычек);
Чтобы проверить работоспособность языка Python в Вашей системе сразу после установки, откройте командную строку Windows и введите команду:
```bash
python --version
```
На экране должно появиться сообщение с версией Python, которая используется в Вашей системе по-умолчанию.
**Теперь подготовим каталоги.** Каталог исходных кодов в моём случае располагается на диске `C:\`, потому что желательно не использовать пробелы в пути адреса до исходных кодов и мой пользователь в операционной системе состоит из русскоязычных символов.
На диске `C:\` я создал каталог `OpenSource`, в нём я создал каталог `ChromiumProjects`, в котором появилось два подкаталога `depot_tools` и `trunk`. Т.е. система каталогов выглядит так:
- `C:\OpenSource\ChromiumProjects\depot_tools` — Пакет для работы с исходным кодом;
- `C:\OpenSource\ChromiumProjects\trunk` — Место хранения исходных кодов;
В случае использование других каталогов в вашей системе, используйте собственные пути, подставляя их в мои примеры.
Так же крайне рекомендуется отключить индексирование системы в данных каталогах, потому что это вызовет фатальные ошибки работы пакета "depot*tools". Чтобы это сделать, откройте "*Панель управления*", выберите пиктограмму "*Параметры индексирования*", нажмите на кнопку "*Изменить\_" и снимите галочку с каталога, содержащий утилиту "depot_tools".
Первоначальную установку и настройку системы можно считать оконченной. Переходим к следующему шагу.
## Установка программы "Cygwin"
Первым делом получите установочный файл последней версии по этой [ссылке](http://cygwin.com/setup.exe). Установочный файл во время установки скачивает необходимые пакеты из интернета. Когда запустите файл, следуйте инструкциям. После выбор зеркала пакетов, Вам покажут список доступных пакетов с зеркала. Требуется найти и отметить для установки следующие пакеты:
- `apache`;
- `bc`;
- `bison`;
- `curl`;
- `diffutils`;
- `e2fsprogs`;
- `emacs`;
- `flex`;
- `gcc`;
- `gperf`;
- `keychain`;
- `make`;
- `nano`;
- `openssh`;
- `patch`;
- `perl`;
- `perl-libwin32`;
- `python`;
- `rebase`;
- `rsync`;
- `ruby`;
- `subversion`;
- `unzip`;
- `vim`;
- `zip`;
Имена пакетов должны полностью совпадать. Воспользуйтесь поиском по пакетам, включённым в саму программу установки. Это должно сильно облегчить задачу.
Актуальный список пакетов, требующихся для установки, Вы всегда можете найти в [официальном скрипте](http://trac.webkit.org/browser/trunk/Tools/CygwinDownloader/cygwin-downloader.py) установки, в поле `required_packages`.
После установки приложения, требуется внести путь до папки с исполняемыми файлами в переменную "Path". Сделать это можно в точности, как после установки пакета Python'а, описанного чуть выше в данной статье. Только в отличии от Python'а, требуется указать путь до папки `bin`, находящейся в корневом каталоге приложения "Cygwin". В моём случае этот путь выглядел так: `C:\Program Files (x86)\Cygwin\bin`.
После установки и проверки приложения "Cygwin", можно переходить к следующему шагу, настройке и установки пакета "depot_tools".
## Установка пакета "depot_tools"
1. Перейдите в каталог, который Вы определили для хранения пакета "depot_tools";
2. Находясь в папке, нажмите правую кнопку мыши в любом свободном месте и контекстном меню выберите пункт "_SVN Checkout_";
3. В пути URL репозитория, указывайте путь: `http://src.chromium.org/svn/trunk/tools/depot_tools`;
Если проблем не возникнет, пойдёт установка последней ревизии данного пакета. По окончанию скачивания пакета, путь до исполняемых файлов пакета следует указать в переменной "Path", по аналогии с программой "Cygwin" и пакетом "Python". В моём случае, путь выглядел так: `C:\OpenSource\ChromiumProjects\depot_tools`.
Если всё прошло успешно, можно перейти к заключительной части статьи, получения и подготовка исходных кодов браузера "Chromium".
## Получение и подготовка исходных кодов
Перейдите по данной [ссылке](http://chromium-browser-source.commondatastorage.googleapis.com/chromium_tarball.html) и скачайте архив с исходными кодами. Вы получите архив с именем "_chromium.r**XXXXX**.tgz_", где **XXXXX** — номер стабильной последней версии.
Распакуйте из архива папку `src` в наш каталог `trunk`. Процесс займёт продолжительное время, потому что объём исходных кодов ~4 Гб. По окончанию распаковки, откройте терминал "Cygwin".
В открытом терминале теперь необходимо пройти в каталог `src`, который получится после распаковки исходных кодов. Переход по каталогам в терминале осуществляется программой `cd`. Чтобы попасть на диск `C:\`, требуется в терминале набрать команду:
```bash
cd "C:/"
```
Чтобы вернуться на каталог выше, требуется набрать команду:
```bash
cd ..
```
В Unix-терминалах для работы с каталогами используется обратная косая черта. По этому, чтобы перейти в требуемый каталог, на моём примере, команда будет выглядеть так:
```bash
cd "C:/OpenSource/ChromiumProjects/trunk/src"
```
Теперь, когда мы в требуемой папке, надо применить команду для первоначальной настройки исходных кодов. Для этого ведите команду:
```bash
gclient sync --force
```
После выполнения данной команды, требуется подготовить исходные коды для работы с "_Visual Studio 2010_". Для этого вводим команду:
```bash
gclient runhooks --force
```
По окончанию выполнения данной команды, мы получаем готовые к работе исходные коды. Чтобы начать с ними работу, откройте Вашу "Visual Studio", выберите "_Открыть проект_" и откройте файл `chrome.sln`, который находится в папке `chrome`, находящейся в папке исходных кодов. В моём случае, полный путь до файла выглядит так: `C:\OpenSource\ChromiumProjects\trunk\src\chrome\chrome.sln`.
На этом работу можно считать законченной.
## Обновление
Чтобы обновить пакет "depot*tools", требуется зайти в каталог, содержащий данный пакет, щёлкнуть правой кнопкой мыши и в контекстном меню выбрать "\_SVN Update*". "TortoiseSVN" обновит данные каталога до последней ревизии пакета.
Для обновления исходных кодов "Chromium", требуется открыть терминал "Cygwin", перейти в каталог с исходными кодами и ввести команду:
```bash
gclient sync
```
## Заключение
Спасибо, что прочитали и большое спасибо, если воспользовались моей инструкцией. Я всегда рад Вашим комментариям с вопросами, уточнениями и предложениями.
## Полезные ссылки
- [http://dev.chromium.org/Home](http://dev.chromium.org/Home) — Официальная страница проекта "The Chromium Projects";
- [http://dev.chromium.org/developers/how-tos/build-instructions-windows](http://dev.chromium.org/developers/how-tos/build-instructions-windows) — Официальная страница по подготовке операционной системы Windows, перед работой с исходными кодами;
- [http://dev.chromium.org/developers/how-tos/get-the-code](http://dev.chromium.org/developers/how-tos/get-the-code) — Официальная инструкция по получению, настройке и подготовке исходных кодов проекта "The Chromium Projects";
- [http://dev.chromium.org/developers/how-tos/install-depot-tools](http://dev.chromium.org/developers/how-tos/install-depot-tools) — Официальная инструкция по установке и настройке пакета "depot_tools";
- [http://dev.chromium.org/developers/how-tos/cygwin](http://dev.chromium.org/developers/how-tos/cygwin) — Страница по установки и настройке терминала "Cygwin";
- [http://groups.google.com/a/chromium.org/group/chromium-discuss/topics](http://groups.google.com/a/chromium.org/group/chromium-discuss/topics) — Официальная дискуссия разработчиков браузера "Chromium";

View File

@ -0,0 +1,23 @@
---
title: "Установка Moodle в Fedora"
author: "Valentin Popov"
pubDate: "2018-07-23"
description: "Решение проблем установки Moodle из-за SELinux: как настроить правила доступа для устранения ошибок в веб-интерфейсе и при работе с cURL. Практические советы и команды."
---
Во время установки Moodle, сталкиваешься со следующими проблемами:
- Веб-интерфейс не продолжает установку после настройки базы данных;
- Если установить через консольный интерфейс, проявляются артефакты;
- Нет доступа к сети, появляется ошибка `unexpected cURL error`.
Главная причина, это [SELinux](https://en.wikipedia.org/wiki/Security-Enhanced_Linux). Решение, это настроить правила доступа:
```bash
# Доступ к сторонним каталогам и сети
/usr/sbin/setsebool -P httpd_can_network_connect true
/usr/sbin/setsebool -P httpd_enable_homedirs true
# Смена контекста безопасности
/usr/bin/chcon -R -h -t httpd_sys_content_t /path/to/moodle
/usr/bin/chcon -R -h -t httpd_sys_script_rw_t /path/to/moodle_data
```

View File

@ -1,31 +1,26 @@
--- ---
description: >- title: "Компиляция Rust на TL-MR3020"
Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера. author: "Valentin Popov"
title: Компиляция Rust на TL-MR3020 pubDate: "2023-05-01"
author: valentineus description: 'Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера.'
layout: post
--- ---
Информация в статье актуальна для дистрибутива [Fedora Linux 38](https://docs.fedoraproject.org/en-US/releases/f38/), прошивки [OpenWrt 22.03.4](https://openwrt.org/releases/22.03/notes-22.03.4) и устройства [TP-Link TL-MR3020](https://www.tp-link.com/en/home-networking/3g-4g-router/tl-mr3020/) ревизии v3.20. Информация в статье актуальна для дистрибутива [Fedora Linux 38](https://docs.fedoraproject.org/en-US/releases/f38/), прошивки [OpenWrt 22.03.4](https://openwrt.org/releases/22.03/notes-22.03.4) и устройства [TP-Link TL-MR3020](https://www.tp-link.com/en/home-networking/3g-4g-router/tl-mr3020/) ревизии v3.20.
Потребуется: Потребуется:
- Установленный [rustup](https://rustup.rs/) инструментарий. - Установленный [rustup](https://rustup.rs/) инструментарий.
- Установленный пакет [cross-rs](https://github.com/cross-rs/cross) для кросс-компиляции. - Установленный пакет [cross-rs](https://github.com/cross-rs/cross) для кросс-компиляции.
- Упаковщик исполняемых файлов [upx](https://github.com/upx/upx). - Упаковщик исполняемых файлов [upx](https://github.com/upx/upx).
- Контейнеризатор [Docker](https://docs.docker.com/engine/install/) (рекомендуется) или [Podman](https://podman.io/getting-started/installation). - Контейнеризатор [Docker](https://docs.docker.com/engine/install/) (рекомендуется) или [Podman](https://podman.io/getting-started/installation).
- SSH подключение к маршрутизатору. - SSH подключение к маршрутизатору.
- Установленный [SFTP сервер](https://openwrt.org/docs/guide-user/services/nas/sftp.server) на TL-MR3020. - Установленный [SFTP сервер](https://openwrt.org/docs/guide-user/services/nas/sftp.server) на TL-MR3020.
> Требуется rustup инструментарий с официального сайта. > Требуется rustup инструментарий с официального сайта. Rust и Cargo из репозитория дистрибутива не подойдут. Пакет кросс-компиляции требует rustup, который в репозиториях дистрибутива отсутствует.
Rust и Cargo из репозитория дистрибутива не подойдут.
Пакет кросс-компиляции требует rustup, который в репозиториях дистрибутива отсутствует.
## "Hello, World!" ver. 1 ## "Hello, World!" ver. 1
Начнем с базы. Начнем с базы. Соберем и запустим "Hello, World" на маршрутизаторе. Инициализируем проект на Rust:
Соберем и запустим "Hello, World" на маршрутизаторе.
Инициализируем проект на Rust:
```bash ```bash
cargo init --bin ramips-rs cargo init --bin ramips-rs
@ -56,8 +51,7 @@ cat /proc/cpuinfo
# VCEI exceptions : not available # VCEI exceptions : not available
``` ```
Видим, что процессор архитектуры MIPS. Видим, что процессор архитектуры MIPS. Теперь определим целевую архитектуру для компиляции:
Теперь определим целевую архитектуру для компиляции:
```bash ```bash
rustup target list | grep mips rustup target list | grep mips
@ -71,15 +65,13 @@ rustup target list | grep mips
# mipsel-unknown-linux-musl # mipsel-unknown-linux-musl
``` ```
Опытным путем определяем, что в случае с TL-MR3020 v3.20 подходит архитектура `mipsel-unknown-linux-musl`. Опытным путем определяем, что в случае с TL-MR3020 v3.20 подходит архитектура `mipsel-unknown-linux-musl`. Далее компилируем проект под целевую архитектуру:
Далее компилируем проект под целевую архитектуру:
```bash ```bash
cross build --release --target mipsel-unknown-linux-musl cross build --release --target mipsel-unknown-linux-musl
``` ```
Получаем исполняемый бинарный файл, который загружаем и запускаем на маршрутизаторе. Получаем исполняемый бинарный файл, который загружаем и запускаем на маршрутизаторе. Выгружаем в раздел `/tmp`, потому что доступной памяти на основном разделе меньше двух мегабайт.
Выгружаем в раздел `/tmp`, потому что доступной памяти на основном разделе меньше двух мегабайт.
```bash ```bash
scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/ scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/
@ -89,12 +81,9 @@ ssh openwrt /tmp/ramips-rs
## Оптимизация размера бинарника ## Оптимизация размера бинарника
После сборки и запуска "Hello, World" можно обратить внимание, что исполняемый файл весит __4.1 мегабайта__. После сборки и запуска "Hello, World" можно обратить внимание, что исполняемый файл весит **4.1 мегабайта**. Для устройства с 8 мегабайтами постоянной памяти это катастрофически много.
Для устройства с 8 мегабайтами постоянной памяти это катастрофически много.
Уменьшим размер исполняемого файла до приемлемого минимума. Уменьшим размер исполняемого файла до приемлемого минимума. Для этого настроим release профиль сборки и компиляции проекта. Дополним Cargo.toml файл:
Для этого настроим release профиль сборки и компиляции проекта.
Дополним Cargo.toml файл:
```toml ```toml
[profile.release] [profile.release]
@ -105,23 +94,19 @@ panic = "abort" # Уменьшает бинарник да 332K
codegen-units = 1 # Включает дополнительные оптимизации кода codegen-units = 1 # Включает дополнительные оптимизации кода
``` ```
Получаем исполняемый файл размером в __332 килобайта__. Получаем исполняемый файл размером в **332 килобайта**. Далее сжимаем исполняемый файл инструментом upx:
Далее сжимаем исполняемый файл инструментом upx:
```bash ```bash
upx --best --lzma target/mipsel-unknown-linux-musl/release/ramips-rs upx --best --lzma target/mipsel-unknown-linux-musl/release/ramips-rs
``` ```
И получаем исходный файл размером в __118 килобайт__. И получаем исходный файл размером в **118 килобайт**. Приемлемый результат.
Приемлемый результат.
Сильнее уменьшить бинарник можно отказом от стандартной std библиотеки и другими экстремальными unsafe приемами, что не подходит в моем случае. Сильнее уменьшить бинарник можно отказом от стандартной std библиотеки и другими экстремальными unsafe приемами, что не подходит в моем случае.
## "Hello, World!" ver. 2 ## "Hello, World!" ver. 2
Теперь сделаем пример посерьезней. Теперь сделаем пример посерьезней. Например, асинхронный TCP сервер. Подключаем зависимости:
Например, асинхронный TCP сервер.
Подключаем зависимости:
```toml ```toml
[dependencies] [dependencies]
@ -167,9 +152,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
} }
``` ```
Проверяем, компилируем и сжимаем. Проверяем, компилируем и сжимаем. Получаем бинарник размером в **236 килобайт**. Теперь загружаем в устройство, запускаем и проверяем:
Получаем бинарник размером в __236 килобайт__.
Теперь загружаем в устройство, запускаем и проверяем:
```bash ```bash
scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/ scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/
@ -183,7 +166,7 @@ curl -L "http://10.0.0.2:3000"
## Полезные ссылки и источники ## Полезные ссылки и источники
- [Building Rust code for my OpenWrt Wi-Fi router](https://blog.dend.ro/building-rust-for-routers/) - [Building Rust code for my OpenWrt Wi-Fi router](https://blog.dend.ro/building-rust-for-routers/)
- [Cross Compile Rust For OpenWRT](https://www.kiloleaf.com/posts/cross-compile-rust-for-openwrt/) - [Cross Compile Rust For OpenWRT](https://www.kiloleaf.com/posts/cross-compile-rust-for-openwrt/)
- [Minimizing Rust Binary Size](https://github.com/johnthagen/min-sized-rust) - [Minimizing Rust Binary Size](https://github.com/johnthagen/min-sized-rust)
- [Кросс-компиляция программ Rust для запуска на маршрутизаторе](https://dzen.ru/media/nuancesprog.ru/krosskompiliaciia-programm-rust-dlia-zapuska-na-marshrutizatore-5f6457b8bdfa745d402cd1ec) - [Кросс-компиляция программ Rust для запуска на маршрутизаторе](https://dzen.ru/media/nuancesprog.ru/krosskompiliaciia-programm-rust-dlia-zapuska-na-marshrutizatore-5f6457b8bdfa745d402cd1ec)

13
src/content/config.ts Normal file
View File

@ -0,0 +1,13 @@
import { defineCollection, z } from "astro:content";
const blog = defineCollection({
type: "content",
schema: z.object({
author: z.string(),
description: z.string(),
pubDate: z.coerce.date(),
title: z.string(),
}),
});
export const collections = { blog };

9
src/env.d.ts vendored Normal file
View File

@ -0,0 +1,9 @@
/// <reference path="../.astro/types.d.ts" />
interface ImportMetaEnv {
readonly DEFAULT_TITLE: string;
readonly DEFAULT_DESCRIPTION: string;
}
interface ImportMeta {
readonly env: ImportMetaEnv;
}

View File

@ -0,0 +1,30 @@
---
import Analytics from "../components/Analytics.astro";
import Footer from "../components/Footer.astro";
import Head from "../components/Head.astro";
import Header from "../components/Header.astro";
import "../scss/global.scss";
type Props = {
readonly description?: string;
readonly title?: string;
};
const { description, title } = Astro.props;
---
<html lang="ru">
<Head
description={description ?? import.meta.env.DEFAULT_DESCRIPTION}
title={title ?? import.meta.env.DEFAULT_TITLE}
/>
<body>
<Header />
<main>
<slot />
</main>
<Footer />
<Analytics title={title ?? import.meta.env.DEFAULT_TITLE} />
</body>
</html>

30
src/pages/[...page].astro Normal file
View File

@ -0,0 +1,30 @@
---
import type { GetStaticPaths, InferGetStaticPropsType } from "astro";
import { getCollection } from "astro:content";
import Layout from "../layouts/BaseLayout.astro";
import Pagination from "../components/Pagination.astro";
import PostSummary from "../components/PostSummary.astro";
type Props = InferGetStaticPropsType<typeof getStaticPaths>;
export const getStaticPaths = (async ({ paginate }) => {
const posts = await getCollection("blog");
posts.sort((a, b) => b.data.pubDate.getTime() - a.data.pubDate.getTime());
return paginate(posts, {
pageSize: 10,
});
}) satisfies GetStaticPaths;
const { page } = Astro.props;
---
<Layout>
<section style={{ "margin-top": "3rem" }}>
{page.data.map((post) => <PostSummary post={post} />)}
</section>
<section>
<Pagination nextUrl={page.url.next} prevUrl={page.url.prev} />
</section>
</Layout>

View File

@ -0,0 +1,49 @@
---
import { type CollectionEntry, getCollection } from "astro:content";
import Comments from "../../components/Comments.astro";
import Layout from "../../layouts/BaseLayout.astro";
type Props = CollectionEntry<"blog">;
export async function getStaticPaths() {
const posts = await getCollection("blog");
return posts.map((post) => ({
params: { slug: post.slug },
props: post,
}));
}
const post = Astro.props;
const { Content, remarkPluginFrontmatter } = await post.render();
---
<style>
.header {
text-align: center;
}
</style>
<Layout description={post.data.description} title={post.data.title}>
<article>
<section class="header">
<h1>{post.data.title}</h1>
<p>
<small>
Posted
<time datetime={post.data.pubDate.toISOString()}>{post.data.pubDate.toDateString()}</time>
&nbsp;by&nbsp;{post.data.author}&nbsp;
<strong>{remarkPluginFrontmatter.minutesRead}</strong>
</small>
</p>
</section>
<section>
<Content />
</section>
<section>
<Comments />
</section>
</article>
</Layout>

20
src/pages/feed.xml.js Normal file
View File

@ -0,0 +1,20 @@
import { getCollection } from "astro:content";
import rss from "@astrojs/rss";
export async function GET(context) {
const posts = await getCollection("blog");
return rss({
customData: `<language>ru-ru</language>`,
description: import.meta.env.DEFAULT_DESCRIPTION,
items: posts.map((post) => ({
customData: post.data.customData,
description: post.data.description,
link: `/blog/${post.slug}`,
pubDate: post.data.pubDate,
title: post.data.title,
})),
site: context.site,
title: import.meta.env.DEFAULT_TITLE,
});
}

View File

@ -0,0 +1,11 @@
import type { RemarkPlugin } from "@astrojs/markdown-remark";
import { toString } from "mdast-util-to-string";
import getReadingTime from "reading-time";
export function remarkReadingTime(): RemarkPlugin {
return function (tree, { data }) {
const textOnPage = toString(tree);
const readingTime = getReadingTime(textOnPage);
data.astro.frontmatter.minutesRead = readingTime.text;
};
}

256
src/scss/_framework.scss Normal file
View File

@ -0,0 +1,256 @@
*,
*::after,
*::before {
box-sizing: border-box;
text-size-adjust: 100%;
}
html {
font-family:
"Jost",
-apple-system,
blinkmacsystemfont,
"Segoe UI",
roboto,
"Helvetica Neue",
arial,
"Noto Sans",
sans-serif,
"Apple Color Emoji",
"Segoe UI Emoji",
"Segoe UI Symbol",
"Noto Color Emoji";
font-size: 62.5%;
min-height: 100%;
overflow-y: scroll;
}
body {
background-color: $colorBg;
color: $colorText;
font-size: $fontSizeBase;
font-synthesis: weight style small-caps;
font-weight: 400;
line-height: 1.5;
margin: auto;
max-width: 52em;
min-height: 100vh;
padding: 4em;
position: relative;
text-rendering: optimizelegibility;
}
@media (width <=684px) {
body {
font-size: $fontSizeBase * 0.85;
padding: 4em 1em 2em;
}
}
h1,
h2,
h3,
h4,
h5,
h6 {
font-weight: 700;
line-height: 1.1;
margin-bottom: 1.5rem;
margin-top: 3rem;
overflow-wrap: break-word;
word-break: break-word;
word-wrap: break-word;
}
h1 {
font-size: 2.35em;
}
h2 {
font-size: 2em;
}
h3 {
font-size: 1.75em;
}
h4 {
font-size: 1.5em;
}
h5 {
font-size: 1.25em;
}
h6 {
font-size: 1em;
}
p {
margin-bottom: 2.5rem;
margin-top: 0;
}
small,
sub,
sup {
font-size: 75%;
}
hr {
border-color: $colorBlossom;
}
a {
color: $colorBlossom;
text-decoration: inherit;
transition: color 0.25s;
&:visited {
color: $colorBlossom;
}
&:active,
&:focus,
&:hover {
opacity: 0.5;
}
}
ul {
margin-bottom: 2.5rem;
margin-top: 0;
padding-left: 1.4em;
}
li {
margin-bottom: 0.4em;
}
blockquote {
background-color: $colorBgAlt;
border-left: 5px solid $colorBlossom;
margin-bottom: 2.5rem;
margin-left: 0;
margin-right: 0;
padding: 0.8em 0.8em 0.8em 1em;
}
blockquote p {
margin-bottom: 0;
}
img,
video {
display: block;
height: auto;
margin-bottom: 2.5rem;
margin-top: 0;
max-width: 100%;
}
pre {
background-color: $colorBgAlt;
border-radius: 4px;
border: 1px solid $colorBgAlt;
display: block;
font-size: 0.9em;
margin-bottom: 2.5rem;
margin-top: 0;
overflow-x: auto;
padding: 1em;
}
code,
kbd,
samp {
background-color: $colorBgCode;
border-radius: 4px;
font-size: 0.9em;
padding: 0 0.2em;
white-space: pre-wrap;
}
pre > code {
background-color: transparent;
font-size: 1em;
padding: 0;
white-space: pre;
}
table {
border-collapse: collapse;
text-align: justify;
width: 100%;
}
td,
th {
border-bottom: 1px dashed $colorBlossom;
padding: 0.5em;
}
textarea {
width: 100%;
}
.button,
button,
input[type="submit"],
input[type="reset"],
input[type="button"] {
background-color: $colorBlossom;
border: 1px solid $colorBlossom;
border-radius: 1px;
box-sizing: border-box;
color: $colorBg;
cursor: pointer;
display: inline-block;
padding: 5px 10px;
text-align: center;
text-decoration: none;
white-space: nowrap;
&[disabled] {
cursor: default;
opacity: 0.5;
}
&:focus:enabled,
&:hover:enabled {
background-color: $colorFade;
border-color: $colorFade;
color: $colorBg;
outline: 0;
}
}
textarea,
select,
input {
background-color: $colorBgAlt;
border: 1px solid $colorBgAlt;
border-radius: 4px;
box-shadow: none;
box-sizing: border-box;
color: $colorText;
margin-bottom: 10px;
padding: 6px 10px;
&:focus {
border: 1px solid $colorBlossom;
outline: 0;
}
}
input[type="checkbox"]:focus {
outline: 1px dotted $colorBlossom;
}
label,
legend,
fieldset {
display: block;
font-weight: 600;
margin-bottom: 0.5rem;
}

21
src/scss/_print.scss Normal file
View File

@ -0,0 +1,21 @@
@media print {
body {
padding: 0;
}
audio,
embed,
footer,
form,
header,
iframe,
nav,
object,
video {
display: none;
}
img {
max-width: 500px;
}
}

7
src/scss/_variables.scss Normal file
View File

@ -0,0 +1,7 @@
$colorBg: #212529;
$colorBgAlt: hwb(0deg 0% 100% / 20%);
$colorBgCode: #3b3d42;
$colorBlossom: #6da13f;
$colorFade: #598332;
$colorText: #dee2e6;
$fontSizeBase: 1.8rem;

3
src/scss/global.scss Normal file
View File

@ -0,0 +1,3 @@
@import "variables";
@import "framework";
@import "print";

3
tsconfig.json Normal file
View File

@ -0,0 +1,3 @@
{
"extends": "astro/tsconfigs/strict"
}