IntelliJ `AnAction` 클래스를 구현하거나 수정하고 `plugin.xml`에 등록하도록 안내합니다. 표시 이름과 설명은 메시지 번들에 두고, 필요하면 아이콘을 설정하며, 이벤트 코루틴 범위에서 중단 함수를 실행해 동기식 처리로 IDE가 멈추는 일을 방지합니다.
- IDE 메뉴에 새 동작 추가
- 동작 등록이나 아이콘 변경
- 동작 이름과 설명 정리
Jewel Markdown의 파싱부터 Compose 렌더링까지 구성하고 문제를 살펴봅니다. 표, 내장 HTML, 이미지, 코드 강조 표시, 실시간 편집기 미리보기에 맞춰 스타일과 파서·렌더러 확장을 선택하고 기본 표시 동작을 유지하도록 안내합니다.
Build or debug Jewel Markdown parsing, rendering, and styling.
실행 점수 미검증
설치 방법 보기Jewel Markdown의 파싱과 표시 흐름을 구성하고 문제를 살펴보는 방법을 안내합니다. MarkdownProcessor는 Markdown 문자열을 MarkdownBlock과 InlineMarkdown 모델로 변환하고, Jewel Compose 렌더러가 이를 화면에 표시합니다. 모양만 바꾸려면 MarkdownStyling을 조정하고, 기존 블록이나 인라인 콘텐츠의 표시 동작을 바꾸려면 해당 렌더러 확장을 사용합니다. 새 구문을 추가할 때는 파서 확장과 렌더러 확장을 함께 구성합니다. GFM 표와 취소선, 알림, 이미지, 코드 강조 표시, 내장 HTML, 편집 내용에 따라 갱신되는 미리보기도 다룹니다. 사용자 정의 렌더러에서는 필요한 경우 정렬, 색상, 인라인 이미지, 비활성 상태, 미리보기 스크롤 동기화 동작을 유지하는 점도 확인합니다.
앱에 Jewel Markdown을 넣거나 기존 스타일과 블록 동작을 바꾸려는 경우에 활용할 수 있습니다. 사용자 정의 구문이나 HTML 태그를 추가하거나 이미지와 코드를 표시할 때도 적합합니다. 편집기와 실시간 미리보기를 연결할 때 사용할 수 있으며, 채팅 Markdown에서는 메시지 관리와 표시 처리를 분리하는 구성을 안내합니다.
이미지 확장 예시에는 Coil3가 포함됩니다. 코드 강조 표시의 기본 제공 방식은 IDE 플러그인과 독립 실행 환경에서 다릅니다. 내장 HTML 파싱은 기본적으로 꺼져 있습니다.
이 소개문은 공개된 SKILL.md를 바탕으로 AI(OpenAI Codex)가 작성했습니다. 정확한 사양은 아래 원문을 확인하세요.
AI가 SKILL.md의 내용에서 주의가 필요한 작업과 도입 전제를 확인했습니다. 점수는 실제로 실행한 결과(실행 검증)만으로 매깁니다.
점수에는 넣지 않았습니다. 2026년 10월 28일 기준으로 AI(OpenAI Codex)가 판정했습니다. 참고용이므로 설치 전에 원문도 확인해 주세요.
설치하기 전에 에이전트에게 전달되는 지시 내용을 확인할 수 있습니다.
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.MarkdownStyling and theme-specific styling helpers.MarkdownBlockRenderer, usually by subclassing DefaultMarkdownBlockRenderer and overriding
the specific Render* method.InlineMarkdownRenderer, usually by subclassing DefaultInlineMarkdownRenderer.ImageRendererExtension, not a general block renderer.parseEmbeddedHtml on the MarkdownProcessor, and for custom HTML→Markdown mapping add a
MarkdownHtmlConverterExtension.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.
MarkdownProcessor parses raw Markdown into List<MarkdownBlock>.InlineMarkdown nodes.Markdown renders short/simple content in a Column; LazyMarkdown renders larger or editor-preview content in a LazyColumn.MarkdownBlockRenderer renders block nodes and delegates inline content to InlineMarkdownRenderer.ProvideMarkdownStyling wires LocalMarkdownStyling, LocalMarkdownProcessor, LocalMarkdownBlockRenderer, and code/image support
into JewelTheme.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.
Use the existing extension modules before inventing syntax:
AutolinkProcessorExtension to the MarkdownProcessor.GitHubTableProcessorExtension and GitHubTableRendererExtension. The processor extension also bundles a
MarkdownHtmlConverterExtension for <table> (active when parseEmbeddedHtml = true).GitHubStrikethroughProcessorExtension and GitHubStrikethroughRendererExtension. The processor extension also
bundles a MarkdownHtmlConverterExtension for <s>, <strike>, and <del> (active when parseEmbeddedHtml = true).GitHubAlertProcessorExtension and GitHubAlertRendererExtension.ImageRendererExtension, commonly Coil3ImageRendererExtension, to the renderer extensions and provide an image source
resolver where needed. For details read references/IMAGE-LOADING.md.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.
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:
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.<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.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.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).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:
MarkdownProcessor(markdownMode = MarkdownMode.EditorPreview(scrollingSynchronizer = ...)) per editable document/preview
stream. Do not share editor-preview processors across unrelated documents.LazyMarkdown for documents and previews.references/SCROLL-SYNC.md — note the synchronizer currently supports ScrollState, not LazyListState.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.
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.
Use gfm-alerts and gfm-tables as templates.
MarkdownBlock.CustomBlock.MarkdownProcessorExtension.ParserExtension.MarkdownBlockProcessorExtension that checks canProcess(CustomBlock) and returns your MarkdownBlock.CustomBlock from
processMarkdownBlock.allowsMergingWithNextBlock = true only when incremental editor parsing must reparse a following block that can merge into this one,
as tables do.MarkdownRendererExtension exposing a MarkdownBlockRendererExtension.RenderCustomBlock, render native Jewel Compose UI and delegate nested Markdown back to the provided MarkdownBlockRenderer /
InlineMarkdownRenderer where possible.AutoScrollableBlock in RenderCustomBlock. See references/SCROLL-SYNC.md.Use gfm-strikethrough as the template.
InlineMarkdown.CustomDelimitedNode.MarkdownProcessorExtension with a CommonMark parser extension if needed.MarkdownDelimitedInlineProcessorExtension that turns supported CommonMark Delimited nodes into your custom inline node.MarkdownRendererExtension exposing MarkdownDelimitedInlineRendererExtension.AnnotatedString, recursively delegating nested inline content to the supplied InlineMarkdownRenderer.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:
Paragraph, headings, table cells, or whichever contexts you support) so the Jewel
Text receives the matching inlineContent map.IconKey, AllIconsKeys, or platform file-type icon APIs in bridge/plugin context) inside the InlineTextContent.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:
[ ] or [x] in text).When overriding or replacing rendering, preserve the behaviors the default renderer relies on. Each item below is something a custom renderer can silently break.
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.LocalContentColor. Preserve that
fallback instead of hardcoding a color.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 flag (links non-interactive, disabled styling) rather than always rendering the enabled
appearance.MarkdownBlockRenderer / InlineMarkdownRenderer so styling, extensions,
and these behaviors stay consistent.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.
Before finishing Jewel Markdown work:
MarkdownProcessor editor-preview instances are not shared across unrelated documents.LazyColumn item body.LocalTextAlignment (text alignment), preserves the content-color fallback, keeps the
inlineContent map, and honors enabled.parseEmbeddedHtml = true; custom tag mapping needs a MarkdownHtmlConverterExtension;
and unconverted/inline HTML is shown as raw text, not interpreted as native UI.아직 리뷰가 없습니다. 사용해 본 소감을 남겨 주세요.
로그인 없이 쓸 수 있습니다. 사용 후기, 질문, 작동하지 않은 환경 등을 편하게 남겨 주세요.
아직 댓글이 없습니다. 첫 댓글을 남겨 보세요.
IntelliJ `AnAction` 클래스를 구현하거나 수정하고 `plugin.xml`에 등록하도록 안내합니다. 표시 이름과 설명은 메시지 번들에 두고, 필요하면 아이콘을 설정하며, 이벤트 코루틴 범위에서 중단 함수를 실행해 동기식 처리로 IDE가 멈추는 일을 방지합니다.
IntelliJ JPS 테스트 모듈을 Bazel로 옮기고 Bazel에서만 발생하는 실패를 조사하는 안내서입니다. 의존성, 플러그인, 테스트 데이터와 runfiles 문제를 확인하고 생성된 대상과 이전된 테스트를 검증합니다.
IntelliJ 프로젝트 규칙에 맞춰 Kotlin과 Java 코드를 작성하거나 검토합니다. 언어 선택, 서식, 봉인 타입, 스레드 주석, 제어 흐름 예외 처리를 확인합니다.
이 가이드는 IntelliJ 프로젝트의 변경 사항을 목적별로 나누고 프로젝트 형식에 맞는 커밋 메시지를 작성하도록 돕습니다. 티켓이 있으면 번호와 변경 설명을, 없으면 레이블과 하위 시스템명을 사용하며 필요에 따라 이유와 판단을 본문에 담습니다.
여러 Python 타입 검사기로 코드 조각이나 파일의 타입 추론과 오류 판정을 비교합니다. 도구별 결과, 실행 시간, 진단 내용을 Markdown 보고서로 모아 저장할 수 있습니다.
Compose Desktop 화면을 구성할 때 컴포저블은 렌더링을 맡고 프레젠터나 코디네이터는 앱 결정을 맡도록 구조를 정리합니다. 상태 소유권, Effect, 재사용 컴포넌트 API, 지연 목록 키, 애니메이션과 성능을 개별 UI 변경에 맞춰 살펴봅니다.