본문으로 건너뛰기
cccskills
무료GitHub에 공개한국어 소개

jewel-markdown

Jewel Markdown의 파싱부터 Compose 렌더링까지 구성하고 문제를 살펴봅니다. 표, 내장 HTML, 이미지, 코드 강조 표시, 실시간 편집기 미리보기에 맞춰 스타일과 파서·렌더러 확장을 선택하고 기본 표시 동작을 유지하도록 안내합니다.

원문원문 설명 보기

Build or debug Jewel Markdown parsing, rendering, and styling.

JetBrains/intellij-community스타 20,685(GitHub 20,685 + cccskills 0)

실행 점수 미검증

설치 방법 보기

이럴 때 유용합니다

  • Markdown 스타일 조정
  • 사용자 정의 Markdown 구문 추가
  • Markdown에 HTML이나 이미지 표시
  • 편집기와 미리보기 연결

한국어 소개

할 수 있는 일

Jewel Markdown의 파싱과 표시 흐름을 구성하고 문제를 살펴보는 방법을 안내합니다. MarkdownProcessor는 Markdown 문자열을 MarkdownBlock과 InlineMarkdown 모델로 변환하고, Jewel Compose 렌더러가 이를 화면에 표시합니다. 모양만 바꾸려면 MarkdownStyling을 조정하고, 기존 블록이나 인라인 콘텐츠의 표시 동작을 바꾸려면 해당 렌더러 확장을 사용합니다. 새 구문을 추가할 때는 파서 확장과 렌더러 확장을 함께 구성합니다. GFM 표와 취소선, 알림, 이미지, 코드 강조 표시, 내장 HTML, 편집 내용에 따라 갱신되는 미리보기도 다룹니다. 사용자 정의 렌더러에서는 필요한 경우 정렬, 색상, 인라인 이미지, 비활성 상태, 미리보기 스크롤 동기화 동작을 유지하는 점도 확인합니다.

이럴 때 유용합니다

앱에 Jewel Markdown을 넣거나 기존 스타일과 블록 동작을 바꾸려는 경우에 활용할 수 있습니다. 사용자 정의 구문이나 HTML 태그를 추가하거나 이미지와 코드를 표시할 때도 적합합니다. 편집기와 실시간 미리보기를 연결할 때 사용할 수 있으며, 채팅 Markdown에서는 메시지 관리와 표시 처리를 분리하는 구성을 안내합니다.

사용 예시

  • “Jewel Markdown에서 GFM 표와 취소선이 표시되도록 구성해 주세요.”
  • “사용자 정의 Markdown 블록을 파싱해 Compose UI로 그려 주세요.”
  • “편집 내용에 따라 갱신되는 Markdown 미리보기를 구현해 주세요.”

주의 사항

이미지 확장 예시에는 Coil3가 포함됩니다. 코드 강조 표시의 기본 제공 방식은 IDE 플러그인과 독립 실행 환경에서 다릅니다. 내장 HTML 파싱은 기본적으로 꺼져 있습니다.

이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.

문서 점검

AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.

안전성전송·삭제·명령 실행 등을 명시하고 있는가
A양호자료의 작업은 파싱과 렌더링 확장이며 파괴적 작업이나 외부 전송은 없습니다.
도입의 용이성필요한 도구나 API 키가 적고 적혀 있는가
B일부 부족Coil3와 실행 방식별 코드 강조 표시를 언급하지만 설치 절차는 제한적입니다.

점수에는 넣지 않았습니다. 2026년 10월 28일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.

평가가 다르다고 생각되면 재검토를 요청하기

어느 항목이 왜 다르다고 생각하는지 적어 주세요. 로그인은 필요 없습니다. SKILL.md와 대조해 평가를 다시 만들고 이곳에 반영합니다.

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

