Compare commits
47 Commits
ecf9a15e77
...
0e80f4e4d7
Author | SHA1 | Date | |
---|---|---|---|
0e80f4e4d7 | |||
b9d8d5ca28 | |||
61e7f5d5b4 | |||
9ff6f2cd0e | |||
cf85f10724 | |||
43f80a7b6e | |||
5217bcb24c | |||
4a821edd50 | |||
d4a6772ec5 | |||
b8fd186801 | |||
33c9464dad | |||
b16d8ce36c | |||
65ee69c645 | |||
fd054f0fa4 | |||
de1885fe8f | |||
3591bebabf | |||
4ac7da1231 | |||
a93400f090 | |||
3376c53b2e | |||
0b57b888ca | |||
4ba339984d | |||
70fa9c2033 | |||
c5affebc6f | |||
dc6c24e56a | |||
6494405a04 | |||
c89ed0f7f9 | |||
97aa90a605 | |||
d3034596b7 | |||
be3616d2d6 | |||
e2f0aecf95 | |||
af70075588 | |||
97ba8666c8 | |||
49c2ffa583 | |||
1a67c77d9d | |||
2b8ddeda4f | |||
b9f5d65559 | |||
492d4965c8 | |||
396f3dcc30 | |||
2a86fd34f6 | |||
9829c0e5fa | |||
6fbdcc94b6 | |||
2f362eaf09 | |||
17c3115a06 | |||
7ba2de7148 | |||
7770a0852c | |||
536956f0f3 | |||
7eff3fde57 |
@ -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
|
@ -1,15 +1,15 @@
|
||||
{
|
||||
"name": "Zola Dev Container",
|
||||
"build": {
|
||||
"dockerfile": "Dockerfile"
|
||||
},
|
||||
"forwardPorts": [
|
||||
1111
|
||||
],
|
||||
"image": "mcr.microsoft.com/devcontainers/javascript-node:22",
|
||||
"forwardPorts": [4321],
|
||||
"portsAttributes": {
|
||||
"1111": {
|
||||
"4321": {
|
||||
"label": "Application",
|
||||
"onAutoForward": "notify"
|
||||
}
|
||||
},
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": ["astro-build.astro-vscode", "esbenp.prettier-vscode"]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
2
.env
Normal file
2
.env
Normal file
@ -0,0 +1,2 @@
|
||||
DEFAULT_TITLE=Valentin Popov’s Technology Blog
|
||||
DEFAULT_DESCRIPTION=Tech insights and coding best practices from an OpenSource enthusiast and ethical hacker.
|
14
.gitea/workflows/main.yml
Normal file
14
.gitea/workflows/main.yml
Normal 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
|
@ -1,26 +1,16 @@
|
||||
name: RenovateBot
|
||||
|
||||
on:
|
||||
schedule:
|
||||
- cron: "@daily"
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
|
||||
jobs:
|
||||
renovate:
|
||||
container: ghcr.io/renovatebot/renovate:37
|
||||
container: ghcr.io/renovatebot/renovate:38
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Run renovate
|
||||
run: |
|
||||
renovate
|
||||
- uses: actions/checkout@v4
|
||||
- run: renovate
|
||||
env:
|
||||
LOG_LEVEL: debug
|
||||
RENOVATE_CONFIG_FILE: renovate.config.cjs
|
||||
RENOVATE_REPOSITORIES: ${{ gitea.repository }}
|
||||
RENOVATE_TOKEN: ${{ secrets.RENOVATE_TOKEN }}
|
||||
|
29
.gitignore
vendored
29
.gitignore
vendored
@ -1,5 +1,24 @@
|
||||
_site
|
||||
.sass-cache
|
||||
.jekyll-cache
|
||||
.jekyll-metadata
|
||||
vendor
|
||||
# build output
|
||||
dist/
|
||||
# generated types
|
||||
.astro/
|
||||
|
||||
# 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
44
.prettierrc.mjs
Normal 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,
|
||||
};
|
46
.renovaterc
46
.renovaterc
@ -1,24 +1,24 @@
|
||||
{
|
||||
"assignees": [
|
||||
"valentineus"
|
||||
],
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
":disableDependencyDashboard"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "all digest updates",
|
||||
"groupSlug": "all-digest",
|
||||
"matchPackagePatterns": [
|
||||
"*"
|
||||
],
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch",
|
||||
"pin",
|
||||
"digest"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
"assignees": [
|
||||
"valentineus"
|
||||
],
|
||||
"extends": [
|
||||
"config:recommended",
|
||||
":disableDependencyDashboard"
|
||||
],
|
||||
"packageRules": [
|
||||
{
|
||||
"groupName": "all digest updates",
|
||||
"groupSlug": "all-digest",
|
||||
"matchPackagePatterns": [
|
||||
"*"
|
||||
],
|
||||
"matchUpdateTypes": [
|
||||
"minor",
|
||||
"patch",
|
||||
"pin",
|
||||
"digest"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
4
.vscode/extensions.json
vendored
Normal file
4
.vscode/extensions.json
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
{
|
||||
"recommendations": ["astro-build.astro-vscode"],
|
||||
"unwantedRecommendations": []
|
||||
}
|
11
.vscode/launch.json
vendored
Normal file
11
.vscode/launch.json
vendored
Normal 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"
|
||||
}
|
||||
]
|
||||
}
|
41
Gemfile
41
Gemfile
@ -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"
|
297
Gemfile.lock
297
Gemfile.lock
@ -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
|
@ -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.
|
20
README.md
20
README.md
@ -1,22 +1,16 @@
|
||||
# Personal 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.
|
||||
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.
|
||||
|
||||
Principles of site development:
|
||||
|
||||
* Lightness and minimalism.
|
||||
The site is designed to store information, it's not a heavy application;
|
||||
- Lightness and minimalism. The site is designed to store information, it's not a heavy application;
|
||||
|
||||
* Maximum cross-platform.
|
||||
Information should be read from any device and software;
|
||||
- Maximum cross-platform. Information should be read from any device and software;
|
||||
|
||||
* Focusing on content perception.
|
||||
Only useful information, nothing superfluous;
|
||||
- Focusing on content perception. Only useful information, nothing superfluous;
|
||||
|
||||
* No JS on the site.
|
||||
The site should be completely safe for the user;
|
||||
- No JS on the site. The site should be completely safe for the user;
|
||||
|
||||
## 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" />
|
||||
|
||||
[MIT](LICENSE.txt).
|
||||
Copyright (c)
|
||||
[Valentin Popov](https://valentineus.link/).
|
||||
[MIT](LICENSE.txt). Copyright (c) [Valentin Popov](https://valentineus.link/).
|
||||
|
58
_config.yml
58
_config.yml
@ -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
|
@ -1,7 +0,0 @@
|
||||
adrianhenke:
|
||||
name: Adrian Henke
|
||||
email: ""
|
||||
|
||||
valentineus:
|
||||
name: Valentin Popov
|
||||
email: valentin@popov.link
|
@ -1,5 +0,0 @@
|
||||
- title: "Home"
|
||||
path: "/"
|
||||
|
||||
- title: "Blog"
|
||||
path: "/blog/"
|
@ -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>— 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>
|
@ -1,17 +0,0 @@
|
||||
{%- assign author = site.data.authors[page.author] -%}
|
||||
|
||||
{%- if author -%}
|
||||
|
||||
by
|
||||
|
||||
{%- 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 -%}
|
||||
|
||||
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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>
|
@ -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 -%}
|
@ -1,5 +0,0 @@
|
||||
{%- capture styles -%}
|
||||
{%- include styles.scss -%}
|
||||
{%- endcapture -%}
|
||||
|
||||
<style>{{- styles | scssify -}}</style>
|
@ -1,10 +0,0 @@
|
||||
// Base
|
||||
@import "reset";
|
||||
@import "variables";
|
||||
@import "framework";
|
||||
@import "print";
|
||||
|
||||
// Modules
|
||||
@import "highlighter";
|
||||
@import "navbar";
|
||||
@import "welcome";
|
@ -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 %}
|
@ -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>
|
@ -1,5 +0,0 @@
|
||||
---
|
||||
layout: default
|
||||
---
|
||||
|
||||
{{- content -}}
|
@ -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 -%}
|
||||
‐
|
||||
<strong>{%- include reading-time.html -%}</strong>
|
||||
</small>
|
||||
</p>
|
||||
</div>
|
||||
|
||||
{{- content -}}
|
||||
|
||||
{%- include comments.html -%}
|
@ -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>
|
@ -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>—</span>
|
||||
<a href="{{- post.url | relative_url | url_escape -}}">{{- post.title | strip | normalize_whitespace | xml_escape -}}</a>
|
||||
</li>
|
||||
{%- endfor -%}
|
||||
</ul>
|
@ -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>
|
@ -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 }}
|
@ -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";
|
@ -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
|
||||
```
|
@ -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 🙂
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
@ -1,21 +0,0 @@
|
||||
@media print {
|
||||
body {
|
||||
padding: 0;
|
||||
}
|
||||
|
||||
audio,
|
||||
embed,
|
||||
footer,
|
||||
form,
|
||||
header,
|
||||
iframe,
|
||||
nav,
|
||||
object,
|
||||
video {
|
||||
display: none;
|
||||
}
|
||||
|
||||
img {
|
||||
max-width: 500px;
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
@ -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;
|
@ -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 |
@ -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()
|
||||
})
|
||||
})();
|
1
assets/javascript/html5shiv-3.7.3.min.js
vendored
1
assets/javascript/html5shiv-3.7.3.min.js
vendored
@ -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);
|
1
assets/javascript/respond-1.4.2.min.js
vendored
1
assets/javascript/respond-1.4.2.min.js
vendored
@ -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='­<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
26
astro.config.mjs
Normal 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
10242
package-lock.json
generated
Normal file
File diff suppressed because it is too large
Load Diff
35
package.json
Normal file
35
package.json
Normal 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
8
postcss.config.cjs
Normal file
@ -0,0 +1,8 @@
|
||||
module.exports = {
|
||||
plugins: [
|
||||
require("autoprefixer"),
|
||||
require("cssnano")({
|
||||
preset: "advanced",
|
||||
}),
|
||||
],
|
||||
};
|
9
public/favicon.svg
Normal file
9
public/favicon.svg
Normal 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
4
public/robots.txt
Normal file
@ -0,0 +1,4 @@
|
||||
User-agent: *
|
||||
Allow: /
|
||||
|
||||
Sitemap: https://popov.link/sitemap-index.xml
|
17
src/components/Analytics.astro
Normal file
17
src/components/Analytics.astro
Normal 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>
|
31
src/components/Comments.astro
Normal file
31
src/components/Comments.astro
Normal 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>
|
60
src/components/Footer.astro
Normal file
60
src/components/Footer.astro
Normal 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>© {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
24
src/components/Head.astro
Normal 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>
|
64
src/components/Header.astro
Normal file
64
src/components/Header.astro
Normal 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>
|
35
src/components/Pagination.astro
Normal file
35
src/components/Pagination.astro
Normal 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}>< Prev</a>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
{
|
||||
nextUrl && (
|
||||
<span>
|
||||
<a href={nextUrl}>Next ></a>
|
||||
</span>
|
||||
)
|
||||
}
|
||||
</div>
|
49
src/components/PostSummary.astro
Normal file
49
src/components/PostSummary.astro
Normal 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>
|
51
src/content/blog/create-lib-file-from-dll.md
Normal file
51
src/content/blog/create-lib-file-from-dll.md
Normal 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 🙂
|
@ -1,17 +1,15 @@
|
||||
---
|
||||
description: >-
|
||||
Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса.
|
||||
title: Горячая перезагрузка ElectronJS приложения
|
||||
author: valentineus
|
||||
layout: post
|
||||
title: "Горячая перезагрузка ElectronJS приложения"
|
||||
author: "Valentin Popov"
|
||||
pubDate: "2019-08-15"
|
||||
description: "Руководство по автоматической перезагрузке приложений на Electron с помощью пакетов electron-reload и electron-webpack. Обход проблем с совместимостью и использование HMR для renderer процесса."
|
||||
---
|
||||
|
||||
## Main процесс
|
||||
|
||||
Для перезагрузки основного процесса можно использовать готовый пакет [electron-reload]. Или перезагружать приложение средствами пакета [electron-webpack].
|
||||
|
||||
Если сборщик кода отличный от WebPack или нет возможности использовать вышеуказанные пакеты, можно обойтись инструментом [nodemon]. Команда запуска будет
|
||||
выглядеть следующим образом:
|
||||
Если сборщик кода отличный от WebPack или нет возможности использовать вышеуказанные пакеты, можно обойтись инструментом [nodemon]. Команда запуска будет выглядеть следующим образом:
|
||||
|
||||
```bash
|
||||
nodemon --watch ./assets/main.js --exec 'electron .'
|
||||
@ -21,49 +19,42 @@ nodemon --watch ./assets/main.js --exec 'electron .'
|
||||
|
||||
## Renderer процесс
|
||||
|
||||
Для обновления renderer процесса, перезагружать полностью приложение нет необходимости. Достаточно обновить страницу. Самый простой способ, горячие
|
||||
клавиши: `Ctrl` + `F5`. Так как рендер процесс по своей сути является обычным окном браузера, можно настроить [HMR] технологию. Конечно, если используются
|
||||
соответствующие инструменты.
|
||||
Для обновления renderer процесса, перезагружать полностью приложение нет необходимости. Достаточно обновить страницу. Самый простой способ, горячие клавиши: `Ctrl` + `F5`. Так как рендер процесс по своей сути является обычным окном браузера, можно настроить [HMR] технологию. Конечно, если используются соответствующие инструменты.
|
||||
|
||||
Мне симпатичен способ использования пакета [electron-reload]. В алгоритме пакета лежит простое слежение за каталогом файлов и обновление активных окон
|
||||
приложения.
|
||||
Мне симпатичен способ использования пакета [electron-reload]. В алгоритме пакета лежит простое слежение за каталогом файлов и обновление активных окон приложения.
|
||||
|
||||
Но мною была найдена досадная [проблема], не позволяющая использовать версии `1.5.0` и `1.4.1` со сборщиком WebPack, который используется в проекте.
|
||||
|
||||
Решение было продублировать основной функционал пакета в проекте:
|
||||
|
||||
```javascript
|
||||
import { app } from 'electron';
|
||||
import chokidar from 'chokidar';
|
||||
import { app } from "electron";
|
||||
import chokidar from "chokidar";
|
||||
|
||||
const browserWindows = [];
|
||||
|
||||
app.on('browser-window-created', (event, window) => {
|
||||
browserWindows.push(window);
|
||||
app.on("browser-window-created", (event, window) => {
|
||||
browserWindows.push(window);
|
||||
|
||||
window.on('closed', () => {
|
||||
const index = browserWindows.indexOf(window);
|
||||
browserWindows.splice(index, 1);
|
||||
});
|
||||
window.on("closed", () => {
|
||||
const index = browserWindows.indexOf(window);
|
||||
browserWindows.splice(index, 1);
|
||||
});
|
||||
});
|
||||
|
||||
if (process.env.NODE_ENV !== 'production') {
|
||||
const watcher = chokidar.watch(__dirname, { ignored: [/node_modules|[/\\]\./] });
|
||||
if (process.env.NODE_ENV !== "production") {
|
||||
const watcher = chokidar.watch(__dirname, { ignored: [/node_modules|[/\\]\./] });
|
||||
|
||||
watcher.on('change', () => {
|
||||
browserWindows.forEach(window => {
|
||||
window.webContents.reloadIgnoringCache();
|
||||
});
|
||||
});
|
||||
watcher.on("change", () => {
|
||||
browserWindows.forEach((window) => {
|
||||
window.webContents.reloadIgnoringCache();
|
||||
});
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
[HMR]: https://webpack.js.org/concepts/hot-module-replacement/
|
||||
|
||||
[electron-reload]: https://www.npmjs.com/package/electron-reload
|
||||
|
||||
[electron-webpack]: https://www.npmjs.com/package/electron-webpack
|
||||
|
||||
[nodemon]: https://www.npmjs.com/package/nodemon
|
||||
|
||||
[проблема]: https://github.com/yan-foto/electron-reload/issues/66
|
133
src/content/blog/example-content.md
Normal file
133
src/content/blog/example-content.md
Normal 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>— 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>
|
185
src/content/blog/getting-source-code-of-chromium.md
Normal file
185
src/content/blog/getting-source-code-of-chromium.md
Normal 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";
|
23
src/content/blog/installing-moodle-to-fedora.md
Normal file
23
src/content/blog/installing-moodle-to-fedora.md
Normal 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
|
||||
```
|
@ -1,31 +1,26 @@
|
||||
---
|
||||
description: >-
|
||||
Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера.
|
||||
title: Компиляция Rust на TL-MR3020
|
||||
author: valentineus
|
||||
layout: post
|
||||
title: "Компиляция Rust на TL-MR3020"
|
||||
author: "Valentin Popov"
|
||||
pubDate: "2023-05-01"
|
||||
description: 'Как настроить и оптимизировать проект Rust для кросс-компиляции на TP-Link TL-MR3020 с использованием Fedora Linux 38 и OpenWrt 22.03.4. Шаг за шагом от базового "Hello, World!" до асинхронного TCP сервера.'
|
||||
---
|
||||
|
||||
Информация в статье актуальна для дистрибутива [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/) инструментарий.
|
||||
- Установленный пакет [cross-rs](https://github.com/cross-rs/cross) для кросс-компиляции.
|
||||
- Упаковщик исполняемых файлов [upx](https://github.com/upx/upx).
|
||||
- Контейнеризатор [Docker](https://docs.docker.com/engine/install/) (рекомендуется) или [Podman](https://podman.io/getting-started/installation).
|
||||
- SSH подключение к маршрутизатору.
|
||||
- Установленный [SFTP сервер](https://openwrt.org/docs/guide-user/services/nas/sftp.server) на TL-MR3020.
|
||||
- Установленный [rustup](https://rustup.rs/) инструментарий.
|
||||
- Установленный пакет [cross-rs](https://github.com/cross-rs/cross) для кросс-компиляции.
|
||||
- Упаковщик исполняемых файлов [upx](https://github.com/upx/upx).
|
||||
- Контейнеризатор [Docker](https://docs.docker.com/engine/install/) (рекомендуется) или [Podman](https://podman.io/getting-started/installation).
|
||||
- SSH подключение к маршрутизатору.
|
||||
- Установленный [SFTP сервер](https://openwrt.org/docs/guide-user/services/nas/sftp.server) на TL-MR3020.
|
||||
|
||||
> Требуется rustup инструментарий с официального сайта.
|
||||
Rust и Cargo из репозитория дистрибутива не подойдут.
|
||||
Пакет кросс-компиляции требует rustup, который в репозиториях дистрибутива отсутствует.
|
||||
> Требуется rustup инструментарий с официального сайта. Rust и Cargo из репозитория дистрибутива не подойдут. Пакет кросс-компиляции требует rustup, который в репозиториях дистрибутива отсутствует.
|
||||
|
||||
## "Hello, World!" ver. 1
|
||||
|
||||
Начнем с базы.
|
||||
Соберем и запустим "Hello, World" на маршрутизаторе.
|
||||
Инициализируем проект на Rust:
|
||||
Начнем с базы. Соберем и запустим "Hello, World" на маршрутизаторе. Инициализируем проект на Rust:
|
||||
|
||||
```bash
|
||||
cargo init --bin ramips-rs
|
||||
@ -56,8 +51,7 @@ cat /proc/cpuinfo
|
||||
# VCEI exceptions : not available
|
||||
```
|
||||
|
||||
Видим, что процессор архитектуры MIPS.
|
||||
Теперь определим целевую архитектуру для компиляции:
|
||||
Видим, что процессор архитектуры MIPS. Теперь определим целевую архитектуру для компиляции:
|
||||
|
||||
```bash
|
||||
rustup target list | grep mips
|
||||
@ -71,15 +65,13 @@ rustup target list | grep mips
|
||||
# mipsel-unknown-linux-musl
|
||||
```
|
||||
|
||||
Опытным путем определяем, что в случае с TL-MR3020 v3.20 подходит архитектура `mipsel-unknown-linux-musl`.
|
||||
Далее компилируем проект под целевую архитектуру:
|
||||
Опытным путем определяем, что в случае с TL-MR3020 v3.20 подходит архитектура `mipsel-unknown-linux-musl`. Далее компилируем проект под целевую архитектуру:
|
||||
|
||||
```bash
|
||||
cross build --release --target mipsel-unknown-linux-musl
|
||||
```
|
||||
|
||||
Получаем исполняемый бинарный файл, который загружаем и запускаем на маршрутизаторе.
|
||||
Выгружаем в раздел `/tmp`, потому что доступной памяти на основном разделе меньше двух мегабайт.
|
||||
Получаем исполняемый бинарный файл, который загружаем и запускаем на маршрутизаторе. Выгружаем в раздел `/tmp`, потому что доступной памяти на основном разделе меньше двух мегабайт.
|
||||
|
||||
```bash
|
||||
scp ./target/mipsel-unknown-linux-musl/release/ramips-rs openwrt:/tmp/
|
||||
@ -89,12 +81,9 @@ ssh openwrt /tmp/ramips-rs
|
||||
|
||||
## Оптимизация размера бинарника
|
||||
|
||||
После сборки и запуска "Hello, World" можно обратить внимание, что исполняемый файл весит __4.1 мегабайта__.
|
||||
Для устройства с 8 мегабайтами постоянной памяти это катастрофически много.
|
||||
После сборки и запуска "Hello, World" можно обратить внимание, что исполняемый файл весит **4.1 мегабайта**. Для устройства с 8 мегабайтами постоянной памяти это катастрофически много.
|
||||
|
||||
Уменьшим размер исполняемого файла до приемлемого минимума.
|
||||
Для этого настроим release профиль сборки и компиляции проекта.
|
||||
Дополним Cargo.toml файл:
|
||||
Уменьшим размер исполняемого файла до приемлемого минимума. Для этого настроим release профиль сборки и компиляции проекта. Дополним Cargo.toml файл:
|
||||
|
||||
```toml
|
||||
[profile.release]
|
||||
@ -105,23 +94,19 @@ panic = "abort" # Уменьшает бинарник да 332K
|
||||
codegen-units = 1 # Включает дополнительные оптимизации кода
|
||||
```
|
||||
|
||||
Получаем исполняемый файл размером в __332 килобайта__.
|
||||
Далее сжимаем исполняемый файл инструментом upx:
|
||||
Получаем исполняемый файл размером в **332 килобайта**. Далее сжимаем исполняемый файл инструментом upx:
|
||||
|
||||
```bash
|
||||
upx --best --lzma target/mipsel-unknown-linux-musl/release/ramips-rs
|
||||
```
|
||||
|
||||
И получаем исходный файл размером в __118 килобайт__.
|
||||
Приемлемый результат.
|
||||
И получаем исходный файл размером в **118 килобайт**. Приемлемый результат.
|
||||
|
||||
Сильнее уменьшить бинарник можно отказом от стандартной std библиотеки и другими экстремальными unsafe приемами, что не подходит в моем случае.
|
||||
|
||||
## "Hello, World!" ver. 2
|
||||
|
||||
Теперь сделаем пример посерьезней.
|
||||
Например, асинхронный TCP сервер.
|
||||
Подключаем зависимости:
|
||||
Теперь сделаем пример посерьезней. Например, асинхронный TCP сервер. Подключаем зависимости:
|
||||
|
||||
```toml
|
||||
[dependencies]
|
||||
@ -167,9 +152,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error + Send + Sync>> {
|
||||
}
|
||||
```
|
||||
|
||||
Проверяем, компилируем и сжимаем.
|
||||
Получаем бинарник размером в __236 килобайт__.
|
||||
Теперь загружаем в устройство, запускаем и проверяем:
|
||||
Проверяем, компилируем и сжимаем. Получаем бинарник размером в **236 килобайт**. Теперь загружаем в устройство, запускаем и проверяем:
|
||||
|
||||
```bash
|
||||
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/)
|
||||
- [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)
|
||||
- [Кросс-компиляция программ Rust для запуска на маршрутизаторе](https://dzen.ru/media/nuancesprog.ru/krosskompiliaciia-programm-rust-dlia-zapuska-na-marshrutizatore-5f6457b8bdfa745d402cd1ec)
|
||||
- [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/)
|
||||
- [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)
|
13
src/content/config.ts
Normal file
13
src/content/config.ts
Normal 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
9
src/env.d.ts
vendored
Normal 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;
|
||||
}
|
30
src/layouts/BaseLayout.astro
Normal file
30
src/layouts/BaseLayout.astro
Normal 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
30
src/pages/[...page].astro
Normal 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>
|
49
src/pages/blog/[...slug].astro
Normal file
49
src/pages/blog/[...slug].astro
Normal 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>
|
||||
by {post.data.author} ‐
|
||||
<strong>{remarkPluginFrontmatter.minutesRead}</strong>
|
||||
</small>
|
||||
</p>
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<Content />
|
||||
</section>
|
||||
|
||||
<section>
|
||||
<Comments />
|
||||
</section>
|
||||
</article>
|
||||
</Layout>
|
20
src/pages/feed.xml.js
Normal file
20
src/pages/feed.xml.js
Normal 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,
|
||||
});
|
||||
}
|
11
src/plugins/remarkReadingTime.ts
Normal file
11
src/plugins/remarkReadingTime.ts
Normal 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
256
src/scss/_framework.scss
Normal 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
21
src/scss/_print.scss
Normal 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
7
src/scss/_variables.scss
Normal 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
3
src/scss/global.scss
Normal file
@ -0,0 +1,3 @@
|
||||
@import "variables";
|
||||
@import "framework";
|
||||
@import "print";
|
3
tsconfig.json
Normal file
3
tsconfig.json
Normal file
@ -0,0 +1,3 @@
|
||||
{
|
||||
"extends": "astro/tsconfigs/strict"
|
||||
}
|
Loading…
Reference in New Issue
Block a user