Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions _layouts/default.html
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@
{% include head.html %}

<body>
<!-- Nine focusable elements sit before <main> on every page (logo, menu
button, six nav links, theme toggle), and a long post then leads with a
<!-- Ten focusable elements sit before <main> on every page (logo, menu
button, seven nav links, theme toggle), and a long post then leads with a
copy button per code block. Screen readers can jump by landmark; sighted
keyboard users had no shortcut. -->
<a class="skip-link" href="#content">Skip to content</a>
Expand Down
2 changes: 1 addition & 1 deletion docs/tech-doc.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,7 @@ Pages가 그대로 서빙.**
| 신택스 하이라이팅 | Rouge(서버사이드, kramdown 내장) | 코드 블록에 색을 입히는 작업을 **빌드 때 미리** 한다(브라우저 부담 0). 색 테마는 `_sass/_syntax.scss` |
| 수식 | kramdown `math_engine: mathjax` → MathJax 3, 포스트별 `use_math`로 로드 | 수학 기호를 브라우저에서 예쁘게 그려 주는 라이브러리. 수식이 있는 글에서만 불러온다 |
| 스타일 | Sass(`_sass/`), 벤더링된 Bourbon + Neat 그리드 프레임워크 | "벤더링"은 외부 라이브러리를 저장소 안에 복사해 둔 것. `jekyll-sass-converter` 2.x(libsass)로 **고정** — 3.x(dart-sass)는 Bourbon/Neat의 구식 `/` 나눗셈 문법에서 에러 |
| 자바스크립트 | 바닐라 JS(`js/main.js`, jQuery 없음) | "바닐라"는 프레임워크 없이 순수 JS만 쓴다는 뜻. 이미지 확대는 GLightbox. 아이콘은 Font Awesome 경로를 복사한 인라인 SVG(`_includes/icon.html`)라 아이콘 글꼴을 받지 않는다. 외부 CDN 스크립트는 **SRI**로 무결성 검증(아래 설명) |
| 자바스크립트 | 바닐라 JS(`js/main.js`, 검색 페이지의 `js/search.js`, 논문 글의 `js/citations.js`, jQuery 없음) | "바닐라"는 프레임워크 없이 순수 JS만 쓴다는 뜻. 이미지 확대는 GLightbox. 아이콘은 Font Awesome 경로를 복사한 인라인 SVG(`_includes/icon.html`)라 아이콘 글꼴을 받지 않는다. 외부 CDN 스크립트는 **SRI**로 무결성 검증(아래 설명) |
| 검색 | `search.json`(전체 본문 색인) 위에 `simple-jekyll-search` | 서버 없이 브라우저에서 도는 검색. 미리 만들어 둔 색인 파일을 받아 클라이언트가 직접 찾는다 |
| 다크모드 | 라이트가 기본, 토글로 opt-in(`_sass/_dark.scss`, `[data-theme="dark"]`) | OS의 다크모드 설정은 **따르지 않고**, 사용자가 버튼을 눌러 켜야 한다. 테마에 따라 바뀌어야 하는 두 값이 CSS 밖에 있다 — `color-scheme`(스크롤바 등 브라우저 위젯)은 `_dark.scss`가 `data-theme`으로 처리하고, `theme-color`(모바일 주소창)는 메타 태그라 `head.html`의 인라인 스크립트와 `main.js`의 토글이 함께 갱신한다 |
| 호스팅/CI | GitHub Actions로 GitHub Pages 배포(`.github/workflows/jekyll.yml`) | `main`에 푸시하면 자동으로 빌드·검사·배포. 같은 검사가 `main`으로 향하는 PR에서도 돌아 머지 전에 막는다 |
Expand Down
13 changes: 9 additions & 4 deletions js/citations.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
// Zero is not a count worth showing: Semantic Scholar answers it for a
// duplicate record of a paper, and it stands in for "not found" below.
function show(entry) {
if (!(entry.count > 0)) return;
if (!(entry.count > 0) || !entry.paperId) return;
var count = entry.count.toLocaleString('en-US');
var link = document.createElement('a');
link.className = 'meta-value';
Expand All @@ -34,7 +34,8 @@
var cached = null;
try { cached = JSON.parse(localStorage.getItem(key)); } catch (e) {}
if (cached && typeof cached.count !== 'number') cached = null;
if (cached && Date.now() - cached.at < DAY) return show(cached);
var age = cached && Date.now() - cached.at;
if (cached && age >= 0 && age < DAY) return show(cached); // a clock set back is not fresh

var controller = new AbortController();
var timer = setTimeout(function () { controller.abort(); }, 5000);
Expand All @@ -54,8 +55,12 @@
show(entry);
})
.catch(function (err) {
console.error('Citation count:', err);
if (cached) show(cached);
console.warn('Citation count:', err); // expected: the keyless API often answers 429
if (!cached) return;
// Kept for another day, or every view of a paper gone missing asks again.
cached.at = Date.now();
try { localStorage.setItem(key, JSON.stringify(cached)); } catch (e) {}
show(cached);
})
.finally(function () { clearTimeout(timer); });
})();
8 changes: 6 additions & 2 deletions script/lint-posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -132,8 +132,12 @@ def self.front_matter(post, spec)
if data.key?("paper_doi") && !data["paper_doi"].to_s.match?(%r{\A10\.\d{4,9}/[^\s?#]+\z})
found << "1: paper_doi is a bare DOI (10.<registrant>/<suffix>), got #{data["paper_doi"].inspect}"
end
elsif data.key?("paper_doi")
found << "1: paper_doi is for #{spec["types"].select { |_, t| t["paper"] }.keys.join(" and ")} posts"
else
paper_types = spec["types"].select { |_, t| t["paper"] }.keys.join(" and ")
# The layout prints "Paper by …" for any post that has it.
%w[paper_author paper_doi].each do |k|
found << "1: #{k} is for #{paper_types} posts" if data.key?(k)
end
end

cover = spec["types"][type]["cover"] || spec["topics"][topic]
Expand Down
1 change: 1 addition & 0 deletions test/test_lint_posts.rb
Original file line number Diff line number Diff line change
Expand Up @@ -279,6 +279,7 @@ def test_paper_doi_is_a_bare_doi_on_paper_posts_only
end
guide = with_doi.call('"10.48550/arXiv.2310.06825"').sub('"Paper Reviews", "Language-Models"', '"Tech Guides", "Agentic-AI"')
assert_finding(/paper_doi is for Paper Reviews and Paper Summaries posts/, lint(front: guide))
assert_finding(/paper_author is for Paper Reviews and Paper Summaries posts/, lint(front: guide))
end
end