포함된 파일(7)

  • SKILL.md17.0 KB
  • evals/evals.json10.3 KB
  • references/CODE-HIGHLIGHTING.md4.9 KB
  • references/HTML-PARSING.md4.9 KB
  • references/IMAGE-LOADING.md6.6 KB
  • references/SCROLL-SYNC.md7.1 KB
  • skill-source.json1.6 KB

SKILL.md(원문)

설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.

<!-- Generated by community/.ai/render-guides.mjs; edit community/.agents/skills/jewel-markdown/SKILL.md -->

Jewel Markdown

Jewel Markdown is a two-stage renderer: parse raw Markdown into Jewel's MarkdownBlock / InlineMarkdown model, then render that model with Jewel Compose renderers. Choose the smallest customization point that matches the job.

The Jewel Markdown sources live in JetBrains intellij-community under platform/jewel/markdown/. Confirm exact API/file/symbol names by reading those sources (grep/read) rather than trusting memory before proposing code. For deeper topic detail, read the matching reference only when that topic is in play:

  • references/CODE-HIGHLIGHTING.md — fenced/indented code highlighting, CodeHighlighter, why code is unstyled by default.
  • references/IMAGE-LOADING.md — ImageRendererExtension + ImageSourceResolver, Coil3, path resolution.
  • references/SCROLL-SYNC.md — editor-preview scroll synchronization and its ScrollState-only limitation.
  • references/HTML-PARSING.md — embedded HTML, built-in tag conversion, MarkdownHtmlConverterExtension, alignment.

First decision: what are you changing?

  1. Visual styling only — customize MarkdownStyling and theme-specific styling helpers.
  2. Existing block UI behavior — use a custom MarkdownBlockRenderer, usually by subclassing DefaultMarkdownBlockRenderer and overriding the specific Render* method.
  3. Existing inline text behavior — use a custom InlineMarkdownRenderer, usually by subclassing DefaultInlineMarkdownRenderer.
  4. New Markdown syntax — write a processor extension and a renderer extension.
  5. Images — use an ImageRendererExtension, not a general block renderer.
  6. Embedded HTML — enable parseEmbeddedHtml on the MarkdownProcessor, and for custom HTML→Markdown mapping add a MarkdownHtmlConverterExtension.
  7. A live editor preview — use MarkdownMode.EditorPreview with a dedicated MarkdownProcessor instance and render with LazyMarkdown.

Do not start with a custom renderer when styling or an extension solves the problem.

High-level rendering flow

  1. MarkdownProcessor parses raw Markdown into List<MarkdownBlock>.
  2. Blocks may contain InlineMarkdown nodes.
  3. Markdown renders short/simple content in a Column; LazyMarkdown renders larger or editor-preview content in a LazyColumn.
  4. MarkdownBlockRenderer renders block nodes and delegates inline content to InlineMarkdownRenderer.
  5. ProvideMarkdownStyling wires LocalMarkdownStyling, LocalMarkdownProcessor, LocalMarkdownBlockRenderer, and code/image support into JewelTheme.
  6. Extensions can plug into processing, block rendering, and inline rendering (with some limitations).

Prefer processing Markdown outside composition for non-trivial or frequently changing text. The string-taking Markdown(...) overload is convenient, but it parses from composition and is best for small, mostly static snippets.

Built-in and existing extension choices

Use the existing extension modules before inventing syntax:

  • Plain URLs are not becoming links: add AutolinkProcessorExtension to the MarkdownProcessor.
  • GFM tables: add GitHubTableProcessorExtension and GitHubTableRendererExtension. The processor extension also bundles a MarkdownHtmlConverterExtension for <table> (active when parseEmbeddedHtml = true).
  • GFM strikethrough: add GitHubStrikethroughProcessorExtension and GitHubStrikethroughRendererExtension. The processor extension also bundles a MarkdownHtmlConverterExtension for <s>, <strike>, and <del> (active when parseEmbeddedHtml = true).
  • GFM alerts: add GitHubAlertProcessorExtension and GitHubAlertRendererExtension.
  • Images: add an ImageRendererExtension, commonly Coil3ImageRendererExtension, to the renderer extensions and provide an image source resolver where needed. For details read references/IMAGE-LOADING.md.
  • Code syntax highlighting: in a plugin, use the Project-aware bridge ProvideMarkdownStyling, which wires an IJPL-backed highlighter by default; in standalone (or a bridge overload without a Project) the default is a no-op and you must provide a CodeHighlighter. For details read references/CODE-HIGHLIGHTING.md.

