rawfeed 0.1.3 → 0.2.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/LICENSE.txt +20 -21
- data/README.md +13 -112
- data/_data/options.yml +270 -0
- data/_data/resume.yml +8 -9
- data/_includes/alert +3 -1
- data/_includes/chart +13 -32
- data/_includes/details +1 -57
- data/_includes/image +12 -4
- data/_includes/layout/blog_search.html +7 -5
- data/_includes/layout/data.liquid +21 -3
- data/_includes/layout/disqus.html +12 -26
- data/_includes/layout/footer.html +34 -16
- data/_includes/layout/giscus.html +27 -19
- data/_includes/layout/head.html +58 -19
- data/_includes/layout/header.html +127 -101
- data/_includes/layout/maintenance.html +8 -12
- data/_includes/layout/paginator.html +6 -4
- data/_includes/socials +7 -5
- data/_includes/tabs +1 -94
- data/_includes/toc +12 -152
- data/_includes/video +4 -1
- data/_layouts/blog.html +8 -7
- data/_layouts/contact.html +90 -196
- data/_layouts/default.html +42 -339
- data/_layouts/error.html +6 -4
- data/_layouts/home.html +45 -36
- data/_layouts/licenses.html +10 -0
- data/_layouts/page.html +4 -6
- data/_layouts/pixel.html +48 -0
- data/_layouts/pixels.html +71 -0
- data/_layouts/post.html +28 -31
- data/_layouts/resume.html +43 -36
- data/_layouts/tag.html +14 -3
- data/_layouts/tag_posts.html +3 -3
- data/_sass/base/_index.scss +39 -3
- data/_sass/components/_badges.scss +10 -0
- data/_sass/components/_markdown.scss +20 -17
- data/_sass/includes/_footer.scss +18 -8
- data/_sass/includes/_header.scss +24 -19
- data/_sass/includes/_highlight.scss +20 -7
- data/_sass/includes/_maintenance.scss +2 -3
- data/_sass/includes/_terminal.scss +35 -12
- data/_sass/layouts/_blog.scss +13 -9
- data/_sass/layouts/_contact.scss +6 -5
- data/_sass/layouts/_default.scss +5 -5
- data/_sass/layouts/_index.scss +3 -0
- data/_sass/layouts/_licenses.scss +7 -0
- data/_sass/layouts/_page.scss +1 -0
- data/_sass/layouts/_pixel.scss +61 -0
- data/_sass/layouts/_pixels.scss +86 -0
- data/_sass/layouts/_post.scss +4 -11
- data/_sass/layouts/_resume.scss +17 -7
- data/_sass/layouts/_tag-posts.scss +1 -2
- data/_sass/layouts/_tag.scss +12 -1
- data/_sass/main.scss +16 -1
- data/_sass/theme/_dark.scss +15 -5
- data/_sass/theme/_light.scss +9 -2
- data/assets/images/blog/.keep +0 -0
- data/assets/images/pixels/luffy.jpg +0 -0
- data/assets/js/blog.coffee +102 -0
- data/assets/js/contact.coffee +105 -0
- data/assets/js/default.coffee +172 -0
- data/assets/js/discus.coffee +30 -0
- data/assets/js/fallback/README.md +3 -0
- data/assets/js/fallback/blog.js +113 -0
- data/assets/js/fallback/contact.js +116 -0
- data/assets/js/{default.js → fallback/default.js} +50 -0
- data/assets/js/fallback/discus.js +32 -0
- data/{_includes/layout/google_analytics.html → assets/js/fallback/google_analytics.js} +7 -3
- data/assets/js/fallback/home.js +275 -0
- data/assets/js/fallback/no_inframe.js +4 -0
- data/assets/js/fallback/page.js +423 -0
- data/assets/js/fallback/pixels.js +1 -0
- data/assets/js/fallback/resume.js +13 -0
- data/assets/js/fallback/tags.js +1 -0
- data/assets/js/fallback/theme_load.js +4 -0
- data/assets/js/google_analytics.coffee +24 -0
- data/assets/js/home.coffee +250 -0
- data/assets/js/no_inframe.coffee +9 -0
- data/assets/js/page.coffee +379 -0
- data/assets/js/pixels.coffee +2 -0
- data/assets/js/resume.coffee +9 -0
- data/assets/js/tags.coffee +2 -0
- data/assets/js/theme_load.coffee +6 -0
- data/assets/json/blog_search.json +2 -2
- data/lib/rawfeed/author.rb +59 -0
- data/lib/rawfeed/csp_filters.rb +19 -0
- data/lib/rawfeed/draft.rb +1 -1
- data/lib/rawfeed/layout.rb +7 -0
- data/lib/rawfeed/page.rb +4 -2
- data/lib/rawfeed/pixel.rb +32 -0
- data/lib/rawfeed/post.rb +2 -2
- data/lib/rawfeed/resume.rb +1 -0
- data/lib/rawfeed/typescript_liquid.rb +172 -0
- data/lib/rawfeed/utils.rb +1 -0
- data/lib/rawfeed/version.rb +1 -1
- data/lib/rawfeed/with_class.rb +20 -0
- data/lib/rawfeed.rb +5 -0
- metadata +46 -12
- data/assets/js/avatar.js +0 -50
- data/assets/js/terminal.js +0 -18
- data/assets/js/toc.js +0 -22
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require "jekyll"
|
|
4
|
+
require "fileutils"
|
|
5
|
+
require "yaml"
|
|
6
|
+
|
|
7
|
+
module Jekyll
|
|
8
|
+
class AuthorGenerator < Generator
|
|
9
|
+
safe true
|
|
10
|
+
priority :low
|
|
11
|
+
|
|
12
|
+
def generate(site)
|
|
13
|
+
options_yml = File.join(site.source, "_data", "options.yml")
|
|
14
|
+
|
|
15
|
+
unless File.exist?(options_yml)
|
|
16
|
+
Jekyll.logger.error "[AuthorPlugin]", "File _data/options.yml not found!"
|
|
17
|
+
return
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
options_data = YAML.load_file(options_yml)
|
|
21
|
+
author_value = options_data["author"]
|
|
22
|
+
|
|
23
|
+
unless author_value
|
|
24
|
+
Jekyll.logger.warn "[AuthorPlugin]", "Field 'author' not found in options.yml."
|
|
25
|
+
return
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
targets = [
|
|
29
|
+
"index.md",
|
|
30
|
+
"blog/index.md",
|
|
31
|
+
"blog/tags/index.md",
|
|
32
|
+
"pixels/index.md"
|
|
33
|
+
]
|
|
34
|
+
|
|
35
|
+
targets.each do |relative_path|
|
|
36
|
+
abs_path = File.join(site.source, relative_path)
|
|
37
|
+
next unless File.exist?(abs_path)
|
|
38
|
+
|
|
39
|
+
content = File.read(abs_path)
|
|
40
|
+
updated = nil
|
|
41
|
+
|
|
42
|
+
if content =~ /^author:\s*.+$/
|
|
43
|
+
updated = content.gsub(/^author:\s*.+$/, "author: \"#{author_value}\"")
|
|
44
|
+
elsif content =~ /\A---\s*\n/ # insere logo depois do primeiro ---
|
|
45
|
+
updated = content.sub(/\A(---\s*\n)/, "\\1author: \"#{author_value}\"\n")
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
if updated && updated != content
|
|
49
|
+
File.write(abs_path, updated)
|
|
50
|
+
Jekyll.logger.info "[AuthorPlugin]", "Updated #{relative_path} → author: #{author_value}"
|
|
51
|
+
else
|
|
52
|
+
Jekyll.logger.debug "[AuthorPlugin]", "No changes to #{relative_path}"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
rescue StandardError => e
|
|
56
|
+
Jekyll.logger.error "[AuthorPlugin]", "Error: #{e.message}"
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
end
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
require "jekyll"
|
|
2
|
+
require 'digest'
|
|
3
|
+
require 'base64'
|
|
4
|
+
|
|
5
|
+
# TODO: Note: If you have an inline script, generate a hash of it for CSP
|
|
6
|
+
# By default, this functionality is not being used because the project does not have any
|
|
7
|
+
# inline scripts. Module disabled!
|
|
8
|
+
module Rawfeed
|
|
9
|
+
module CspFilters
|
|
10
|
+
# Generates a SHA256 hash and encodes it in Base64, ready for use in a CSP.
|
|
11
|
+
def sha256_base64(input)
|
|
12
|
+
# Calculates the SHA256 hash of the input text.
|
|
13
|
+
hash = Digest::SHA256.digest(input)
|
|
14
|
+
# Encodes the result in strict Base64 (no line breaks).
|
|
15
|
+
Base64.strict_encode64(hash)
|
|
16
|
+
end
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
Liquid::Template.register_filter(Rawfeed::CspFilters)
|
data/lib/rawfeed/draft.rb
CHANGED
|
@@ -13,9 +13,9 @@ module Rawfeed
|
|
|
13
13
|
File.open(array[3], 'w') do |file|
|
|
14
14
|
file.puts("---")
|
|
15
15
|
file.puts("layout: post")
|
|
16
|
+
file.puts("author: # \"Your Name\"")
|
|
16
17
|
file.puts("title: \"#{array[0]}\"")
|
|
17
18
|
file.puts("description: \"Description of your post\"")
|
|
18
|
-
file.puts("author: \"Your Name\"")
|
|
19
19
|
file.puts("date: #{array[2]} -0300")
|
|
20
20
|
file.puts("update_date: ")
|
|
21
21
|
file.puts("comments: false")
|
data/lib/rawfeed/layout.rb
CHANGED
|
@@ -127,6 +127,13 @@ module Rawfeed
|
|
|
127
127
|
File.write(file, updated)
|
|
128
128
|
end
|
|
129
129
|
|
|
130
|
+
def self.pixels_index(value)
|
|
131
|
+
file = "pixels/index.md"
|
|
132
|
+
content = File.read(file)
|
|
133
|
+
updated = content.gsub(/^published:\s*\S+$/, "published: #{value}")
|
|
134
|
+
File.write(file, updated)
|
|
135
|
+
end
|
|
136
|
+
|
|
130
137
|
def self.tags_index(value)
|
|
131
138
|
file = "blog/tags/index.md"
|
|
132
139
|
content = File.read(file)
|
data/lib/rawfeed/page.rb
CHANGED
|
@@ -14,11 +14,13 @@ module Rawfeed
|
|
|
14
14
|
File.open(array[3], 'w') do |file|
|
|
15
15
|
file.puts("---")
|
|
16
16
|
file.puts("layout: page")
|
|
17
|
-
file.puts("
|
|
17
|
+
file.puts("author: # \"Your Name\"")
|
|
18
18
|
file.puts("title: \"#{array[0]}\"")
|
|
19
|
-
file.puts("
|
|
19
|
+
file.puts("order: #number")
|
|
20
|
+
file.puts("emoji: 😃 # Add an emoji to the page menu or leave it blank")
|
|
20
21
|
file.puts("date: #{array[2]} -0300")
|
|
21
22
|
file.puts("update_date: ")
|
|
23
|
+
file.puts("in_menu: true")
|
|
22
24
|
file.puts("reading_time: true")
|
|
23
25
|
file.puts("published: false")
|
|
24
26
|
file.puts("permalink: /#{permalink}/")
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
#encoding: utf-8
|
|
2
|
+
|
|
3
|
+
require "colorize"
|
|
4
|
+
require_relative "utils"
|
|
5
|
+
|
|
6
|
+
module Rawfeed
|
|
7
|
+
class Pixel
|
|
8
|
+
def self.pixel_create
|
|
9
|
+
array = Rawfeed::Utils.enginer(Rawfeed::CONFIG['PIXELS_DIR'], 'Enter new pixel title:', 'pixel')
|
|
10
|
+
|
|
11
|
+
puts "Creating new pixel: #{array[3]}"
|
|
12
|
+
|
|
13
|
+
File.open(array[3], 'w') do |file|
|
|
14
|
+
file.puts("---")
|
|
15
|
+
file.puts("layout: pixel")
|
|
16
|
+
file.puts("author: # \"Your Name\"")
|
|
17
|
+
file.puts("title: \"#{array[0]}\"")
|
|
18
|
+
file.puts("description: \"Description of your post\"")
|
|
19
|
+
file.puts("image:")
|
|
20
|
+
file.puts(" path: # /assets/images/pixels/example.jpg")
|
|
21
|
+
file.puts(" caption: ")
|
|
22
|
+
file.puts("date: #{array[2]} -0300")
|
|
23
|
+
file.puts("---")
|
|
24
|
+
file.puts("")
|
|
25
|
+
file.puts "<!-- Write from here your post !!! -->"
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
puts "Created successfully!"
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
32
|
+
|
data/lib/rawfeed/post.rb
CHANGED
|
@@ -5,7 +5,7 @@ require_relative "utils"
|
|
|
5
5
|
|
|
6
6
|
module Rawfeed
|
|
7
7
|
class Post
|
|
8
|
-
def self.
|
|
8
|
+
def self.post
|
|
9
9
|
drafts = Dir.glob(File.join(Rawfeed::CONFIG['DRAFTS_DIR'], "*.#{Rawfeed::CONFIG['markdown_extension']}"))
|
|
10
10
|
|
|
11
11
|
if drafts.empty?
|
|
@@ -13,7 +13,7 @@ module Rawfeed
|
|
|
13
13
|
return
|
|
14
14
|
end
|
|
15
15
|
|
|
16
|
-
puts "Select the file to move:\n".
|
|
16
|
+
puts "Select the file to move:\n".cyan
|
|
17
17
|
|
|
18
18
|
drafts.each_with_index do |file, index|
|
|
19
19
|
puts "#{index + 1} - #{File.basename(file)}"
|
data/lib/rawfeed/resume.rb
CHANGED
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
require "jekyll"
|
|
3
|
+
require "open3"
|
|
4
|
+
require "tmpdir"
|
|
5
|
+
require "tempfile"
|
|
6
|
+
require "fileutils"
|
|
7
|
+
require "shellwords"
|
|
8
|
+
require "json"
|
|
9
|
+
|
|
10
|
+
# TODO: Note: A functional module for writing TypeScript with Liquid support. The project currently uses CoffeeScript, so this module is disabled.
|
|
11
|
+
|
|
12
|
+
# Install: npm install --save-dev typescript
|
|
13
|
+
#
|
|
14
|
+
# Default tsconfig.json:
|
|
15
|
+
# {
|
|
16
|
+
# "compilerOptions": {
|
|
17
|
+
# "target": "es6",
|
|
18
|
+
# "strict": true
|
|
19
|
+
# },
|
|
20
|
+
# "exclude": [
|
|
21
|
+
# "node_modules",
|
|
22
|
+
# ".bundle-cache",
|
|
23
|
+
# "tmp",
|
|
24
|
+
# "tools",
|
|
25
|
+
# "_site",
|
|
26
|
+
# ]
|
|
27
|
+
# }
|
|
28
|
+
|
|
29
|
+
module Jekyll
|
|
30
|
+
class TypeScriptGenerator < Generator
|
|
31
|
+
safe true
|
|
32
|
+
priority :low
|
|
33
|
+
|
|
34
|
+
def generate(site)
|
|
35
|
+
Jekyll.logger.info "[PLUGIN TS] Plugin TypeScript carregado!"
|
|
36
|
+
ts_config_path = File.join(site.source, "tsconfig.json")
|
|
37
|
+
|
|
38
|
+
unless File.exist?(ts_config_path)
|
|
39
|
+
Jekyll.logger.error "[PLUGIN TS]", "tsconfig.json não encontrado!"
|
|
40
|
+
return
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
source_dir = File.join(site.source, "assets", "ts")
|
|
44
|
+
output_dir_source = File.join(site.source, "assets", "js") # escreve no source para ser copiado
|
|
45
|
+
FileUtils.mkdir_p(output_dir_source)
|
|
46
|
+
|
|
47
|
+
unless Dir.exist?(source_dir)
|
|
48
|
+
Jekyll.logger.info "[PLUGIN TS] nenhum diretório assets/ts encontrado (procure por #{source_dir})"
|
|
49
|
+
return
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
Dir.glob(File.join(source_dir, "**", "*.ts")).each do |ts_file|
|
|
53
|
+
process_ts_file(site, ts_config_path, ts_file, source_dir, output_dir_source)
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
private
|
|
58
|
+
|
|
59
|
+
def process_ts_file(site, ts_config_path, ts_file, source_dir, output_dir_source)
|
|
60
|
+
rel_path = ts_file.sub(/^#{Regexp.escape(source_dir)}\//, "")
|
|
61
|
+
js_rel = rel_path.sub(/\.ts$/, ".js")
|
|
62
|
+
js_output_path_source = File.join(output_dir_source, js_rel)
|
|
63
|
+
FileUtils.mkdir_p(File.dirname(js_output_path_source))
|
|
64
|
+
|
|
65
|
+
Jekyll.logger.info "[PLUGIN TS] processando #{rel_path}"
|
|
66
|
+
|
|
67
|
+
raw_content = File.read(ts_file)
|
|
68
|
+
|
|
69
|
+
# --- 1) remove front matter do arquivo ORIGINAL (antes do render)
|
|
70
|
+
# isto garante que o bloco ---...--- não chegue ao conteúdo final
|
|
71
|
+
content_without_fm = raw_content.sub(/\A---\s*\n.*?\n---\s*\n/m, "")
|
|
72
|
+
|
|
73
|
+
# --- 2) renderiza o Liquid usando o motor do Jekyll (includes, assigns, etc)
|
|
74
|
+
# usamos PageWithoutAFile para obter o contexto completo do site
|
|
75
|
+
liquid_page = Jekyll::PageWithoutAFile.new(site, site.source, File.dirname(ts_file), File.basename(ts_file))
|
|
76
|
+
liquid_page.content = content_without_fm
|
|
77
|
+
# renderiza com o payload do site (disponibiliza includes, site.data, etc)
|
|
78
|
+
liquid_page.render({}, site.site_payload)
|
|
79
|
+
processed_content = liquid_page.output.to_s
|
|
80
|
+
|
|
81
|
+
# --- 3) remove qualquer linha que contenha somente '---' (proteção extra)
|
|
82
|
+
# (remove linhas contendo apenas traços e espaços)
|
|
83
|
+
processed_content = processed_content.gsub(/^\s*-{3,}\s*$\r?\n?/, "")
|
|
84
|
+
|
|
85
|
+
# também remove possíveis linhas vazias no início
|
|
86
|
+
processed_content = processed_content.sub(/\A\s*\r?\n/, "")
|
|
87
|
+
|
|
88
|
+
# debug: mostra as primeiras linhas do que será compilado
|
|
89
|
+
# Jekyll.logger.debug "[PLUGIN TS] preview do conteúdo final:\n#{processed_content.lines.first(12).join}"
|
|
90
|
+
|
|
91
|
+
# --- 4) grava o .ts temporário (no tmpdir)
|
|
92
|
+
tmp_dir = Dir.mktmpdir("jekyll_ts_")
|
|
93
|
+
begin
|
|
94
|
+
tmp_ts = File.join(tmp_dir, File.basename(ts_file))
|
|
95
|
+
|
|
96
|
+
# 1) remove qualquer front matter inicial
|
|
97
|
+
processed_content = processed_content.sub(/\A\s*---\s*\n?/, "")
|
|
98
|
+
|
|
99
|
+
# 2) remove linhas isoladas com apenas ---
|
|
100
|
+
processed_content = processed_content.gsub(/^\s*-{3,}\s*$\r?\n?/, "")
|
|
101
|
+
|
|
102
|
+
File.write(tmp_ts, processed_content)
|
|
103
|
+
File.chmod(0644, tmp_ts) rescue nil
|
|
104
|
+
Jekyll.logger.debug "[PLUGIN TS] tmp ts criado em #{tmp_ts}"
|
|
105
|
+
|
|
106
|
+
# detecta comando tsc como antes (array de tokens)
|
|
107
|
+
tsc_cmd_tokens = detect_tsc_command_tokens(site.source)
|
|
108
|
+
unless tsc_cmd_tokens
|
|
109
|
+
Jekyll.logger.error "[PLUGIN TS] compilador TypeScript não encontrado. Rode `npm install typescript --save-dev` ou assegure npx/tsc no PATH."
|
|
110
|
+
return
|
|
111
|
+
end
|
|
112
|
+
|
|
113
|
+
# monta e executa comando com array (evita problemas de escape)
|
|
114
|
+
ts_config = JSON.parse(File.read(ts_config_path))
|
|
115
|
+
target = ts_config.dig("compilerOptions", "target") || "ES5"
|
|
116
|
+
strict = ts_config.dig("compilerOptions", "strict") || false
|
|
117
|
+
cmd_array = tsc_cmd_tokens + ["--target", "#{target}", "--strict", "#{strict}", "--outFile", js_output_path_source, tmp_ts]
|
|
118
|
+
Jekyll.logger.info "[PLUGIN TS] Running → #{cmd_array.shelljoin}"
|
|
119
|
+
|
|
120
|
+
stdout, stderr, status = Open3.capture3(*cmd_array)
|
|
121
|
+
if status.success?
|
|
122
|
+
Jekyll.logger.info "[PLUGIN TS] OK: #{rel_path} -> assets/js/#{js_rel}"
|
|
123
|
+
Jekyll.logger.debug stdout unless stdout.to_s.strip.empty?
|
|
124
|
+
else
|
|
125
|
+
Jekyll.logger.error "[PLUGIN TS] tsc falhou para #{rel_path}:"
|
|
126
|
+
puts stderr.to_s
|
|
127
|
+
puts stdout.to_s unless stdout.to_s.strip.empty?
|
|
128
|
+
end
|
|
129
|
+
ensure
|
|
130
|
+
FileUtils.remove_entry(tmp_dir) if tmp_dir && Dir.exist?(tmp_dir)
|
|
131
|
+
end
|
|
132
|
+
rescue => e
|
|
133
|
+
Jekyll.logger.error "[PLUGIN TS] erro processando #{ts_file}: #{e.class}: #{e.message}"
|
|
134
|
+
puts e.backtrace.join("\n")
|
|
135
|
+
end
|
|
136
|
+
|
|
137
|
+
def remove_front_matter(content)
|
|
138
|
+
# remove o bloco YAML inicial (--- ... ---) se existir
|
|
139
|
+
content.sub(/\A---\s*\n.*?\n---\s*\n/m, "")
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def render_liquid(site, content)
|
|
143
|
+
# render no contexto do site para que {{ site.url }} e afins sejam resolvidos
|
|
144
|
+
Liquid::Template.parse(content).render(site.site_payload)
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
# Retorna um array de tokens do comando tsc, por exemplo:
|
|
148
|
+
# - ["/path/to/node_modules/.bin/tsc"]
|
|
149
|
+
# - ["/path/to/node_modules/.bin/npx", "tsc"]
|
|
150
|
+
# - ["npx", "tsc"]
|
|
151
|
+
# - ["tsc"]
|
|
152
|
+
def detect_tsc_command_tokens(root)
|
|
153
|
+
local_tsc = File.join(root, "node_modules", ".bin", "tsc")
|
|
154
|
+
return [local_tsc] if File.exist?(local_tsc) && File.executable?(local_tsc)
|
|
155
|
+
|
|
156
|
+
npx_local = File.join(root, "node_modules", ".bin", "npx")
|
|
157
|
+
if File.exist?(npx_local) && File.executable?(npx_local)
|
|
158
|
+
return [npx_local, "tsc"]
|
|
159
|
+
end
|
|
160
|
+
|
|
161
|
+
# fallback para npx no PATH
|
|
162
|
+
which_npx = `which npx`.strip
|
|
163
|
+
return ["npx", "tsc"] unless which_npx.empty?
|
|
164
|
+
|
|
165
|
+
# fallback para tsc global
|
|
166
|
+
which_tsc = `which tsc`.strip
|
|
167
|
+
return ["tsc"] unless which_tsc.empty?
|
|
168
|
+
|
|
169
|
+
nil
|
|
170
|
+
end
|
|
171
|
+
end
|
|
172
|
+
end
|
data/lib/rawfeed/utils.rb
CHANGED
|
@@ -5,6 +5,7 @@ module Rawfeed
|
|
|
5
5
|
CONFIG = {
|
|
6
6
|
'DRAFTS_DIR' => File.join(".", "_drafts"),
|
|
7
7
|
'POSTS_DIR' => File.join(".", "_posts"),
|
|
8
|
+
'PIXELS_DIR' => File.join(".", "_pixels"),
|
|
8
9
|
'PAGES_DIR' => File.join(".", "_pages"),
|
|
9
10
|
'RESUME_DIR' => File.join(".", "_data"),
|
|
10
11
|
'CONFIG_YML' => File.join(".", "_config.yml"),
|
data/lib/rawfeed/version.rb
CHANGED
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
require "jekyll"
|
|
2
|
+
require 'digest'
|
|
3
|
+
require 'base64'
|
|
4
|
+
|
|
5
|
+
# Usage: {{ content | wrap_with_class: 'your-class' }}
|
|
6
|
+
|
|
7
|
+
module Rawfeed
|
|
8
|
+
module AddClassHtml
|
|
9
|
+
def with_class(input, class_name)
|
|
10
|
+
return input if input.to_s.strip.empty?
|
|
11
|
+
html_output = "<span class=\"#{class_name}\">#{input.to_s}</span>"
|
|
12
|
+
return html_output
|
|
13
|
+
end
|
|
14
|
+
|
|
15
|
+
alias_method :add_class_html, :with_class
|
|
16
|
+
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
|
|
20
|
+
Liquid::Template.register_filter(Rawfeed::AddClassHtml)
|
data/lib/rawfeed.rb
CHANGED
|
@@ -7,5 +7,10 @@ require_relative "rawfeed/post"
|
|
|
7
7
|
require_relative "rawfeed/page"
|
|
8
8
|
require_relative "rawfeed/resume"
|
|
9
9
|
require_relative "rawfeed/layout"
|
|
10
|
+
require_relative "rawfeed/pixel"
|
|
11
|
+
require_relative "rawfeed/author"
|
|
10
12
|
require "rawfeed/datelang"
|
|
11
13
|
require "rawfeed/reading_time"
|
|
14
|
+
require "rawfeed/with_class"
|
|
15
|
+
# require "rawfeed/csp_filters"
|
|
16
|
+
# require "rawfeed/typescript_liquid"
|
metadata
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: rawfeed
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.
|
|
4
|
+
version: 0.2.0
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- William C. Canin
|
|
@@ -30,19 +30,19 @@ dependencies:
|
|
|
30
30
|
- !ruby/object:Gem::Version
|
|
31
31
|
version: '5.0'
|
|
32
32
|
- !ruby/object:Gem::Dependency
|
|
33
|
-
name: jekyll-
|
|
33
|
+
name: jekyll-coffeescript
|
|
34
34
|
requirement: !ruby/object:Gem::Requirement
|
|
35
35
|
requirements:
|
|
36
36
|
- - "~>"
|
|
37
37
|
- !ruby/object:Gem::Version
|
|
38
|
-
version: 2.
|
|
38
|
+
version: 2.0.0
|
|
39
39
|
type: :runtime
|
|
40
40
|
prerelease: false
|
|
41
41
|
version_requirements: !ruby/object:Gem::Requirement
|
|
42
42
|
requirements:
|
|
43
43
|
- - "~>"
|
|
44
44
|
- !ruby/object:Gem::Version
|
|
45
|
-
version: 2.
|
|
45
|
+
version: 2.0.0
|
|
46
46
|
- !ruby/object:Gem::Dependency
|
|
47
47
|
name: jekyll-sitemap
|
|
48
48
|
requirement: !ruby/object:Gem::Requirement
|
|
@@ -135,6 +135,7 @@ extra_rdoc_files: []
|
|
|
135
135
|
files:
|
|
136
136
|
- LICENSE.txt
|
|
137
137
|
- README.md
|
|
138
|
+
- _data/options.yml
|
|
138
139
|
- _data/resume.yml
|
|
139
140
|
- _includes/alert
|
|
140
141
|
- _includes/chart
|
|
@@ -147,7 +148,6 @@ files:
|
|
|
147
148
|
- _includes/layout/disqus.html
|
|
148
149
|
- _includes/layout/footer.html
|
|
149
150
|
- _includes/layout/giscus.html
|
|
150
|
-
- _includes/layout/google_analytics.html
|
|
151
151
|
- _includes/layout/head.html
|
|
152
152
|
- _includes/layout/header.html
|
|
153
153
|
- _includes/layout/maintenance.html
|
|
@@ -161,7 +161,10 @@ files:
|
|
|
161
161
|
- _layouts/default.html
|
|
162
162
|
- _layouts/error.html
|
|
163
163
|
- _layouts/home.html
|
|
164
|
+
- _layouts/licenses.html
|
|
164
165
|
- _layouts/page.html
|
|
166
|
+
- _layouts/pixel.html
|
|
167
|
+
- _layouts/pixels.html
|
|
165
168
|
- _layouts/post.html
|
|
166
169
|
- _layouts/resume.html
|
|
167
170
|
- _layouts/tag.html
|
|
@@ -190,7 +193,10 @@ files:
|
|
|
190
193
|
- _sass/layouts/_error.scss
|
|
191
194
|
- _sass/layouts/_home.scss
|
|
192
195
|
- _sass/layouts/_index.scss
|
|
196
|
+
- _sass/layouts/_licenses.scss
|
|
193
197
|
- _sass/layouts/_page.scss
|
|
198
|
+
- _sass/layouts/_pixel.scss
|
|
199
|
+
- _sass/layouts/_pixels.scss
|
|
194
200
|
- _sass/layouts/_post.scss
|
|
195
201
|
- _sass/layouts/_resume.scss
|
|
196
202
|
- _sass/layouts/_tag-posts.scss
|
|
@@ -203,11 +209,34 @@ files:
|
|
|
203
209
|
- assets/images/avatar_back.png
|
|
204
210
|
- assets/images/avatar_dark.png
|
|
205
211
|
- assets/images/avatar_light.png
|
|
212
|
+
- assets/images/blog/.keep
|
|
206
213
|
- assets/images/favicon.png
|
|
207
|
-
- assets/
|
|
208
|
-
- assets/js/
|
|
209
|
-
- assets/js/
|
|
210
|
-
- assets/js/
|
|
214
|
+
- assets/images/pixels/luffy.jpg
|
|
215
|
+
- assets/js/blog.coffee
|
|
216
|
+
- assets/js/contact.coffee
|
|
217
|
+
- assets/js/default.coffee
|
|
218
|
+
- assets/js/discus.coffee
|
|
219
|
+
- assets/js/fallback/README.md
|
|
220
|
+
- assets/js/fallback/blog.js
|
|
221
|
+
- assets/js/fallback/contact.js
|
|
222
|
+
- assets/js/fallback/default.js
|
|
223
|
+
- assets/js/fallback/discus.js
|
|
224
|
+
- assets/js/fallback/google_analytics.js
|
|
225
|
+
- assets/js/fallback/home.js
|
|
226
|
+
- assets/js/fallback/no_inframe.js
|
|
227
|
+
- assets/js/fallback/page.js
|
|
228
|
+
- assets/js/fallback/pixels.js
|
|
229
|
+
- assets/js/fallback/resume.js
|
|
230
|
+
- assets/js/fallback/tags.js
|
|
231
|
+
- assets/js/fallback/theme_load.js
|
|
232
|
+
- assets/js/google_analytics.coffee
|
|
233
|
+
- assets/js/home.coffee
|
|
234
|
+
- assets/js/no_inframe.coffee
|
|
235
|
+
- assets/js/page.coffee
|
|
236
|
+
- assets/js/pixels.coffee
|
|
237
|
+
- assets/js/resume.coffee
|
|
238
|
+
- assets/js/tags.coffee
|
|
239
|
+
- assets/js/theme_load.coffee
|
|
211
240
|
- assets/json/blog_search.json
|
|
212
241
|
- assets/json/datelang.json
|
|
213
242
|
- assets/vendor/bootstrap/css/bootstrap-grid.css
|
|
@@ -257,23 +286,28 @@ files:
|
|
|
257
286
|
- assets/vendor/simple-jekyll-search.js
|
|
258
287
|
- assets/vendor/simple-jekyll-search.min.js
|
|
259
288
|
- lib/rawfeed.rb
|
|
289
|
+
- lib/rawfeed/author.rb
|
|
290
|
+
- lib/rawfeed/csp_filters.rb
|
|
260
291
|
- lib/rawfeed/datelang.rb
|
|
261
292
|
- lib/rawfeed/draft.rb
|
|
262
293
|
- lib/rawfeed/installer.rb
|
|
263
294
|
- lib/rawfeed/layout.rb
|
|
264
295
|
- lib/rawfeed/page.rb
|
|
296
|
+
- lib/rawfeed/pixel.rb
|
|
265
297
|
- lib/rawfeed/post.rb
|
|
266
298
|
- lib/rawfeed/reading_time.rb
|
|
267
299
|
- lib/rawfeed/resume.rb
|
|
300
|
+
- lib/rawfeed/typescript_liquid.rb
|
|
268
301
|
- lib/rawfeed/utils.rb
|
|
269
302
|
- lib/rawfeed/version.rb
|
|
270
|
-
|
|
303
|
+
- lib/rawfeed/with_class.rb
|
|
304
|
+
homepage: https://rawfeed.github.io/rawfeed-jekyll
|
|
271
305
|
licenses:
|
|
272
306
|
- MIT
|
|
273
307
|
metadata:
|
|
274
308
|
allowed_push_host: https://rubygems.org
|
|
275
|
-
source_code_uri: https://github.
|
|
276
|
-
changelog_uri: https://github.
|
|
309
|
+
source_code_uri: https://rawfeed.github.io/rawfeed-jekyll
|
|
310
|
+
changelog_uri: https://rawfeed.github.io/rawfeed-jekyll/blob/main/CHANGELOG.md
|
|
277
311
|
rdoc_options: []
|
|
278
312
|
require_paths:
|
|
279
313
|
- lib
|
data/assets/js/avatar.js
DELETED
|
@@ -1,50 +0,0 @@
|
|
|
1
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
2
|
-
// O alvo do clique agora é o contêiner INTERATIVO
|
|
3
|
-
const flipperAvatars = document.querySelectorAll('.avatar-flipper__open-true');
|
|
4
|
-
const modalEl = document.getElementById('avatarModal');
|
|
5
|
-
const modalAvatar = document.getElementById('modalAvatar');
|
|
6
|
-
const header = document.querySelector('.header');
|
|
7
|
-
const bsModal = new bootstrap.Modal(modalEl);
|
|
8
|
-
|
|
9
|
-
flipperAvatars.forEach((flipper) => {
|
|
10
|
-
// Escuta o clique no contêiner inteiro
|
|
11
|
-
flipper.addEventListener("click", () => {
|
|
12
|
-
// Encontra o card que realmente anima
|
|
13
|
-
const card = flipper.querySelector('.avatar-card');
|
|
14
|
-
// Encontra a imagem de TRÁS e pega o seu src ANTES da animação
|
|
15
|
-
const backImage = flipper.querySelector('.avatar-back img');
|
|
16
|
-
const backImageSrc = backImage.src;
|
|
17
|
-
|
|
18
|
-
// Adiciona a classe de animação ao card
|
|
19
|
-
card.classList.add("flip-avatar");
|
|
20
|
-
|
|
21
|
-
card.addEventListener(
|
|
22
|
-
"animationend",
|
|
23
|
-
() => {
|
|
24
|
-
card.classList.remove("flip-avatar");
|
|
25
|
-
|
|
26
|
-
// Usa o src da imagem de trás que guardamos
|
|
27
|
-
modalAvatar.src = backImageSrc;
|
|
28
|
-
|
|
29
|
-
bsModal.show();
|
|
30
|
-
},
|
|
31
|
-
{ once: true }
|
|
32
|
-
);
|
|
33
|
-
});
|
|
34
|
-
});
|
|
35
|
-
|
|
36
|
-
// quando o modal está visível, escondemos os contêineres (esta parte já estava correta)
|
|
37
|
-
modalEl.addEventListener("shown.bs.modal", () => {
|
|
38
|
-
modalAvatar.classList.remove("modal-avatar");
|
|
39
|
-
void modalAvatar.offsetWidth;
|
|
40
|
-
modalAvatar.classList.add("modal-avatar");
|
|
41
|
-
header.classList.remove("modal-active");
|
|
42
|
-
|
|
43
|
-
flipperAvatars.forEach((flipper) => flipper.classList.add("hidden"));
|
|
44
|
-
});
|
|
45
|
-
|
|
46
|
-
// quando o modal é fechado, mostramos os contêineres (esta parte já estava correta)
|
|
47
|
-
modalEl.addEventListener("hidden.bs.modal", () => {
|
|
48
|
-
flipperAvatars.forEach((flipper) => flipper.classList.remove("hidden"));
|
|
49
|
-
});
|
|
50
|
-
});
|
data/assets/js/terminal.js
DELETED
|
@@ -1,18 +0,0 @@
|
|
|
1
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
2
|
-
/* effects terminal: maximize
|
|
3
|
-
--------------------------------------------------------------------------------------------------
|
|
4
|
-
*/
|
|
5
|
-
const terminal = document.getElementById("terminal");
|
|
6
|
-
|
|
7
|
-
if (!terminal) return;
|
|
8
|
-
|
|
9
|
-
const btnMax = terminal.querySelector(".terminal-header__max");
|
|
10
|
-
|
|
11
|
-
let isFullscreen = false;
|
|
12
|
-
|
|
13
|
-
// maximize/restore
|
|
14
|
-
btnMax.addEventListener("click", () => {
|
|
15
|
-
isFullscreen = !isFullscreen;
|
|
16
|
-
terminal.classList.toggle("terminal-fullscreen", isFullscreen);
|
|
17
|
-
});
|
|
18
|
-
});
|
data/assets/js/toc.js
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
document.addEventListener("DOMContentLoaded", () => {
|
|
2
|
-
/* TOC in top */
|
|
3
|
-
const toc = document.getElementById('toc');
|
|
4
|
-
|
|
5
|
-
if (!toc) return;
|
|
6
|
-
|
|
7
|
-
const sentinel = document.createElement('div');
|
|
8
|
-
toc.parentNode.insertBefore(sentinel, toc);
|
|
9
|
-
|
|
10
|
-
const observer = new IntersectionObserver(
|
|
11
|
-
([entry]) => {
|
|
12
|
-
if (!entry.isIntersecting) {
|
|
13
|
-
toc.classList.add('toc-fixed');
|
|
14
|
-
} else {
|
|
15
|
-
toc.classList.remove('toc-fixed');
|
|
16
|
-
}
|
|
17
|
-
},
|
|
18
|
-
{ threshold: 0 }
|
|
19
|
-
);
|
|
20
|
-
|
|
21
|
-
observer.observe(sentinel);
|
|
22
|
-
});
|