Skip to content
Open
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: 4 additions & 0 deletions .Jules/palette.md
Original file line number Diff line number Diff line change
Expand Up @@ -21,3 +21,7 @@
## 2024-07-15 - Expand clickable area of project cards
**Learning:** Using an anchor tag to wrap an entire card (block-level element) can result in verbose and confusing screen reader output. However, restricting the clickable area to just the title makes the UI harder to interact with (violating Fitts's Law).
**Action:** Apply `position: relative` to the card container and use a `::after` pseudo-element with `position: absolute; inset: 0;` on the title's anchor tag. This expands the clickable area to the whole card while keeping semantic and accessible HTML structure.

## 2024-08-25 - ์™ธ๋ถ€ ๋งํฌ์— ์ ‘๊ทผ์„ฑ ํ–ฅ์ƒ์„ ์œ„ํ•œ title ์†์„ฑ๊ณผ i18n ์ ์šฉ

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿ“ Info: Palette entry date likely off by two years

The new entry is dated 2024-08-25 while the change lands in 2026. Given the journal records recent incidents, this reads as a typo, though other entries also use 2024 dates so intent is ambiguous.

Open in Devin Review

Was this helpful? React with ๐Ÿ‘ or ๐Ÿ‘Ž to provide feedback.

**Learning:** ์™ธ๋ถ€ ๋งํฌ(`target="_blank"`)๊ฐ€ ์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆฐ๋‹ค๋Š” ์‚ฌ์‹ค์„ ์Šคํฌ๋ฆฐ ๋ฆฌ๋”์™€ ์‹œ๊ฐ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ธ์ง€์‹œํ‚ค๊ธฐ ์œ„ํ•ด ์ปค์Šคํ…€ CSS(.sr-only) ์ถ”๊ฐ€ ์—†์ด ๊ธฐ์กด `i18n.js` ๊ตฌ์กฐ๋ฅผ ํ™•์žฅ(`data-i18n-title` ์ง€์›)ํ•˜๋Š” ๋ฐฉ์‹์œผ๋กœ ๋‹ค๊ตญ์–ด ์ ‘๊ทผ์„ฑ ํˆดํŒ์„ ์ถ”๊ฐ€ํ•˜๋Š” ๊ฒƒ์ด ๋” ์œ ์—ฐํ•˜๊ณ  ํšจ๊ณผ์ ์ž„์„ ๋ฐœ๊ฒฌํ•จ.
**Action:** ์‹œ๊ฐ์ ์ธ ๋””์ž์ธ ๋ณ€๊ฒฝ ์—†์ด ์ ‘๊ทผ์„ฑ ํžŒํŠธ๋ฅผ ์ฃผ๊ณ  ์‹ถ์„ ๋•Œ `title` ์–ดํŠธ๋ฆฌ๋ทฐํŠธ์™€ `i18n.js` ์†์„ฑ ํ™•์žฅ์„ ํ™œ์šฉํ•  ๊ฒƒ.
22 changes: 16 additions & 6 deletions i18n.js
Original file line number Diff line number Diff line change
Expand Up @@ -144,7 +144,8 @@ const messages = {
"work.fourTitle": "์ž‘์—… ํ๋ฆ„",
"work.fourBody": "๋ฐ˜๋ณต ํƒ์ƒ‰์€ ์ค„์ด๊ณ  ๊ทผ๊ฑฐ ํ™•์ธ๊ณผ ์‚ฌ๋žŒ์˜ ํŒ๋‹จ์€ ๋‚จ๊ธฐ๋Š” ํ๋ฆ„.",
"footer.founded": "Founded by",
"footer.line": "Context into judgment. Judgment into action."
"footer.line": "Context into judgment. Judgment into action.",
"a11y.newWindow": "(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)"
},
en: {
metaTitle: "Contextual Wisdom Lab",
Expand Down Expand Up @@ -291,7 +292,8 @@ const messages = {
"work.fourTitle": "Agentic workflows",
"work.fourBody": "Workflows that reduce repeated search while preserving evidence checks and human judgment.",
"footer.founded": "Founded by",
"footer.line": "Context into judgment. Judgment into action."
"footer.line": "Context into judgment. Judgment into action.",
"a11y.newWindow": "(Opens in a new tab)"
}
};

Expand Down Expand Up @@ -365,14 +367,22 @@ function setLanguage(lang) {

if (!isInitialDefault) {
if (!i18nNodes) {
i18nNodes = document.querySelectorAll("[data-i18n]");
i18nNodes = document.querySelectorAll("[data-i18n], [data-i18n-title]");
}

// Only update textContent if it actually changed to avoid layout recalculations
i18nNodes.forEach((node) => {
const newText = dict[node.dataset.i18n];
if (newText && node.textContent !== newText) {
node.textContent = newText;
if (node.hasAttribute("data-i18n")) {
const newText = dict[node.dataset.i18n];
if (newText && node.textContent !== newText) {
node.textContent = newText;
}
}
if (node.hasAttribute("data-i18n-title")) {
const newTitle = dict[node.dataset.i18nTitle];
if (newTitle && node.getAttribute("title") !== newTitle) {
node.setAttribute("title", newTitle);
}
}
});
}
Comment on lines 367 to 388

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

๐Ÿ“ Info: Initial Korean load skips title translation, stays consistent

On initial Korean load isInitialDefault skips the node traversal, so data-i18n-title titles are never set by JS. Safe because every external link carries an inline Korean title matching a11y.newWindow, and later language switches populate i18nNodes and update titles correctly.

(Refers to this code)

Open in Devin Review

Was this helpful? React with ๐Ÿ‘ or ๐Ÿ‘Ž to provide feedback.

Expand Down
32 changes: 16 additions & 16 deletions index.html
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@
<a href="#projects" data-i18n="nav.projects">ํ”„๋กœ์ ํŠธ</a>
<a href="#forks" data-i18n="nav.forks">Fork</a>
<a href="#work" data-i18n="nav.work">์ž‘์—…</a>
<a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab">GitHub</a>
<a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">GitHub</a>

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Expose the new-tab hint without relying on title

For keyboard-only and touch users, the only new cue is a title tooltip, which is generally exposed through mouse hover and is not reliably announced by assistive technologies when the link already has visible text. Consequently, these users can still activate the link without learning that it opens a new tab, defeating the accessibility goal of this change; provide the localized hint through visible or visually hidden text, or associate it with the link using aria-describedby instead.

Useful? React with ๐Ÿ‘ย / ๐Ÿ‘Ž.

</nav>
<div class="language-switch" role="group" aria-label="Language">
<button type="button" data-lang="ko" lang="ko" aria-pressed="true" aria-label="ํ•œ๊ตญ์–ด">KO</button>
Expand All @@ -59,7 +59,7 @@ <h1 data-i18n="hero.title">๋งฅ๋ฝ์ง€ํ˜œ ์—ฐ๊ตฌ์‹ค</h1>
๊ตฌ์Šฌ์ด ์„œ ๋ง์ด์–ด๋„ ๊ฟฐ์–ด์•ผ ๋ณด๋ฐฐ์ด๋“ฏ, ๋ฌธ์„œ, ๋ฉ”์ผ, ๋กœ๊ทธ, ํšŒ์˜๋ก์„ ๋งฅ๋ฝ ์•ˆ์—์„œ ์—ฎ์–ด ์‚ฌ๋žŒ์ด ๋ฌด์—‡์„ ๊ฒฐ์ •ํ•˜๊ณ  ๋ฌด์—‡์„ ์‹คํ–‰ํ• ์ง€ ๋ณด์ด๊ฒŒ ํ•˜๋Š” AI ์˜์‚ฌ๊ฒฐ์ • ์ง€์› ์‹œ์Šคํ…œ์„ ์—ฐ๊ตฌํ•˜๊ณ  ๋งŒ๋“ญ๋‹ˆ๋‹ค.
</p>
<div class="hero-actions" role="group" aria-label="Homepage actions">
<a target="_blank" rel="noopener noreferrer" class="button primary" href="https://github.com/ContextualWisdomLab" data-i18n="hero.primaryCta">GitHub ๋ณด๊ธฐ</a>
<a target="_blank" rel="noopener noreferrer" class="button primary" href="https://github.com/ContextualWisdomLab" data-i18n="hero.primaryCta" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">GitHub ๋ณด๊ธฐ</a>
<a class="button secondary" href="#dikw" data-i18n="hero.secondaryCta">DIKW ๋ณด๊ธฐ</a>
</div>
</div>
Expand Down Expand Up @@ -254,19 +254,19 @@ <h2 data-i18n="references.title">์ฐธ๊ณ ๋ฌธํ—Œ</h2>
<ol class="reference-list">
<li>
<span data-i18n="references.ackoff">Ackoff, R. L. (1989). From data to wisdom. Journal of Applied Systems Analysis, 16(1), 3-9.</span>
<a target="_blank" rel="noopener noreferrer" href="https://faculty.ung.edu/kmelton/documents/datawisdom.pdf">https://faculty.ung.edu/kmelton/documents/datawisdom.pdf</a>
<a target="_blank" rel="noopener noreferrer" href="https://faculty.ung.edu/kmelton/documents/datawisdom.pdf" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">https://faculty.ung.edu/kmelton/documents/datawisdom.pdf</a>
</li>
<li>
<span data-i18n="references.baskarada">Baskarada, S., &amp; Koronios, A. (2013). Data, information, knowledge, wisdom (DIKW): A semiotic theoretical and empirical exploration of the hierarchy and its quality dimension. Australasian Journal of Information Systems, 18(1).</span>
<a target="_blank" rel="noopener noreferrer" href="https://doi.org/10.3127/ajis.v18i1.748">https://doi.org/10.3127/ajis.v18i1.748</a>
<a target="_blank" rel="noopener noreferrer" href="https://doi.org/10.3127/ajis.v18i1.748" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">https://doi.org/10.3127/ajis.v18i1.748</a>
</li>
<li>
<span data-i18n="references.fricke">Frickรฉ, M. (2009). The knowledge pyramid: A critique of the DIKW hierarchy. Journal of Information Science, 35(2), 131-142.</span>
<a target="_blank" rel="noopener noreferrer" href="https://doi.org/10.1177/0165551508094050">https://doi.org/10.1177/0165551508094050</a>
<a target="_blank" rel="noopener noreferrer" href="https://doi.org/10.1177/0165551508094050" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">https://doi.org/10.1177/0165551508094050</a>
</li>
<li>
<span data-i18n="references.brienza">Brienza, J. P., Kung, F. Y. H., Santos, H. C., Bobocel, D. R., &amp; Grossmann, I. (2018). Wisdom, bias, and balance: Toward a process-sensitive measurement of wisdom-related cognition. Journal of Personality and Social Psychology, 115(6), 1093-1126.</span>
<a target="_blank" rel="noopener noreferrer" href="https://doi.org/10.1037/pspp0000171">https://doi.org/10.1037/pspp0000171</a>
<a target="_blank" rel="noopener noreferrer" href="https://doi.org/10.1037/pspp0000171" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">https://doi.org/10.1037/pspp0000171</a>
</li>
</ol>
</section>
Expand Down Expand Up @@ -327,39 +327,39 @@ <h2 data-i18n="projects.title">๊ณต๊ฐœ ํ”„๋กœ์ ํŠธ</h2>
</div>
<div class="naruon-grid project-grid">
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/naruon" data-i18n="projects.naruonTitle">Naruon</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/naruon" data-i18n="projects.naruonTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">Naruon</a></h3>
<p data-i18n="projects.naruonBody">๋ฉ”์ผ, ์ฒจ๋ถ€, ์ผ์ •, ์ž‘์—…์„ ๋งฅ๋ฝ์œผ๋กœ ๋ฌถ์–ด ํŒ๋‹จ๊ณผ ์‹คํ–‰์œผ๋กœ ์—ฐ๊ฒฐํ•˜๋Š” AI ์ด๋ฉ”์ผ ์›Œํฌ์ŠคํŽ˜์ด์Šค์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/pg-erd-cloud" data-i18n="projects.pgErdTitle">pg-erd-cloud</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/pg-erd-cloud" data-i18n="projects.pgErdTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">pg-erd-cloud</a></h3>
<p data-i18n="projects.pgErdBody">PostgreSQL ์Šคํ‚ค๋งˆ๋ฅผ ๋ฆฌ๋ฒ„์Šค ์—”์ง€๋‹ˆ์–ด๋งํ•˜๊ณ  ERD์™€ DDL ๊ณต์œ  ํ๋ฆ„์œผ๋กœ ๊ด€๋ฆฌํ•˜๋Š” ํด๋ผ์šฐ๋“œ MVP์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/bandscope" data-i18n="projects.bandscopeTitle">BandScope</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/bandscope" data-i18n="projects.bandscopeTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">BandScope</a></h3>
<p data-i18n="projects.bandscopeBody">๊ณก์„ ์„น์…˜, ์—ญํ• , ํ…œํฌ, ์—ฐ์Šต ์šฐ์„ ์ˆœ์œ„๋กœ ๋ถ„์„ํ•˜๋Š” ๋กœ์ปฌ ์šฐ์„  ๋ฆฌํ—ˆ์„ค ์•ฑ์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/codec-carver" data-i18n="projects.codecCarverTitle">codec-carver</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/codec-carver" data-i18n="projects.codecCarverTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">codec-carver</a></h3>
<p data-i18n="projects.codecCarverBody">๊ธด ๋…น์Œ์„ ๋ฉ”ํƒ€๋ฐ์ดํ„ฐ๋ฅผ ๋ณด์กดํ•œ FLAC/Opus ์กฐ๊ฐ์œผ๋กœ ๋ณ€ํ™˜ํ•˜๋Š” Python CLI์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/newsdom-api" data-i18n="projects.newsdomTitle">newsdom-api</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/newsdom-api" data-i18n="projects.newsdomTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">newsdom-api</a></h3>
<p data-i18n="projects.newsdomBody">์Šค์บ”๋œ ์ผ๋ณธ์–ด ์‹ ๋ฌธ PDF๋ฅผ ๊ธฐ์‚ฌ, ์ œ๋ชฉ, ๋ณธ๋ฌธ, ์ด๋ฏธ์ง€ ๊ตฌ์กฐ์˜ DOMํ˜• JSON์œผ๋กœ ํŒŒ์‹ฑํ•˜๋Š” API์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/scopeweave" data-i18n="projects.scopeweaveTitle">scopeweave</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/scopeweave" data-i18n="projects.scopeweaveTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">scopeweave</a></h3>
<p data-i18n="projects.scopeweaveBody">ํŠธ๋ฆฌ ํŽธ์ง‘, ์ง„ํ–‰๋ฅ  ๊ณ„์‚ฐ, CSV/JSON, ์ฃผ๊ฐ„ Gantt๋ฅผ ์ง€์›ํ•˜๋Š” ์ •์  HTML/CSS/JS WBS ํ”Œ๋ž˜๋„ˆ์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/VibeSec" data-i18n="projects.vibesecTitle">VibeSec</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/VibeSec" data-i18n="projects.vibesecTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">VibeSec</a></h3>
<p data-i18n="projects.vibesecBody">๋ฐ”์ด๋ธŒ์ฝ”๋”ฉ ์•ฑ์„ ์œ„ํ•œ ๋ณด์•ˆ ๊ฐ€๋“œ๋ ˆ์ผ์ž…๋‹ˆ๋‹ค. AI ๊ฐœ๋ฐœ ๋„๊ตฌ ๊ทœ์น™, ์ •์  ์ ๊ฒ€, ๋ฆฌ๋ทฐ์™€ ์ˆ˜์ • ํ”„๋กฌํ”„ํŠธ๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/fast-mlsirm" data-i18n="projects.fastMlsirmTitle">fast-mlsirm</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/fast-mlsirm" data-i18n="projects.fastMlsirmTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">fast-mlsirm</a></h3>
<p data-i18n="projects.fastMlsirmBody">MLSIRM/MLS2PLM ๋ชจํ˜•์˜ ์‹œ๋ฎฌ๋ ˆ์ด์…˜, ์ ํ•ฉ, ๋ณต์› ์ง„๋‹จ์„ ๋น ๋ฅด๊ฒŒ ์ˆ˜ํ–‰ํ•˜๋Š” Python/Rust ํŒจํ‚ค์ง€์ž…๋‹ˆ๋‹ค.</p>
</article>
<article>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/waf-ids-ai-soc" data-i18n="projects.wafIdsTitle">waf-ids-ai-soc</a></h3>
<h3><a target="_blank" rel="noopener noreferrer" href="https://github.com/ContextualWisdomLab/waf-ids-ai-soc" data-i18n="projects.wafIdsTitle" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">waf-ids-ai-soc</a></h3>
<p data-i18n="projects.wafIdsBody">DNSBL ๊ฒŒ์‹œ ๊ธฐ๋Šฅ์„ ๊ฐ–์ถ˜ Rust ์šฐ์„  WAF/IDS/AI SOC ๊ฒŒ์ดํŠธ์›จ์ด์ž…๋‹ˆ๋‹ค.</p>
</article>
</div>
Expand Down Expand Up @@ -431,7 +431,7 @@ <h2 data-i18n="work.title">์—ฐ๊ตฌ์—์„œ ์ œํ’ˆ์œผ๋กœ</h2>
>
<p>
<span data-i18n="footer.founded">Founded by</span>
<a target="_blank" rel="noopener noreferrer" href="https://github.com/seonghobae">Seongho Bae</a>.
<a target="_blank" rel="noopener noreferrer" href="https://github.com/seonghobae" title="(์ƒˆ ์ฐฝ์—์„œ ์—ด๋ฆผ)" data-i18n-title="a11y.newWindow">Seongho Bae</a>.
<span data-i18n="footer.line">Context into judgment. Judgment into action.</span>
</p>
</footer>
Expand Down
Loading