For a worked example of combining several extensions (processor + renderer + theme-specific styling, parsing off composition, LazyMarkdown), read the standalone sample at platform/jewel/samples/standalone/src/main/kotlin/org/jetbrains/jewel/samples/standalone/markdown/MarkdownPreview.kt.

Keep parser and renderer extensions paired when a feature has both sides. If a processor creates a custom block or inline node and no renderer extension claims it, the content will not render usefully. Do not invent renderer extensions for parse-only features such as autolink, and do not invent processor extensions for renderer-only image loading.

Embedded HTML

HTML support is off by default: a MarkdownProcessor ignores embedded HTML unless you construct it with parseEmbeddedHtml = true. There are two distinct HTML paths, do not conflate them:

  • Native HTML mapped to Markdown: when parseEmbeddedHtml is on, a fixed set of built-in tags is converted into normal MarkdownBlocks ( p, li, ol, ul, h1-h6, code, pre, img). These render through the standard block/inline renderers, not through a raw-HTML renderer.
  • Custom tag conversion: to map an additional HTML tag onto a Markdown block your code understands (e.g., <table> to a tables block), implement a MarkdownHtmlConverterExtension and expose it from your MarkdownProcessorExtension.htmlConverterExtension. It declares supportedTags and returns an HtmlElementConverter per tag; the converter turns an HTML element into a MarkdownBlock (or inline list), delegating children/inlines via the provided lambdas. Existing GFM extensions ship these: gfm-tables converts <table> (block), and gfm-strikethrough converts <s>/<strike>/<del> (inline). Use them as references and add the extension whose tags you need rather than reimplementing it.

For full details, models, and wiring, read references/HTML-PARSING.md.

Key points and gotchas:

  • htmlConverterExtensions are only collected when parseEmbeddedHtml = true; adding one without enabling embedded HTML does nothing.
  • HTML that is not converted is preserved as an HtmlBlock (raw HTML string) or inline HTML; the default renderer shows it via the htmlBlock styling, it is not interpreted as native UI. Jewel does not do general inline-HTML rendering.
  • HTML carrying layout attributes (e.g., an align attribute) becomes a MarkdownBlock.HtmlBlockWithAttributes wrapping the converted block; the default renderer reads the align attribute and propagates text alignment to children. A custom renderer that overrides this path must preserve that alignment behavior (see Gotchas for custom renderers).
  • Custom HTML conversion is parse-side only. If a converter emits a custom block type, you still need a matching renderer extension to display it.

Live Markdown editor/preview

MarkdownMode.EditorPreview optimizes for small, frequent edits (a user typing): the MarkdownProcessor keeps state between calls and re-parses only the block(s) that changed instead of the whole document. That statefulness is why an editor-preview processor is tied to one evolving document and must not be shared across unrelated documents (doing so busts the cache and is slower than Standalone). Use MarkdownMode.Standalone (the default, stateless) for content that is parsed once and doesn't change.

For a side-by-side editor and preview:

  1. Keep raw text/editing state in the presenter or state holder, not hidden inside the preview leaf.
  2. Create one MarkdownProcessor(markdownMode = MarkdownMode.EditorPreview(scrollingSynchronizer = ...)) per editable document/preview stream. Do not share editor-preview processors across unrelated documents.
  3. Process edits off the UI path when practical, debounce/drop stale work if the editor can emit faster than rendering.
  4. Render with LazyMarkdown for documents and previews.
  5. Add the expected dialect extensions: autolink is processor-only, tables/strikethrough/alerts need processor and renderer pieces, and images need an image renderer extension.
  6. If scroll sync matters, use the scrolling synchronizer/rendering support rather than ad-hoc list scrolling. Read references/SCROLL-SYNC.md — note the synchronizer currently supports ScrollState, not LazyListState.

AI chat with Markdown

For chat timelines, do not make Markdown own the chat architecture.

Use a presenter/coordinator to project message state, roles, streaming status, and parsed Markdown blocks. The UI should render a LazyColumn of message rows and use Markdown or LazyMarkdown inside text-bearing rows as appropriate. Keep networking, agent protocol, message mutation, and Markdown parsing policy outside leaf composables. Use stable lazy-list keys and content types for heterogeneous chat rows.

Custom syntax: extension or renderer?

Write a custom extension when the Markdown input language changes, e.g., task list items, custom admonitions, ::file:/path/foo.kt::, or another syntax that must parse into a domain model.

Write a custom renderer when the existing parsed model is right, but the UI should change, e.g., headings need link buttons, code blocks need copy buttons, list markers need different layout, or inline images need product-specific treatment.

Many features need both: an extension to parse syntax into model nodes, and a renderer to display those nodes. Some may need more than two parts. See the examples below.

How to write a custom block extension

Use gfm-alerts and gfm-tables as templates.

  1. Define a model type implementing MarkdownBlock.CustomBlock.
  2. Add a MarkdownProcessorExtension.
  3. If CommonMark needs help recognizing the syntax, expose a CommonMark ParserExtension.
  4. Expose a MarkdownBlockProcessorExtension that checks canProcess(CustomBlock) and returns your MarkdownBlock.CustomBlock from processMarkdownBlock.
  5. Set allowsMergingWithNextBlock = true only when incremental editor parsing must reparse a following block that can merge into this one, as tables do.
  6. Add a MarkdownRendererExtension exposing a MarkdownBlockRendererExtension.
  7. In RenderCustomBlock, render native Jewel Compose UI and delegate nested Markdown back to the provided MarkdownBlockRenderer / InlineMarkdownRenderer where possible.
  8. Add standalone and bridge styling helpers when the feature has colors, spacing, borders, or icons.
  9. If the block will be used in an editor preview and should be a scroll-sync target, opt in: the scroll-sync renderer does not wrap custom blocks automatically. Wrap your content in AutoScrollableBlock in RenderCustomBlock. See references/SCROLL-SYNC.md.
  10. Add processor tests and renderer tests or validated sample coverage.

How to write a custom delimited inline extension

Use gfm-strikethrough as the template.

  1. Define a model type implementing InlineMarkdown.CustomDelimitedNode.
  2. Add a MarkdownProcessorExtension with a CommonMark parser extension if needed.
  3. Expose a MarkdownDelimitedInlineProcessorExtension that turns supported CommonMark Delimited nodes into your custom inline node.
  4. Add a MarkdownRendererExtension exposing MarkdownDelimitedInlineRendererExtension.
  5. Render to an AnnotatedString, recursively delegating nested inline content to the supplied InlineMarkdownRenderer.
  6. Add an HTML converter only if embedded HTML should map to the same inline model.

Example: inline icons and rich inline content

MarkdownDelimitedInlineRendererExtension returns only an AnnotatedString. If custom inline syntax must show an icon or other InlineTextContent — for example ::file:/my/path/foo.kt:: with the file icon and name — plan for an extension encompassing parsing plus renderer customization:

  1. Parse the syntax into a custom inline node.
  2. Provide an inline renderer or block renderer path that appends inline-content placeholders for those nodes.
  3. Override the block rendering for text-bearing blocks (Paragraph, headings, table cells, or whichever contexts you support) so the Jewel Text receives the matching inlineContent map.
  4. Use Jewel icon APIs (IconKey, AllIconsKeys, or platform file-type icon APIs in bridge/plugin context) inside the InlineTextContent.
  5. Document supported contexts rather than pretending every Markdown block can host the custom inline content automatically.

Example: GFM task lists

Do not claim Jewel already supports GFM task lists. They are listed as missing/roadmap in Jewel docs. To support - [ ] / - [x] task list items, create and validate a new extension:

  1. Decide whether the model is a custom block/list item wrapper or an extension of list rendering.
  2. Parse checked/unchecked state into an explicit model.
  3. Render with native Jewel checkbox-like visuals, preserving Markdown semantics and disabled/read-only behavior as appropriate.
  4. Validate both processor output and rendering. Include editor-preview incremental parsing if task-list syntax can interact with neighboring list blocks.
  5. If you're rendering interactive components such as checkboxes, make sure their status is managed, and that changes are reflected in the underlying Markdown (e.g., checked state for a checkbox should manifest as [ ] or [x] in text).

Gotchas for custom renderers

When overriding or replacing rendering, preserve the behaviors the default renderer relies on. Each item below is something a custom renderer can silently break.

  • Text alignment: every text-bearing block in DefaultMarkdownBlockRenderer passes textAlign = LocalTextAlignment.current to its Jewel Text. That composition local is set when an aligned block (e.g., an HTML block with an align attribute) wraps its children, so alignment propagates into nested text. A custom Render* override or a renderer written from scratch that emits Text without forwarding the current text alignment will silently lose center/right alignment. Always apply the provided text alignment in custom text rendering. Note LocalTextAlignment is internal to DefaultMarkdownBlockRenderer; prefer subclassing it (and still forwarding textAlign in your override) rather than reimplementing block rendering and dropping this wiring.
  • Content color: text-bearing rendering resolves color via the styling text style falling back to LocalContentColor. Preserve that fallback instead of hardcoding a color.
  • Inline content / images: paragraphs that contain images render through an inlineContent map. If you override paragraph or other text-bearing rendering, keep passing the inlineContent map so images and other inline placeholders still appear.
  • Enabled/disabled state: honor the enabled flag (links non-interactive, disabled styling) rather than always rendering the enabled appearance.
  • Delegation: render nested blocks/inlines through the provided MarkdownBlockRenderer / InlineMarkdownRenderer so styling, extensions, and these behaviors stay consistent.
  • Editor-preview scroll sync: scroll sync is implemented entirely by ScrollSyncMarkdownBlockRenderer (a DefaultMarkdownBlockRenderer subclass that wraps blocks in AutoScrollableBlock and reports layout). If you supply your own block renderer for an editor preview, you bypass that subclass and lose scroll sync. Subclass ScrollSyncMarkdownBlockRenderer instead of DefaultMarkdownBlockRenderer (calling super from your overrides), or re-implement the AutoScrollableBlock wiring yourself. See references/SCROLL-SYNC.md.

General rule: when you override one Render* method, mirror the default implementation's wiring (alignment, color, inline content, enabled state, and editor-preview scroll sync) and change only what you intend to change.

Validation checklist

Before finishing Jewel Markdown work:

  • Confirm runtime context: standalone uses int-ui standalone styling; IntelliJ plugin/bridge uses IDE LaF bridge styling.
  • Confirm required processor and renderer extensions are both wired.
  • Confirm MarkdownProcessor editor-preview instances are not shared across unrelated documents.
  • Confirm heavy parsing is not happening in a hot LazyColumn item body.
  • Confirm code highlighting, image loading, and URL click handling are provided where the UX requires them.
  • Confirm custom syntax has tests for parsing and rendering; for new extensions, use existing extension tests as guides.
  • Confirm task lists or other missing GFM features were implemented/validated, not merely mentioned as supported.
  • Confirm custom text rendering forwards LocalTextAlignment (text alignment), preserves the content-color fallback, keeps the inlineContent map, and honors enabled.
  • Confirm HTML expectations: embedded HTML needs parseEmbeddedHtml = true; custom tag mapping needs a MarkdownHtmlConverterExtension; and unconverted/inline HTML is shown as raw text, not interpreted as native UI.

리뷰

아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.

댓글

로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.

아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.

보내면 바로 공개됩니다. 이메일 주소나 전화번호 같은 개인 정보는 쓰지 마세요. URL은 2개까지입니다.

0 / 1,000자

이 양식은 reCAPTCHA로 보호되며 Google 개인정보처리방침 및 서비스 약관이 적용됩니다.

같은 저장소의 스킬

actions

무료요약 있음

IntelliJ `AnAction` 클래스를 구현하거나 수정하고 `plugin.xml`에 등록하도록 안내합니다. 표시 이름과 설명은 메시지 번들에 두고, 필요하면 아이콘을 설정하며, 이벤트 코루틴 범위에서 중단 함수를 실행해 동기식 처리로 IDE가 멈추는 일을 방지합니다.

  • IDE 메뉴에 새 동작 추가
  • 동작 등록이나 아이콘 변경
  • 동작 이름과 설명 정리
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

bazel-test-migration

무료요약 있음

IntelliJ JPS 테스트 모듈을 Bazel로 옮기고 Bazel에서만 발생하는 실패를 조사하는 안내서입니다. 의존성, 플러그인, 테스트 데이터와 runfiles 문제를 확인하고 생성된 대상과 이전된 테스트를 검증합니다.

  • 기존 JPS 테스트 모듈을 Bazel로 이전할 때
  • Bazel에서만 실패하는 테스트를 조사할 때
  • 테스트 의존성과 데이터 설정을 확인할 때
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

code-style

무료요약 있음

IntelliJ 프로젝트 규칙에 맞춰 Kotlin과 Java 코드를 작성하거나 검토합니다. 언어 선택, 서식, 봉인 타입, 스레드 주석, 제어 흐름 예외 처리를 확인합니다.

  • IntelliJ 규칙에 맞는 Kotlin 작성
  • Java 코드 검토
  • 예외 처리와 봉인 타입 분기 확인
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

commits

무료요약 있음

이 가이드는 IntelliJ 프로젝트의 변경 사항을 목적별로 나누고 프로젝트 형식에 맞는 커밋 메시지를 작성하도록 돕습니다. 티켓이 있으면 번호와 변경 설명을, 없으면 레이블과 하위 시스템명을 사용하며 필요에 따라 이유와 판단을 본문에 담습니다.

  • 티켓이 있는 변경의 프로젝트 형식 메시지 작성
  • 테스트나 문서 커밋에 적절한 레이블 적용
  • 기존 커밋 메시지를 규칙에 맞게 수정
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

compare-python-typecheckers

무료요약 있음

여러 Python 타입 검사기로 코드 조각이나 파일의 타입 추론과 오류 판정을 비교합니다. 도구별 결과, 실행 시간, 진단 내용을 Markdown 보고서로 모아 저장할 수 있습니다.

  • 검사기별 타입 추론 비교
  • 코드가 타입 오류로 판정되는지 확인
  • 여러 도구의 진단 결과 비교
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

compose-ui-architecture

무료요약 있음

Compose Desktop 화면을 구성할 때 컴포저블은 렌더링을 맡고 프레젠터나 코디네이터는 앱 결정을 맡도록 구조를 정리합니다. 상태 소유권, Effect, 재사용 컴포넌트 API, 지연 목록 키, 애니메이션과 성능을 개별 UI 변경에 맞춰 살펴봅니다.

  • 화면 렌더링과 프레젠터 판단 분리
  • UI 상태를 둘 위치 정리
  • Effect 키와 코루틴 사용 검토
JetBrains/intellij-community2.1만2026년 10월 29일 업데이트

JetBrains의 스킬 모두 보기

이 스킬의 문제 신고