risum 모듈 — RISU modules[] — 기능 확장
조회 1365 · 2026-07-03
**-- Main Container --** **-- Header --** 라이트보드 나무위키 개조버전 v1.8.1 | 원본 v1.8.0 기반 개조 **-- Intro --** AI 채팅 속 세계관과 캐릭터들을 나무위키 스타일 문서로 생성해주는 라이트보드 모듈의 개조버전입니다. 원본의 기능을 유지하면서 관점 전환, 스포일러 접기, 헤딩 접기, 창의성 조절 등 다양한 기능이 추가되었습니다. **-- Example --** 결과물 예시 더 많은 예시 보기 **-- Download --** 다운로드 개조버전 v1.8.1 프로톤 원본 v1.8.0 아카라이브 원본글 **-- Changes --** 원본과의 차이점 관점 전환 "세계관 내부" 또는 "현실의 위키" 중 선택할 수 있습니다. 현실의 위키를 선택하면 캐릭터를 작품 속 등장인물로, 세계관을 작품의 설정으로 서술합니다. 세계관 내부는 원본과 동일하게 모든 것을 실제 존재하는 것처럼 서술합니다. 메타 정보 입력 현실의 위키 관점에서 작품의 종류(웹소설, 만화, 게임 등), 장르, 작가명 등을 직접 지정할 수 있습니다. AI가 문서를 쓸 때 이 정보를 참고합니다. 창의성 조절 AI가 문서를 작성할 때 얼마나 자유롭게 내용을 창작할지 3단계로 조절 가능합니다. "엄격하게"는 채팅 내역에 있는 정보만, "적당히 추론"은 자연스러운 추론 허용, "적극적 창작"은 설정에 맞는 내용을 자유롭게 만들어냅니다. 스포일러 접기 토글에서 스포일러를 "접기"로 설정하면, AI가 중요 스포일러를 클릭해야만 볼 수 있도록 숨겨서 작성합니다. 헤딩(목차) 접기 AI가 판단해서 길거나 스포일러가 많은 섹션을 기본적으로 접힌 상태로 생성할 수 있습니다. 클릭하면 펼쳐집니다. 주제별 적응형 문서 구조 원본은 항상 같은 구조로 문서를 생성하지만, 개조버전은 주제 유형에 따라 구조가 달라집니다. 가상 캐릭터는 "작중 행적/특징", 창작물은 "시놉시스/등장인물/설정", 실존 인물은 "생애/작품 목록" 등으로 자동 분류됩니다. 컨텍스트 제어 포함 채팅 수와 최대 컨텍스트 크기를 직접 지정할 수 있는 토글이 추가되었습니다. 비워두면 라이트보드 백엔드 기본 설정을 따릅니다. NSFW 자동 필터링 최근 채팅에 성적 묘사가 없거나 성인 작품으로 명시되지 않은 경우, 캐릭터 시트에 성적 설정이 있더라도 위키 문서에는 반영하지 않습니다. 단, 연애나 관계 설정은 정상적으로 작성됩니다. 기타 개선 하단 바(관련 문서, 새로고침 버튼 등)의 레이아웃이 개선되었습니다. 주석 펼치기 모드에서도 하단 바와 내부 링크가 정상적으로 표시됩니다. **-- Caution --** 주의사항 / 알려진 이슈 개조 후 "현실의 위키" 관점만 테스트되었습니다. "세계관 내부" 관점은 원본과 동일하게 동작할 것으로 예상되지만, 개조 과정에서 미처 확인하지 못한 문제가 있을 수 있습니다. 문제가 발견되면 알려주시면 감사하겠습니다. **-- Dependency --** 필수 의존성 이 모듈은 단독으로 동작하지 않습니다. 반드시 라이트보드 백엔드 모듈 이 함께 설치 및 활성화되어 있어야 합니다. **-- End Main Container --** 나는 작품의 위키를 읽고싶은데 원본에서는 메타서술을 금지하고 있어서 개조하기 시작함 겸사겸사 컨텍 덮어쓰기도 만들긴 했는데 사실 이건 잘 작동되는지 테스트 안 해봤고 지금 생각해보니까 안 만들어도 되지 않았나 싶기도 함... ㅋㅋ 원본 제작자가 내려달라고 하면 언제든 내려갈 수 있음 CC BY-NC-SA 4.0 국제 라이선스 적용 이 저작물은 크리에이티브 커먼즈 저작자표시-비영리-동일조건변경허락 4.0 국제 라이선스 에 따라 이용할 수 있습니다. 이 저작물은 아카라이브 커뮤니티 - AI 채팅 채널 을 위해 공개되었으며, AI 채팅 채널 외 타 채널 혹은 커뮤니티에 공유, 배포 등 으로 이용할 때에는 반드시 원 저작자의 이름과 출처를 명시 해야 합니다. 상업적 용도의 경우 어떠한 이유로도 이용할 수 없습니다. 리믹스, 변형, 2차적 저작물을 작성하고 그 결과물을 공유할 경우에는 원 저작물과 동일한 조건의 CCL 을 적용하여야 합니다.
나무위키 모듈 개조버전
{
"name": "🔦라이트보드 나무위키 개조버전 v1.8.1",
"description": "나무위키 모듈 개조버전",
"lorebook": [
{
"key": "",
"comment": "manifest.lb",
"content": "identifier=lightboard-namuwiki\n\nauthorsNote=true\ncharDesc=true\nloreBooks=true\npersonaDesc=true\nrerollBehavior=remove-prev",
"mode": "normal",
"insertorder": 100,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"comment": "lightboard-namuwiki.lb",
"content": "# Simulation Details\n\n## About the Wiki\nNamuwiki: A collaborative wiki encyclopedia written in Korean, similar to the real Namuwiki, with articles documenting various topics including creative works, fictional characters, settings, and real-world creators. \n\n{{#when::lightboard-namuwiki.perspective::tis::1}}\nThe article content should be simulated from an out-of-universe perspective. Editors are real people in the real world contributing to a public knowledge base. The article subject can be a fictional element (character, setting), a creative work (manga, game, anime), or a real person (author, director).\n\n**OUT-OF-UNIVERSE RULE**: You MUST write from an out-of-universe (real world) perspective.\n- ENCOURAGED META-TERMS: Actively use terms like '작품', '연재', '설정', '세계관', '작중 행적', '캐릭터', '작가', '생애'.\n- For fictional subjects, DO NOT treat the events as real historical facts. Describe them as events happening within the story of the fictional work.\n{{#when::keep::{{? {{length::{{trim::{{getglobalvar::toggle_lightboard-namuwiki.meta_info}}}}}} > 0}}}}\n- META INFORMATION: {{getglobalvar::toggle_lightboard-namuwiki.meta_info}}\n{{/when}}\n{{/when}}\n{{#when::lightboard-namuwiki.perspective::tis::0}}\nThe article content should be simulated from an in-universe perspective.\n\n**STRICT IN-UNIVERSE RULE**: You MUST write from an in-universe perspective. DO NOT break the 4th wall.\n- FORBIDDEN META-TERMS: DO NOT use meta-terms like '작품', '연재', '설정', '세계관', '작중 행적', '캐릭터', '작가'.\n- Treat the subject and events as real historical facts happening in reality. Use terms like '생애', '역사', '인물' instead.\n{{/when}}\n\n## Doc Title\nSpecifies the topic. doc_title may have an optional specific sub-topic, like '홍길동/논란 및 사건 사고'.\nDoc Title is search_term.\nsearch_term is \"{{getglobalvar::toggle_lightboard-namuwiki.search}}\".\nif search_term is blank, choose popular article from the universe except {{user}}.\n\n## Tone and Manner\nThe overall tone of a Namuwiki article is encyclopedic but often informal. It's a collective voice formed by many anonymous editors. All descriptions should be more detailed and written at greater length to provide rich context. Key characteristics include:\n\n### Fact-based but Opinionated\nWhile it aims to present facts, articles usually contain subjective analysis, interpretations, and even sarcasm.\n\n### Use of Slang and Memes\nIt's common to see modern internet slang, memes, and in-jokes integrated directly into the text to explain concepts or add color.\n\n### Jokes and Gags\nThere are many bolds('❗(bold text)❗'), Strikethrough('✂️(strikethrought text)✂️') and footnotes('📌(footnote text)📌') in the article. These are exclusively used for short, punchy humorous gags, jokes, sarcasm, and comedic asides — never for conveying serious factual information. Keep them brief and witty; long or informational use of these formats is discouraged. \n**STRICT RULE FOR FOOTNOTES**: YOU MUST place a Footnote for a full sentence ('📌full sentence📌'). Inserting a footnote between words, inside a phrase, or before a sentence concludes is FORBIDDEN.\n\n### Internal links\nInternal Link is '➡️linked_article_title➡️' . This represents a hyperlink to another article (e.g., a person, organization, event, system, ability, or any proper noun) within the wiki. Internal link syntax can be used within any content block, such as [Infobox], [Quote], [Paragraph], [List], [Table] and [Heading] titles.\nTo ensure readability and avoid visual clutter, the same term must not be hyperlinked multiple times within a single content block (e.g., linking the same word repeatedly inside one [Paragraph] or [List] item).\n\n### \"Namuche\" (나무체)\nA distinctive writing style that ends sentences with clauses like ~한다, ~이다, giving it a slightly detached, descriptive feel. Periods are generally used.\n\n### User's direction: Provides specific instructions on the content, tone, or details to include.\nUser's direction is {{getglobalvar::toggle_lightboard-namuwiki.direction}}.\nFollowing the User's direction is mandatory.User's direction must be strictly followed. \n\n## Article Content Guide\nThe article's content should reflect the narrative. The Article Content should be generated based on the doc_title type.\n\n### Content Restrictions (NSFW)\nIf there is no explicit sexual description in the recent chat history or the work is not explicitly stated as adult-oriented, you MUST completely ignore sexual settings in the character sheet and DO NOT write them in the wiki. However, DO NOT ignore romance or relationship settings; you may write about them.\n\n## Recommended Article Heading titles.\nThe Article Heading titles MUST be dynamically generated based on the subject type. \n\nIf the subject is a Fictional Character or Setting:\n1. Overview ('개요'): A summary of the subject. Include 1~2 '[Quote]' block.\n2. In-Story Actions ('작중 행적'): A description of the character's actions and history within the narrative.\n3. Characteristics ('특징'): Appearance, personality, or abilities.\n\nIf the subject is a Creative Work (e.g., Manga, Game, Movie):\n1. Overview ('개요'): A summary of the work. Include 1~2 '[Quote]' block.\n2. Synopsis ('시놉시스' or '줄거리'): The premise or plot.\n3. Characters ('등장인물'): Key figures in the work.\n4. Setting ('설정'): World-building elements.\n\nIf the subject is a Real Person (e.g., Author, Director):\n1. Overview ('개요'): A summary of the person. Include 1~2 '[Quote]' block.\n2. Life and Career ('생애' or '경력'): Their personal and professional history.\n3. Style/Characteristics ('작풍' or '특징'): Their creative style.\n4. Works ('작품 목록'): Notable works they created.\n\nCommon Headings for ALL types:\n- Controversies and Incidents ('논란 및 사건 사고'): Notable incidents.\n- Evaluation ('평가'): Contains '긍정적 평가', '부정적 평가', '복합적 평가'.\n- Trivia ('여담'): Anecdotes or interesting facts.\n\n## Topics\nArticles can cover any topic relevant to the in-universe setting: people, places, events, technology, culture, organizations, etc.\n\n## Major Characters\nProtagonists and major characters do not edit the wiki themselves unless the narrative explicitly states they do. They are the subjects of articles, not the authors.\n\nInformation in an article about a major character should reflect their public persona, known history, and confirmed deeds.\n\n## Key Syntax\n\n### Image Formatting Rule\nWhenever you display ANY image in the article (such as in Paragraph, Table, CategoryTable), you MUST refer to the provided image tag rules to find ONLY the exact image file name.\nExcept for {{user}} image '{{source::user}}',\nyou MUST STRICTLY format the image name using the raw syntax: '{{raw::image_name}}'.\n\n### Main Tag\nUse '<lightboard-namuwiki doc_title=\"(article title)\" main_color=\"(#hexcode)\" asset_src=\"(asset_name)\"\n related1=\"(related article1)\" related2=\"(related article2)\" related3=\"(related article3) recent1=\"(recent article1) recent2=\"(recent article2) recent3=\"(recent article3)\" >'. Must close the entire block with '</lightboard-namuwiki>'.\n\ndoc_title: The title of the article. doc_title may have an optional specific sub-topic like '홍길동/논란 및 사건 사고'.\nmain_color: A representative CSS hex color code (#hexcode) for the article's subject (ex: character's hair color). hexcode must be 6 hex characters.\nrelated1, related2, related3: Detailed sub-topics about current doc_title, format is 'doc_title/sub-topic'.\nrecent1, recent2, recent3: The articles that appeared recently. Newly introduced events, organizations, etc. but not linked in the current article.\n\nasset image name: Must strictly follow rules below.\n{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.show_asset}} == 1 }} }}\nasset image name for {{user}} is \"{{source::user}}\".\nOtherwise, select proper image name from the image tag or image command rule for the asset image name. If the image name rule includes emotion or pose, select it appropriately that represents the article content. Must extract only the image name. asset_name = \"{{raw::(proper_img_name)}}\".\nIf there is no proper image, asset_name = \"\".\n{{/if}}\n\n{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.show_asset}} == 0 }} }}\nasset_name must be blank\n{{/if}}\n\n### Inline Formatting\nThe syntax for Strikethrough is '✂️strikethrough_text✂️'.\nThe syntax for Footnote is '📌footnote_text📌'.\nThe syntax for Bold is '❗bold_text❗'.\nThe syntax for Internal link is '➡️internal_link➡️'.\nThe syntax for Spoiler is '👻spoiler_text👻'.\nUse these inline formattings properly. Inline Formatting must be used separately. Do not nest these formatting types within each other.\nInline formatting must be completed before starting a new one. Do not start a new inline formatting before closing the current one. Opened Inline formatting must be closed properly.\n\n### Infobox\n'[Infobox]Title:John|Age:23|...' creates the information box. Fields are divided by '|'. No field related with image.\n\n### Table of Contents (TOC)\n'[Toc]' marks the position for the auto-generated Table of Contents.\n\n### Quote Box\n'[Quote]...|Source:...|' Creates an italicized blockquote. Paragraph must be followed after Quote box.\n\n### Heading\n'[Heading]Level:1|Title:Overview' starts a new section. 'Level' determines if it's a main heading (1) or subheading (2). Divide fields within tags like '[Infobox]' and '[Heading]' with '|'.\nIf a heading contains massive spoilers or overly long details, you can add 'Collapsed:true' to hide it by default like '[Heading]Level:1|Title:Overview|Collapsed:true'.\nLevel1 heading titles should be simple, level2 heading tiltes should be specific and concise. Headings must contain Paragraphs.\n\n### Paragraph\n'[Paragraph] (main content...)' Paragraph must contain the main body content for a section, elaborating on the preceding '[Heading]'. This section requires substantial volume and is where you should write detailed descriptions, specific episodes, and in-depth explanations. It should actively include Namuwiki-style trivial content, such as TMI or behind-the-scenes stories, not just core facts.\n- You should insert an image with a caption inside a Paragraph, List, or Quote using image syntax: ''. Every image in these sections MUST have a descriptive caption. (e.g., '')\n- Do NOT use images of people or characters inside a Paragraph, List, or Quote. The use of character portraits to describe anecdotes or events is FORBIDDEN. Only use images of items, places, objects, or conceptual logos in these sections.\n{{#when::lightboard-namuwiki.spoiler::tis::1}}\n- **SPOILER RULE**: If the information contains major spoilers, you MUST wrap the spoiler content with '👻' emojis to hide it. Use '👻spoiler content👻'.\n{{/when}}\n\n### List Item\n'[List]This is a list item. It can be used in any section to create a bulleted list. Usually used in Trivia section.\n\n### Category Table\n'[CategoryTable]Caption:Category Name|Color:#hexcode|Head:H1;;H2...|Row:➡️C1➡️;;➡️C2➡️...' creates a collapsible category table.\nA Category Table MUST be inserted at the very beginning of the content (before [Toc] or [Infobox]).\n- You SHOULD output MULTIPLE Category Tables when the subject belongs to multiple classification systems, including both specific groups and broader, more general categories. Categories can be hierarchical, ranging from higher-level classifications to more specific subcategories, and may include diverse dimensions like occupation, affiliation, region, rank, origin, race, and any other applicable classifications.\n- Do NOT create a Category Table if the category, organization, or group has only one member.\n- The 'Caption' MUST be the exact name of that organization, group, or category (e.g., 'Caption:Student Council').\n- It MUST have a unique 'Color' (#hexcode) representing the category.\n- The Rows MUST contain ALL members, items, or sub-documents that belong to this category. EVERY member or item name MUST be formatted as an internal link using '➡️Item Name➡️'.\n**STRICT RULE FOR CATEGORY TABLE**: You MUST include representative images (leader, residence, etc) for every item in each cell. Include their image and name in the SAME cell separated by a space. If the person or item has a specific position, title, or alias, you MUST include it using '<br>' for a line break (e.g., '{{raw::representative_img}} Position/Alias<br>➡️Item Name➡️'). A space after the image tag is MANDATORY.\n- A single 'Row' MUST have a maximum of 5 items. If there are more than 5 members in the category, do NOT create a new '[CategoryTable]'. Instead, wrap them by adding another 'Row' property to the SAME table (e.g., '|Row:...|Row:...').\n- Table Structure Elements:\n - 'Head': Defines top-side column headers to group columns (e.g., '|Head:Unit 1;;Unit 2').\n - 'RowHead': Defines a row with a left-side header. The first cell becomes the header and should be an internal link. Multiple 'RowHead' properties can be used sequentially to create multiple rows with left-side headers (e.g., '|RowHead:➡️1학년➡️;;{{raw::img}} ➡️Name➡️').\n - 'Row': Defines a standard row of items.\nOrganize the table naturally using 'Head', 'RowHead', or 'Row' depending on the category's hierarchy and structure. For instance, complex organizations can utilize 'Head' or 'RowHead' to clarify roles, while simple groups can rely solely on 'Row' with aliases (e.g., '|Row:{{raw::img}} ➡️Role➡️<br>➡️Name➡️'). Use either RowHead or Row consistently throughout; do not mix both formats within the same table.\n\n### Table\n'[Table]Caption:Title|Color:#hexcode|Head:H1;;H2;;H3|Row:C1;;C2;;C3' creates a standard table.\nCreate a '[Table]' if it has 3 or more 'Head' columns AND 4 or more 'Row's of data. Do NOT use a '[Table]' for short data that only has 1 or 2 rows or columns. Use '[Paragraph]' or '[List]' instead.\nUse ';;' as separator for cells in a row. Use '|' as separator for properties.\nDo NOT create a 'Image' (이미지/사진) head. The image and the item MUST share a single column.\n[Table] is optional, and you may use it only when the context is suitable for a tabular format considering the of the content of the Paragraph.\nAppropriate Use Cases: Statistics, specifications comparison, organizational roles and responsibilities, event timelines.\nInappropriate Use Cases: Subjective evaluations, relationship descriptions, anecdotes, behavioral pattern analyses, or any narrative content. These should be written in [Paragraph] or [List] format, not a table.\nInside 'Row', you MUST include representative images for every item in each cell if they exist in the image tags or rules. A space after each image tag is MANDATORY.\nThe number of items separated by ';;' in a single 'Row' MUST exactly match the number of columns defined in the 'Head'.\n- Do NOT chain multiple rows of data into a single 'Row' property. Each new row MUST be created as a separate property using '|' (e.g., '|Row:A1;;B1;;C1|Row:A2;;B2;;C2|Row:A3;;B3;;C3').\n- If you need a left-side row header for specific rows, use 'RowHead' instead of 'Row' (e.g., '|RowHead:HeaderName;;C2;;C3'). The first cell will be formatted as a header. Use either RowHead or Row consistently throughout; do not mix both formats within the same table\n\n## Content Generation Guidelines\nThe content should be structured like a real wiki article.\nStart with 1 or more Category Tables.\nWrite 6-8 infobox property. Write 6~8 main headings ('Level:1') and optionally add 2~6 subheadings ('Level:2') under them. Write 2~4 [Paragraph] for each [Heading]. Each paragraph contains long detailed contents including line breaks ('\\n'). Use 0~2 Strikethroughs, 0~2 Bolds,\n{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.length}} == 0 }} }} 4~6 {{/if}}\n{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.length}} == 1 }} }} 3~5 {{/if}}\n{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.length}} == 2 }} }} 5~7 {{/if}}\n{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.length}} == 3 }} }} 6~8 {{/if}}\nsentences for each paragraph.\nUse 6~9 Footnotes for the entire article.\nDescribe paragraph content in a specific, detailed, and thorough way like real namu-wiki style in fluent Korean language.",
"mode": "normal",
"insertorder": 1,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"comment": "lightboard-namuwiki.lb.format",
"content": "<lightboard-namuwiki doc_title=\"(Document Title)\" main_color=\"(#hexcode)\" asset_src=\"(asset_name)\"\n related1=\"(related article1)\" related2=\"(related article2)\" related3=\"(related article3) recent1=\"(recent article1) recent2=\"(recent article2) recent3=\"(recent article3)\">\n[CategoryTable]Caption:(Category 1)|Color:(#hexcode)|Row:(Row contents...)|Row:(Row contents...)|...\n[CategoryTable]Caption:(Category 2)|Color:(#hexcode)|Row:(Row contents...)|Row:(Row contents...)|...\n[Infobox]Title:(doc_title)|(key:value...)|...\n[Toc]\n[Heading]Level:1|Title:Overview\n[Quote](A famous quote or an evaluation of the subject.)|Source:(Attribution)\n[Paragraph](Paragraph content...)\n[Paragraph](Paragraph content...  ...)\n[Heading]Level:1|Title:(Adaptive Heading 1: e.g., In-Story Actions / Synopsis / Life)\n[Paragraph](Paragraph content...)\n[Paragraph](Paragraph content...)\n(optional)[Table]Caption:➡️(Table Caption)➡️|Color:(#hexcode)|Head:(Head contents...)|RowHead:(Left Header);;(Row contents...)|Row:(Row contents...)\n[Heading]Level:1|Title:(Adaptive Heading 2: e.g., Characteristics / Characters / Works)\n[Paragraph](Paragraph content...)\n[Heading]Level:1|Title:Evaluation\n[Heading]Level:2|Title:Positive Evaluation\n[Quote](A famous quote or an evaluation of the subject.)|Source:(Attribution)\n[Paragraph](Positive evaluation content...)\n[Heading]Level:2|Title:Negative Evaluation\n[Paragraph](Negative evaluation content...)\n[Heading]Level:2|Title:Mixed Evaluation\n[Paragraph](Mixed evaluation content...)\n[Heading]Level:1|Title:Trivia\n[Paragraph](Paragraph content...)\n[List](First trivia item...)\n[List](Second trivia item...)\n(...)\n</lightboard-namuwiki>",
"mode": "normal",
"insertorder": 1,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"comment": "lightboard-namuwiki.lb.thoughts",
"content": "Think step-by-step for final data, but keep minimal draft per step. Always include subject and object. Total no more than 8 words per step (exclude step label).\n\nSuggestion:\n1. User's direction is: ...\n2. Generate Namuwiki-style content: ...\n3. Mandatory Category Table at top: ...\n4. Image name format: ...",
"mode": "normal",
"insertorder": 1,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"comment": "lightboard-namuwiki.lb.interaction",
"content": "# Namuwiki Module Interaction Guide\nYour ultimate task: Replace the last data block with a completely new Namuwiki article according to the user's direction.\n\n## RelatedArticle/(New_topic)\nChange the doc_title attribute to the given New_topic, ignore search_item. doc_title may have an optional specific sub-topic, like '홍길동/논란 및 사건 사고'.\n\n## ChangeArticle/(New_topic)\nChange the doc_title attribute to the given New_topic, ignore search_item. doc_title may have an optional specific sub-topic, like '홍길동/논란 및 사건 사고'.\n\nHow to change article: REPLACE THE WHOLE <lightboard-namuwiki> DATA BLOCK WITH A NEW, COMPLETE ARTICLE based on the topic specified in the user's input.\n\nWriting direction is {{getglobalvar::toggle_lightboard-namuwiki.direction}}\n{{#when::lightboard-namuwiki.perspective::tis::1}}\n{{#when::keep::{{? {{length::{{trim::{{getglobalvar::toggle_lightboard-namuwiki.meta_info}}}}}} > 0}}}}\nMETA INFORMATION: {{getglobalvar::toggle_lightboard-namuwiki.meta_info}}\n{{/when}}\n{{/when}}\n\nGenerate new related articles and recent articles for new article.\n\nGenerate a completely new article body, including a relevant [Infobox], [Quote], [Heading], [Paragraph], [Trivia] sections.\n\nThe new article must adhere to all guidelines specified in the Simulation Details document (tone, structure, formatting, content length, etc.).\n\nIf the User's direction includes specific details, tone, or manner, apply them to the new article's content.\n\nThe newly generated article must not be a simple copy of a real-world wiki page, but a creative work written in the Namuwiki style based on the given narrative context.\n\nMust close the entire block with '</lightboard-namuwiki>'.",
"mode": "normal",
"insertorder": 1,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"comment": "lightboard-namuwiki.lb.thoughts-interaction",
"content": "Think step-by-step for final data, but keep minimal draft per step. Always include subject and object. Total no more than 8 words per step (exclude step label).\n\nSuggestion:\n1. User's direction is: ...\n2. Generate Namuwiki-style content: ...\n3. Mandatory Category Table at top: ...\n4. Image name format: ...",
"mode": "normal",
"insertorder": 1,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"comment": "lightboard-namuwiki.lb.onOutput",
"content": "function onOutput(triggerId, output)\n if not string.find(output, \"</lightboard%-namuwiki>\") then\n output = output .. '\\n</lightboard-namuwiki>'\n end\n\n return output\nend\n\nreturn onOutput",
"mode": "normal",
"insertorder": 100,
"alwaysActive": false,
"secondkey": "",
"selective": false,
"useRegex": false,
"bookVersion": 2
},
{
"key": "",
"content": "{{#when::lightboard-namuwiki.perspective::tis::1}}\nYour job is to simulate a real-world wiki encyclopedia (like Namuwiki). Treat the current narrative universe as a published fictional work (web novel, manga, game, etc.) or document real-world subjects (authors, etc.).\n{{#when::keep::{{? {{length::{{trim::{{getglobalvar::toggle_lightboard-namuwiki.meta_info}}}}}} > 0}}}}\nMETA INFORMATION: {{getglobalvar::toggle_lightboard-namuwiki.meta_info}}\n{{/when}}\n{{/when}}\n{{#when::lightboard-namuwiki.perspective::tis::0}}\nYour job is to simulate a wiki encyclopedia within the narrative universe. Treat the events and characters as real historical facts.\n{{/when}}\n\n{{#when::lightboard-namuwiki.creativity::tis::0}}\nYou MUST STRICTLY base the article ONLY on the provided chat log and lorebooks. DO NOT invent or hallucinate unprovided information. If information is missing, omit it or state it is unknown.\n{{/when}}\n{{#when::lightboard-namuwiki.creativity::tis::1}}\nYou should base the article on the provided chat log and lorebooks, but you are ALLOWED to naturally EXTRAPOLATE minor details that fit the established narrative and tone if direct information is missing.\n{{/when}}\n{{#when::lightboard-namuwiki.creativity::tis::2}}\nYou MUST ACTIVELY INVENT and CREATIVELY HALLUCINATE plausible information, history, and details that fit the current universe to create a rich, complete wiki article, even if the information is not present in the chat log.\n{{/when}}",
"comment": "lightboard-namuwiki.lb.job",
"alwaysActive": false,
"secondkey": "",
"selective": false,
"insertorder": 100,
"mode": "normal",
"bookVersion": 2
}
],
"regex": [
{
"comment": "Filter Response",
"in": "<lightboard-namuwiki((?:[^<]|<(?!\\/lightboard-namuwiki>))+)<\\/lightboard-namuwiki>\\n?",
"out": "",
"type": "editoutput",
"ableFlag": false,
"flag": "gmsi"
},
{
"comment": "Ignore Old",
"in": "<lightboard-namuwiki\\s*([^>]+)?>((?:[^<]|<(?!\\/lightboard-namuwiki>))+)<\\/lightboard-namuwiki>\\n?",
"out": "{{#if {{? {{getglobalvar::toggle_lightboard-namuwiki.context}}=1}}}}\n{{#if {{greater_equal::{{chat_index}}::{{? {{lastmessageid}}-5}}}}}}\n$&\n{{/if}}\n{{/if}}",
"type": "editprocess",
"ableFlag": false,
"flag": "gmsi<order 1>"
},
{
"comment": "Lazy",
"in": "<lb-lazy id=\"lightboard-namuwiki\" />\\n?",
"out": "{{#if {{greater_equal::{{chat_index}}::{{? {{lastmessageid}}}}}}}}\n<div class=\"lb-module-root\" data-id=\"namuwiki-module\">\n<button class=\"lb-lazyloader\" risu-btn=\"lb-reroll__lightboard-namuwiki\">\n<span class=\"lb-opener\"><span>🔍나무위키 검색하기</span></span>\n</button>\n</div>\n{{/if}}",
"type": "editdisplay",
"ableFlag": false,
"flag": "g"
},
{
"comment": "에셋 찐빠 처리기 충돌 수정",
"in": "<img src=\"(.*?)\"(.*?)>",
"out": "<img $2src=\"$1\">",
"type": "editdisplay",
"ableFlag": true,
"flag": "g<order 999>"
}
],
"trigger": [
{
"comment": "",
"type": "start",
"conditions": [],
"effect": [
{
"type": "triggerlua",
"code": "--- Copyright (c) 2025 YourName\n--- Namuwiki Module (Table, Image, Hyperlink & Collapsible Fix)\n\nlocal triggerId = ''\n\nlocal function setTriggerId(tid)\n triggerId = tid\n if type(prelude) ~= \"nil\" then return end\n local source = getLoreBooks(triggerId, 'lightboard-prelude')\n if not source or #source == 0 then\n error('Failed to load lightboard-prelude.')\n end\n load(source[1].content, '@prelude', 't')()\nend\n\nlocal function findFirstTag(text, pos)\n local s_start, s_end = text:find(\"✂️\", pos, true)\n local n_start, n_end = text:find(\"📌\", pos, true)\n local b_start, b_end = text:find(\"❗\", pos, true)\n local g_start, g_end = text:find(\"👻\", pos, true)\n \n local link_start, link_end = text:find(\"➡\\239?\\184?\\143?\", pos)\n \n local br_start, br_end = text:find(\"<br%s*/?>\", pos)\n local html_img_start, html_img_end, html_img_src = text:find(\"<img[^>]*src=[\\\"']?([^%s>\\\"'<]*)[\\\"']?[^>]*>\", pos)\n local http_start, http_end, http_val = text:find(\"(https?://[^%s>\\\"';|<]+)\", pos)\n local legacy_start, legacy_end, legacy_val = text:find(\"%[Image:(.-)%]\", pos)\n \n local md_start, md_end, md_cap, md_url = text:find(\"!%[(.-)%]%(([^%s)]*)%)\", pos)\n\n local first_pos, first_end, first_type, extra, extra2 = nil, nil, nil, nil, nil\n\n local function chk(start_pos, end_pos, t_type, t_extra, t_extra2)\n if start_pos and (not first_pos or start_pos < first_pos) then\n first_pos, first_end, first_type, extra, extra2 = start_pos, end_pos, t_type, t_extra, t_extra2\n end\n end\n\n chk(s_start, s_end, \"strike\")\n chk(n_start, n_end, \"note\")\n chk(b_start, b_end, \"bold\")\n chk(g_start, g_end, \"spoiler\")\n chk(link_start, link_end, \"link\")\n chk(br_start, br_end, \"br\")\n chk(md_start, md_end, \"md_img\", md_url, md_cap)\n chk(html_img_start, html_img_end, \"html_img\", html_img_src)\n chk(http_start, http_end, \"http_img\", http_val)\n chk(legacy_start, legacy_end, \"legacy_img\", legacy_val)\n \n return first_pos, first_end, first_type, extra, extra2\nend\n\nlocal function findClosingTag(text, startPos, expected)\n if expected == \"link\" then\n local s1, e1 = text:find(\"➡\\239?\\184?\\143?\", startPos)\n local s2, e2 = text:find(\"⬅\\239?\\184?\\143?\", startPos)\n local fs, fe = nil, nil\n if s1 then fs, fe = s1, e1 end\n if s2 and (not fs or s2 < fs) then fs, fe = s2, e2 end\n if fs then return fs, fe end\n return #text + 1, #text\n end\n\n local s, e = text:find(expected, startPos, true)\n if s then return s, e end\n \n local s1, e1 = text:find(\"✂️\", startPos, true)\n local s2, e2 = text:find(\"📌\", startPos, true)\n local s3, e3 = text:find(\"❗\", startPos, true)\n local s4, e4 = text:find(\"👻\", startPos, true)\n local s5, e5 = text:find(\"➡\\239?\\184?\\143?\", startPos)\n \n local fs, fe = nil, nil\n if s1 then fs, fe = s1, e1 end\n if s2 and (not fs or s2 < fs) then fs, fe = s2, e2 end\n if s3 and (not fs or s3 < fs) then fs, fe = s3, e3 end\n if s4 and (not fs or s4 < fs) then fs, fe = s4, e4 end\n if s5 and (not fs or s5 < fs) then fs, fe = s5, e5 end\n \n if fs then return fs, fe end\n return #text + 1, #text\nend\n\nlocal function parseInlineFormatting(text, state, skipFootnotes)\n local elements = {}\n local lastPos = 1\n \n while true do\n local firstTagPos, firstTagEnd, firstTagType, extra, extra2 = findFirstTag(text, lastPos)\n \n if not firstTagPos then\n if lastPos <= #text then table.insert(elements, text:sub(lastPos)) end\n break\n else\n if firstTagPos > lastPos then \n local beforeText = text:sub(lastPos, firstTagPos - 1)\n if firstTagType == \"note\" and beforeText:match(\"%s$\") then\n beforeText = beforeText:gsub(\"%s+$\", \"\")\n end\n if beforeText ~= \"\" then\n table.insert(elements, beforeText)\n end\n end\n \n if firstTagType == \"link\" then\n local nextTag, nextTagEnd = findClosingTag(text, firstTagEnd + 1, \"link\")\n local innerContent = text:sub(firstTagEnd + 1, nextTag - 1)\n table.insert(elements, h.button['nw-inline-link']{ \n risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. innerContent,\n type = \"button\",\n innerContent \n })\n lastPos = nextTagEnd + 1\n\n elseif firstTagType == \"strike\" then\n local nextTag, nextTagEnd = findClosingTag(text, firstTagEnd + 1, \"✂️\")\n local innerContent = text:sub(firstTagEnd + 1, nextTag - 1)\n local innerElements = parseInlineFormatting(innerContent, state, skipFootnotes)\n table.insert(elements, h.del{ innerElements })\n lastPos = nextTagEnd + 1\n \n elseif firstTagType == \"spoiler\" then\n local nextTag, nextTagEnd = findClosingTag(text, firstTagEnd + 1, \"👻\")\n local innerContent = text:sub(firstTagEnd + 1, nextTag - 1)\n local innerElements = parseInlineFormatting(innerContent, state, skipFootnotes)\n table.insert(elements, h.details['nw-spoiler'] {\n h.summary['nw-spoiler-summary'] { \"\" },\n h.span['nw-spoiler-content'] { innerElements }\n })\n lastPos = nextTagEnd + 1\n\n elseif firstTagType == \"note\" then\n local nextTag, nextTagEnd = findClosingTag(text, firstTagEnd + 1, \"📌\")\n if skipFootnotes then\n lastPos = nextTagEnd + 1\n else\n state.footnote_counter = state.footnote_counter + 1\n local id = state.footnote_counter\n local innerContent = text:sub(firstTagEnd + 1, nextTag - 1)\n local innerElements = parseInlineFormatting(innerContent, state, skipFootnotes)\n table.insert(elements, h.span['nw-footnote'] { \n h.span['nw-footnote-link'] { \"[\" .. id .. \"]\" }, \n h.span['nw-footnote-content'] { innerElements } \n })\n lastPos = nextTagEnd + 1\n end\n \n elseif firstTagType == \"bold\" then\n local nextTag, nextTagEnd = findClosingTag(text, firstTagEnd + 1, \"❗\")\n local innerContent = text:sub(firstTagEnd + 1, nextTag - 1)\n local innerElements = parseInlineFormatting(innerContent, state, skipFootnotes)\n table.insert(elements, h.b{ innerElements })\n lastPos = nextTagEnd + 1\n\n elseif firstTagType == \"br\" then\n table.insert(elements, h.br{void=true})\n lastPos = firstTagEnd + 1\n\n elseif firstTagType == \"md_img\" then\n local img_src = extra and extra:match(\"^%s*(.-)%s*$\") or \"\"\n local caption = extra2 and extra2:match(\"^%s*(.-)%s*$\") or \"\"\n \n if img_src ~= \"\" then\n if caption ~= \"\" then\n local cap_elements = parseInlineFormatting(caption, state, skipFootnotes)\n table.insert(elements, h.span['nw-img-wrap'] {\n h.img { \n src = img_src,\n class = \"nw-inline-img\"\n },\n h.span['nw-img-caption'] { cap_elements }\n })\n else\n table.insert(elements, h.img { \n src = img_src,\n class = \"nw-inline-img\"\n })\n end\n end\n \n lastPos = firstTagEnd + 1\n \n local remainder = text:sub(lastPos)\n local consumed = 0\n while true do\n local matched = false\n local s1, e1 = remainder:find(\"^%s+\")\n if s1 then\n consumed = consumed + e1\n remainder = remainder:sub(e1 + 1)\n matched = true\n end\n local s2, e2 = remainder:find(\"^<br%s*/?>\")\n if s2 then\n consumed = consumed + e2\n remainder = remainder:sub(e2 + 1)\n matched = true\n end\n if not matched then break end\n end\n lastPos = lastPos + consumed\n\n elseif firstTagType == \"html_img\" or firstTagType == \"http_img\" or firstTagType == \"legacy_img\" then\n local img_src = extra and extra:match(\"^%s*(.-)%s*$\") or \"\"\n if img_src ~= \"\" then\n table.insert(elements, h.img { \n src = img_src,\n class = \"nw-inline-img\"\n })\n end\n lastPos = firstTagEnd + 1\n end\n end\n end\n return elements\nend\n\nlocal function processMainColor(hex_input)\n if not hex_input then return nil end\n local hex = hex_input:match(\"#?(%x+)\")\n if not hex or (#hex ~= 6) then hex = \"666666\" end\n local main_color = \"#\" .. hex\n local text_color = \"#fff\"\n local r = tonumber(hex:sub(1,2), 16) / 255\n local g = tonumber(hex:sub(3,4), 16) / 255\n local b = tonumber(hex:sub(5,6), 16) / 255\n local function srgb_to_linear(c)\n if c <= 0.03928 then return c / 12.92\n else return ((c + 0.055) / 1.055) ^ 2.4 end\n end\n local luminance = 0.2126 * srgb_to_linear(r) + 0.7152 * srgb_to_linear(g) + 0.0722 * srgb_to_linear(b)\n if luminance > 0.34 then text_color = \"#000\" end\n return { main = main_color, text = text_color, luminance = luminance }\nend\n\nlocal function render(block, isLast)\n local rawContent = block.attributes.content or block.content\n if not rawContent or rawContent == \"\" then return \"[Namuwiki Module Error: Empty Content]\" end\n rawContent = rawContent:gsub(\"([^%.])📌%.\", \"%1.📌\")\n rawContent = rawContent:gsub(\"%*%*\", \"❗\")\n \n local docTitle = block.attributes.doc_title or \"문서 제목 없음\"\n local color_data = processMainColor(block.attributes.main_color)\n local asset_src = block.attributes.asset_src\n local related1, related2, related3 = block.attributes.related1, block.attributes.related2, block.attributes.related3\n local recent1, recent2, recent3 = block.attributes.recent1, block.attributes.recent2, block.attributes.recent3\n \n local infobox_e, toc_e = nil, nil\n local content_es, headings = {}, {}\n local state = { footnote_counter = 0 }\n local blocks = {}\n local cleanContent = rawContent:match(\"^%s*(.-)%s*$\")\n \n if cleanContent and cleanContent ~= \"\" then\n local blockStarts = {}\n local validBlocks = { Heading=true, Paragraph=true, Quote=true, List=true, CategoryTable=true, Table=true, Infobox=true, Toc=true }\n local s = 1\n while true do\n local bs, be, bType = cleanContent:find(\"%[([%a]+)%]\", s)\n if not bs then break end\n if validBlocks[bType] then table.insert(blockStarts, bs) end\n s = bs + 1\n end\n if #blockStarts > 0 then\n for i = 1, #blockStarts do\n local startPos = blockStarts[i]\n local endPos = blockStarts[i+1] and (blockStarts[i+1] - 1) or #cleanContent\n table.insert(blocks, string.sub(cleanContent, startPos, endPos))\n end\n else\n table.insert(blocks, cleanContent)\n end\n end\n \n local l1_counter, l2_counter = 0, 0\n \n local grouped_content = {}\n local current_group = { heading = nil, collapsed = false, items = {} }\n table.insert(grouped_content, current_group)\n\n for _, contentBlock in ipairs(blocks) do\n local blockType = contentBlock:match(\"%[(%w+)%]\")\n local raw_text_content = contentBlock:match(\"%]%s*(.*)$\") or \"\"\n local trimmed_content = raw_text_content:match(\"^%s*(.-)%s*$\") or \"\"\n\n if blockType == \"Heading\" then\n local level = trimmed_content:match(\"Level:([%d]+)\") or \"1\"\n local title = trimmed_content:match(\"Title:(.-)|\") or trimmed_content:match(\"Title:(.*)$\") or \"제목 없음\"\n local collapsed = trimmed_content:match(\"Collapsed:(%a+)\") == \"true\"\n \n level = level:match(\"^%s*(.-)%s*$\")\n title = title:match(\"^%s*(.-)%s*$\")\n \n local number_str = \"\"\n if level == \"1\" then l1_counter, l2_counter = l1_counter + 1, 0; number_str = l1_counter .. \". \"\n elseif level == \"2\" then l2_counter = l2_counter + 1; number_str = l1_counter .. \".\" .. l2_counter .. \". \" end\n \n table.insert(headings, { Level = level, Title = title, Number = number_str })\n local title_elements = parseInlineFormatting(title, state)\n local number_span, title_span = h.span['nw-heading-number']{number_str}, h.span['nw-heading-title-text']{title_elements}\n local heading_el = h['h' .. level]['nw-heading nw-heading-' .. level] { number_span, title_span }\n \n current_group = { heading = heading_el, collapsed = collapsed, items = {} }\n table.insert(grouped_content, current_group)\n \n elseif blockType == \"Paragraph\" then\n if trimmed_content ~= \"\" then\n local parsed_elements = parseInlineFormatting(trimmed_content, state)\n table.insert(current_group.items, h.div['nw-paragraph']{parsed_elements})\n end\n \n elseif blockType == \"Quote\" then\n if trimmed_content ~= \"\" then\n local quote_text, source_text = trimmed_content, nil\n local source_pos = trimmed_content:find(\"|Source:\", 1, true)\n if source_pos then\n quote_text = trimmed_content:sub(1, source_pos - 1)\n source_text = trimmed_content:sub(source_pos + 8)\n end\n local quote_elements = parseInlineFormatting(quote_text:match(\"^%s*(.-)%s*$\") or \"\", state)\n local quote_children = { h.div['nw-quote-text'](quote_elements) }\n if source_text then\n local source_elements = parseInlineFormatting(source_text:match(\"^%s*(.-)%s*$\") or \"\", state)\n table.insert(quote_children, h.hr['nw-quote-separator']{void=true})\n table.insert(quote_children, h.div['nw-quote-source'](source_elements))\n end\n local quote_style = nil\n if color_data then quote_style = \"border-left-color: \" .. color_data.main .. \";\" end\n table.insert(current_group.items, h.div['nw-quote']{ style = quote_style, quote_children})\n end\n \n elseif blockType == \"List\" then\n if trimmed_content ~= \"\" then\n local parsed_elements = parseInlineFormatting(trimmed_content, state)\n table.insert(current_group.items, h.div['nw-list-item']{parsed_elements})\n end\n \n elseif blockType == \"CategoryTable\" then\n local caption, color = nil, nil\n local rows_data = {}\n local max_cols = 1\n local pairs = {}\n local current = \"\"\n local in_braces = 0\n for i = 1, #trimmed_content do\n local c = trimmed_content:sub(i, i)\n if c == \"{\" then in_braces = in_braces + 1 end\n if c == \"}\" then in_braces = in_braces - 1 end\n if c == \"|\" and in_braces == 0 then\n table.insert(pairs, current); current = \"\"\n else current = current .. c end\n end\n if current ~= \"\" then table.insert(pairs, current) end\n \n for _, p in ipairs(pairs) do\n local key_end = p:find(\":\", 1, true)\n if key_end then\n local key = p:sub(1, key_end - 1):match(\"^%s*(.-)%s*$\")\n local val = p:sub(key_end + 1):match(\"^%s*(.-)%s*$\")\n if key == \"Caption\" then caption = val\n elseif key == \"Color\" then color = val\n elseif key == \"Head\" or key == \"Row\" or key == \"RowHead\" then\n local is_head, is_row_head = (key == \"Head\"), (key == \"RowHead\")\n local cells = {}\n for cell in (val .. \";;\"):gmatch(\"(.-);;\") do\n if cell ~= \"\" then table.insert(cells, cell) end\n end\n table.insert(rows_data, { is_head = is_head, is_row_head = is_row_head, cells = cells })\n end\n end\n end\n \n local new_rows_data = {}\n local actual_max_cols = 1\n for _, r in ipairs(rows_data) do\n local cells = r.cells\n if r.is_head or r.is_row_head then\n table.insert(new_rows_data, r)\n if #cells > actual_max_cols then actual_max_cols = #cells end\n elseif #cells > 5 then\n for i = 1, #cells, 5 do\n local chunk = {}\n for j = i, math.min(i + 4, #cells) do table.insert(chunk, cells[j]) end\n table.insert(new_rows_data, { is_head = r.is_head, is_row_head = false, cells = chunk })\n if #chunk > actual_max_cols then actual_max_cols = #chunk end\n end\n else\n table.insert(new_rows_data, r)\n if #cells > actual_max_cols then actual_max_cols = #cells end\n end\n end\n rows_data = new_rows_data\n max_cols = actual_max_cols\n \n local base_color = nil\n if color and color ~= \"\" and color:lower() ~= \"none\" then base_color = processMainColor(color) end\n if not base_color then base_color = color_data end\n \n local header_style, table_style = \"\", \"\"\n if base_color then\n header_style = \"background-color: \" .. base_color.main .. \"; color: \" .. base_color.text .. \" !important;\"\n table_style = \"border: 2px solid \" .. base_color.main .. \"; border-top: none;\"\n end\n \n local table_rows = {}\n for _, r in ipairs(rows_data) do\n local row_items = {}\n for i, c in ipairs(r.cells) do\n local parsed = parseInlineFormatting(c, state)\n if r.is_head then\n table.insert(row_items, h.th { style = \"text-align: center; vertical-align: middle; \" .. header_style, parsed })\n elseif r.is_row_head and i == 1 then\n table.insert(row_items, h.th { style = \"text-align: center; vertical-align: middle; \" .. header_style, parsed })\n else\n table.insert(row_items, h.td { style = \"text-align: center; vertical-align: middle;\", parsed })\n end\n end\n while #row_items < max_cols do\n if r.is_head then table.insert(row_items, h.th{style=\"text-align: center; vertical-align: middle; \" .. header_style, \"\"})\n else table.insert(row_items, h.td{\"\"}) end\n end\n table.insert(table_rows, h.tr(row_items))\n end\n \n local parsed_caption = caption and parseInlineFormatting(caption, state) or \"분류\"\n table.insert(current_group.items, h.details {\n class = \"nw-category-details\",\n h.summary { class = \"nw-category-summary\", style = header_style, parsed_caption },\n h.div {\n class = \"nw-table-wrap nw-category-wrap\",\n style = \"margin: 0;\",\n h.table['nw-table nw-category-table'] {\n style = table_style .. \" margin: 0;\",\n h.tbody(table_rows)\n }\n }\n })\n\n elseif blockType == \"Table\" then\n local caption, color = nil, nil\n local rows_data = {}\n local max_cols = 1\n local pairs = {}\n local current = \"\"\n local in_braces = 0\n for i = 1, #trimmed_content do\n local c = trimmed_content:sub(i, i)\n if c == \"{\" then in_braces = in_braces + 1 end\n if c == \"}\" then in_braces = in_braces - 1 end\n if c == \"|\" and in_braces == 0 then table.insert(pairs, current); current = \"\"\n else current = current .. c end\n end\n if current ~= \"\" then table.insert(pairs, current) end\n \n for _, p in ipairs(pairs) do\n local key_end = p:find(\":\", 1, true)\n if key_end then\n local key = p:sub(1, key_end - 1):match(\"^%s*(.-)%s*$\")\n local val = p:sub(key_end + 1):match(\"^%s*(.-)%s*$\")\n if key == \"Caption\" then caption = val\n elseif key == \"Color\" then color = val\n elseif key == \"Head\" or key == \"Row\" or key == \"RowHead\" then\n local is_head, is_row_head = (key == \"Head\"), (key == \"RowHead\")\n local cells = {}\n for cell in (val .. \";;\"):gmatch(\"(.-);;\") do\n if cell ~= \"\" then table.insert(cells, cell) end\n end\n table.insert(rows_data, { is_head = is_head, is_row_head = is_row_head, cells = cells })\n end\n end\n end\n \n local actual_max_cols = 1\n for _, r in ipairs(rows_data) do\n if #r.cells > actual_max_cols then actual_max_cols = #r.cells end\n end\n max_cols = actual_max_cols\n \n local base_color = nil\n if color and color ~= \"\" and color:lower() ~= \"none\" then base_color = processMainColor(color) end\n if not base_color then base_color = color_data end\n \n local header_style = \"text-align: center;\"\n local table_style = \"\"\n if base_color then\n header_style = \"background-color: \" .. base_color.main .. \"; color: \" .. base_color.text .. \" !important; text-align: center;\"\n table_style = \"border: 2px solid \" .. base_color.main .. \";\"\n end\n \n local table_rows = {}\n if caption and caption ~= \"\" then\n local parsed_caption = parseInlineFormatting(caption, state)\n table.insert(table_rows, h.tr { h.th { colspan = tostring(max_cols), style = header_style, parsed_caption } })\n end\n \n for _, r in ipairs(rows_data) do\n local row_items = {}\n for i, c in ipairs(r.cells) do\n local parsed = parseInlineFormatting(c, state)\n if r.is_head then\n table.insert(row_items, h.th { style = header_style, parsed })\n elseif r.is_row_head and i == 1 then\n table.insert(row_items, h.th { style = header_style .. \" vertical-align: middle;\", parsed })\n else\n table.insert(row_items, h.td { style = \"text-align: center; vertical-align: middle;\", parsed })\n end\n end\n while #row_items < max_cols do\n if r.is_head then table.insert(row_items, h.th{style=header_style,\"\"})\n else table.insert(row_items, h.td{\"\"}) end\n end\n table.insert(table_rows, h.tr(row_items))\n end\n \n table.insert(current_group.items, h.div['nw-table-wrap'] {\n h.table['nw-table'] {\n style = table_style,\n h.tbody(table_rows)\n }\n })\n\n elseif blockType == \"Infobox\" then\n local header_style, key_cell_style, infobox_style = nil, nil, nil\n if color_data then\n header_style = \"background-color: \" .. color_data.main .. \"; color: \" .. color_data.text .. \" !important;\"\n infobox_style = \"border-color: \" .. color_data.main .. \";\"\n key_cell_style = \"background-color: \" .. color_data.main .. \"; color: \" .. color_data.text .. \" !important;\"\n end\n\n local infobox_items, infobox_title = {}, \"정보\"\n local pairs = {}\n local current = \"\"\n local in_braces = 0\n for i = 1, #trimmed_content do\n local c = trimmed_content:sub(i, i)\n if c == \"{\" then in_braces = in_braces + 1 end\n if c == \"}\" then in_braces = in_braces - 1 end\n if c == \"|\" and in_braces == 0 then table.insert(pairs, current); current = \"\"\n else current = current .. c end\n end\n if current ~= \"\" then table.insert(pairs, current) end\n \n for _, pair in ipairs(pairs) do\n local colonPos = pair:find(\":\", 1, true)\n if colonPos then\n local key = pair:sub(1, colonPos - 1):match(\"^%s*(.-)%s*$\")\n local value = pair:sub(colonPos + 1):match(\"^%s*(.-)%s*$\")\n if key == \"Title\" then infobox_title = value\n else\n local parsed_key = parseInlineFormatting(key, state)\n local parsed_value = parseInlineFormatting(value, state)\n table.insert(infobox_items, h.tr { \n h.td { style = key_cell_style, parsed_key }, h.td{ parsed_value }\n })\n end\n end\n end\n \n local asset_container = nil\n if asset_src and asset_src ~= \"\" then\n local src = asset_src:match(\"<img[^>]*src=[\\\"']?([^%s>\\\"'<]+)[\\\"']?[^>]*>\")\n if not src then src = asset_src:match(\"(https?://[^%s>\\\"';|<]+)\") end\n if not src then src = asset_src:match(\"%[Image:(.-)%]\") end\n if not src then src = asset_src end\n asset_container = h.div['nw-infobox-asset'] {\n h.img { style = \"width: 100%; height: auto; display: block;\", src = src:match(\"^%s*(.-)%s*$\") }\n }\n end\n \n infobox_e = h.div['nw-infobox'] { style = infobox_style,\n h.div['nw-infobox-header'] { style = header_style, infobox_title },\n asset_container,\n h.table['nw-infobox-table'] { infobox_items }\n }\n end\n end\n\n for _, group in ipairs(grouped_content) do\n if group.heading then\n table.insert(content_es, h.details['nw-heading-details'] {\n open = (not group.collapsed) or nil,\n h.summary['nw-heading-summary'] { group.heading },\n h.div['nw-heading-body'](group.items)\n })\n else\n for _, item in ipairs(group.items) do\n table.insert(content_es, item)\n end\n end\n end\n\n local toc_items = {}\n if #headings > 0 then\n for _, heading in ipairs(headings) do\n local class_name = \"nw-toc-item nw-toc-item-l\" .. heading.Level\n local title_elements = parseInlineFormatting(heading.Title, state, true)\n local number_span, title_span = h.span['nw-heading-number']{heading.Number or \"\"}, h.span['nw-toc-title-text']{title_elements}\n table.insert(toc_items, h.li[class_name]{ number_span, title_span })\n end\n end\n toc_e = h.div['nw-toc'] { h.p['nw-toc-title'] { \"목차\" }, h.ul['nw-toc-list'] { toc_items } }\n \n local recent_docs_e = nil\n local recent_buttons = {}\n if recent1 and recent1 ~= \"\" then\n table.insert(recent_buttons, h.button['nw-recent-btn']{ risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. recent1, type=\"button\", recent1 })\n end\n if recent2 and recent2 ~= \"\" then\n table.insert(recent_buttons, h.button['nw-recent-btn']{ risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. recent2, type=\"button\", recent2 })\n end\n if recent3 and recent3 ~= \"\" then\n table.insert(recent_buttons, h.button['nw-recent-btn']{ risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. recent3, type=\"button\", recent3 })\n end\n if #recent_buttons > 0 then\n recent_docs_e = h.div['nw-recent-docs'] { h.span['nw-recent-label'] {'관련 문서: '}, recent_buttons }\n end\n \n local related_docs_e = nil\n local related_buttons = {}\n if related1 and related1 ~= \"\" then\n table.insert(related_buttons, h.button['nw-related-btn']{ risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. related1, type=\"button\", related1 })\n end\n if related2 and related2 ~= \"\" then\n table.insert(related_buttons, h.button['nw-related-btn']{ risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. related2, type=\"button\", related2 })\n end\n if related3 and related3 ~= \"\" then\n table.insert(related_buttons, h.button['nw-related-btn']{ risu_btn = \"lb-interaction__lightboard-namuwiki__preserve;immediate#ChangeArticle/\" .. related3, type=\"button\", related3 })\n end\n if #related_buttons > 0 then\n related_docs_e = h.div['nw-related-docs'] { h.span['nw-related-label'] {'상세 문서: '}, related_buttons }\n end\n\n local root_style = nil\n if color_data then root_style = \"--main-color: \" .. color_data.main .. \";\" end\n\n local html = h.div {\n data_id = 'lightboard-namuwiki',\n style = root_style,\n h.details['nw-root'] {\n open = isLast or nil,\n h.summary['nw-header'] {\n h.div['nw-title'] { docTitle }\n },\n h.div['nw-body'] {\n h.div['nw-top-container'] {\n h.div['nw-toc-container'] { toc_e },\n h.div['nw-infobox-container'] { infobox_e }\n },\n h.div['nw-main-content'] { content_es }\n },\n h.div['nw-bottom-bar'] {\n h.div['nw-bottom-top'] {\n recent_docs_e,\n related_docs_e\n },\n h.div['nw-bottom-bottom'] {\n h.button['nw-search-btn'] {\n risu_btn = \"lb-interaction__lightboard-namuwiki__preserve#ChangeArticle\",\n type = \"button\",\n \"🔍 다른 문서 검색\"\n },\n h.button['nw-reroll'] {\n risu_btn = 'lb-reroll__lightboard-namuwiki',\n type = 'button',\n h.span['nw-reroll-icon'] {'↻'},\n h.span['nw-reroll-text'] {'새로고침'}\n }\n }\n }\n }\n }\n\n return tostring(html)\nend\n\nlocal function main(data)\n if not data or data == \"\" then return \"\" end\n local output, lastIndex = \"\", 1\n local extractionResult = prelude.queryNodes('lightboard-namuwiki', data)\n if extractionResult and #extractionResult > 0 then\n local totalCount = #extractionResult\n for i, match in ipairs(extractionResult) do\n if match.rangeStart > lastIndex then output = output .. data:sub(lastIndex, match.rangeStart - 1) end\n local isLast = (i == totalCount)\n local success, result = pcall(render, match, isLast)\n if success then output = output .. result\n else\n print(\"[Namuwiki Module] Parsing failed:\", tostring(result))\n output = output .. \"\\n\\n\"\n end\n lastIndex = match.rangeEnd + 1\n end\n else lastIndex = 1 end\n if lastIndex <= #data then output = output .. data:sub(lastIndex) end\n return output\nend\n\nlistenEdit( \"editDisplay\", function(tid, data)\n setTriggerId(tid)\n local success, result = pcall(main, data)\n if success then return result\n else\n print(\"[Namuwiki Module] Display failed:\", tostring(result))\n return data\n end\nend)"
}
],
"lowLevelAccess": true,
"source": "🔦라이트보드 미니보드 2.4"
}
],
"lowLevelAccess": true,
"hideIcon": false,
"backgroundEmbedding": "<style>\n@import url(\"https://cdn.jsdelivr.net/gh/orioncactus/pretendard@v1.3.9/dist/web/variable/pretendardvariable-dynamic-subset.min.css\");\n\n/* Spoiler */\n[data-id='lightboard-namuwiki'] .nw-spoiler { display: inline; }\n[data-id='lightboard-namuwiki'] .nw-spoiler-summary { display: inline; cursor: pointer; color: var(--nw-link) !important; font-weight: bold; font-size: 0.9em; list-style: none; user-select: none; }\n[data-id='lightboard-namuwiki'] .nw-spoiler-summary::-webkit-details-marker { display: none; }\n[data-id='lightboard-namuwiki'] .nw-spoiler-summary::before { content: '[스포일러 펼치기]'; }\n[data-id='lightboard-namuwiki'] .nw-spoiler[open] .nw-spoiler-summary::before { content: '[스포일러 접기]'; }\n[data-id='lightboard-namuwiki'] .nw-spoiler-content { display: inline; margin-left: 5px; }\n\n/* Heading Collapsible */\n[data-id='lightboard-namuwiki'] .nw-heading-details { margin-bottom: 0px; }\n[data-id='lightboard-namuwiki'] .nw-heading-summary { cursor: pointer; list-style: none; user-select: none; }\n[data-id='lightboard-namuwiki'] .nw-heading-summary::-webkit-details-marker { display: none; }\n[data-id='lightboard-namuwiki'] .nw-heading-details:not([open]) .nw-heading-summary .nw-heading { color: var(--nw-strikethrough-text) !important; border-bottom: 1px dashed var(--nw-heading-underline); }\n[data-id='lightboard-namuwiki'] .nw-heading-details:not([open]) .nw-heading-summary .nw-heading * { color: var(--nw-strikethrough-text) !important; }\n\n[data-id='lightboard-namuwiki']{container-type:inline-size;--darkness:{{getglobalvar::toggle_lightboard-namuwiki.darkness}};--show-footnote:{{getglobalvar::toggle_lightboard-namuwiki.show_footnote}};--show-asset:{{getglobalvar::toggle_lightboard-namuwiki.show_asset}};--nw-font:\"Pretendard Variable\",sans-serif}\n\n@container style(--darkness:0){[data-id='lightboard-namuwiki']>*{--nw-bg:#fff;--nw-border:#dbdbdb;--nw-text:#000;--nw-link:#007bff;--nw-strikethrough-text:#888;--nw-title-underline:#80c5ff;--nw-heading-underline:#a2a9b1;--nw-infobox-bg:#f9f9f9;--nw-infobox-key-bg:#f2f2f2;--nw-infobox-header-bg:#e9ecef;--nw-toc-bg:#f8f9fa;--nw-toc-border:#DDE3E8FF;--nw-footnote-bg:#333;--nw-footnote-text:#fff}}\n\n@container style(--darkness:1){[data-id='lightboard-namuwiki']>*{--nw-bg:#222;--nw-border:#4a4a4a;--nw-text:#e0e0e0;--nw-link:#FFA500;--nw-strikethrough-text:#888;--nw-title-underline:#FFA500;--nw-heading-underline:#555;--nw-infobox-bg:#2c2c2c;--nw-infobox-key-bg:#3a3a3a;--nw-infobox-header-bg:#3a3a3a;--nw-toc-bg:#2c2c2c;--nw-toc-border:#4a4a4a;--nw-footnote-bg:#e0e0e0;--nw-footnote-text:#121212}}\n\n@container style(--show-footnote:1){[data-id='lightboard-namuwiki'] .nw-footnote .nw-footnote-link{display:none!important}[data-id='lightboard-namuwiki'] .nw-footnote .nw-footnote-content{visibility:visible!important;position:static!important;display:inline!important;background-color:transparent!important;color:#888!important;padding:0!important;max-width:none!important;transform:none!important;font-size:inherit!important;vertical-align:baseline!important;border-radius:0!important;width:auto!important;line-height:inherit!important;font-weight:inherit!important;z-index:auto!important;bottom:auto!important;left:auto!important;font-style:italic!important;text-decoration:line-through!important}[data-id='lightboard-namuwiki'] .nw-footnote .nw-footnote-content::before{content:'('!important}[data-id='lightboard-namuwiki'] .nw-footnote .nw-footnote-content::after{content:')'!important;border:none!important;position:static!important;margin:0!important}[data-id='lightboard-namuwiki'] .nw-footnote{vertical-align:baseline!important;font-size:inherit!important}[data-id='lightboard-namuwiki'] .nw-toc{display:none!important}}\n\n@container style(--show-asset:0){[data-id='lightboard-namuwiki'] .nw-infobox-asset,[data-id='lightboard-namuwiki'] .nw-inline-img,[data-id='lightboard-namuwiki'] .nw-img-wrap{display:none!important}}\n\n[data-id='lightboard-namuwiki'],[data-id='lightboard-namuwiki'] *{color:var(--nw-text)!important;font-family:var(--nw-font)!important}\n\n[data-id='lightboard-namuwiki'] .nw-footnote-link,[data-id='lightboard-namuwiki'] .nw-heading-number,[data-id='lightboard-namuwiki'] .nw-related-btn,[data-id='lightboard-namuwiki'] .nw-recent-btn,[data-id='lightboard-namuwiki'] .nw-reroll-icon{color:var(--nw-link)!important}\n\n.nw-root{position:relative;background-color:var(--nw-bg);border:1px solid var(--nw-border);font-family:var(--nw-font);box-sizing:border-box}\n.nw-header{padding:16px 20px 10px;border-bottom:1px solid var(--nw-border);cursor:pointer;list-style:none}\n.nw-header::-webkit-details-marker{display:none}\n.nw-root:not([open])>.nw-header{border-bottom:none}\n.nw-title{font-size:26px;font-weight:700;margin:0 0 10px 0;padding-bottom:5px;border-bottom:3px solid var(--nw-title-underline);user-select:none;display:flex;justify-content:space-between;align-items:center}\n.nw-title::after{content:'▲';font-size:16px;color:var(--nw-heading-underline);transition:transform .2s ease-in-out;margin-left:10px}\n.nw-root:not([open])>.nw-header>.nw-title::after{transform:rotate(180deg)}\n.nw-body{padding:15px}\n.nw-top-container{display:flex;flex-direction:column;margin-bottom:25px}\n.nw-toc-container{flex:1 1 auto}\n.nw-infobox-container{flex:0 0 auto}\n.nw-main-content{width:100%;line-height:1.7}\n.nw-infobox{background-color:var(--nw-infobox-bg);border:1px solid var(--main-color,var(--nw-border));max-width:340px;width:100%;font-size:16px;margin:0 auto;padding:0;box-sizing:border-box}\n[data-id='lightboard-namuwiki'] .nw-infobox-header{background-color:var(--main-color,var(--nw-infobox-header-bg));color:#fff!important;padding:10px 12px;font-weight:bold;text-align:center;border-bottom:1px solid var(--nw-border)}\n.nw-infobox-asset{padding:0!important;margin:0!important;border:none!important;line-height:0!important}\n.nw-infobox-asset img{max-width:100%;height:auto;display:block;margin:0!important;padding:0!important;vertical-align:top}\n.nw-infobox-table{width:100%;border-collapse:collapse;border-spacing:0;margin:0;display:table}\n.nw-infobox-table td{padding:8px 12px;border-top:1px solid var(--nw-border);text-align:left}\n[data-id='lightboard-namuwiki'] .nw-infobox-table tr td:first-child{background-color:var(--main-color,var(--nw-infobox-key-bg));color:#fff!important;font-weight:bold;width:110px;text-align:center;vertical-align:middle}\n.nw-toc{background-color:var(--nw-toc-bg);border:1px solid var(--nw-toc-border);padding:15px;margin:0 auto 15px auto;width:fit-content;max-width:100%}\n.nw-toc-title{font-weight:bold;margin:0 0 10px 0;font-size:16px}\n.nw-toc-list{list-style-type:none;padding-left:0;margin:0}\n.nw-toc-item{padding:0;line-height:1.3}\n.nw-toc-item-l1{font-size:15px}\n.nw-toc-item-l2{padding-left:20px!important;font-size:14px}\n.nw-quote{font-style:italic;background-color:var(--nw-toc-bg);padding:15px;border-left:5px solid var(--main-color,var(--nw-link));margin:20px 0;width:fit-content;max-width:100%}\n.nw-quote+.nw-quote{margin-top:15px}\n.nw-quote-text{margin:0;padding:0;font-weight:bold}\n.nw-quote-source{margin:0;padding:0}\n.nw-quote-separator{border:none;border-top:1px solid var(--nw-heading-underline);width:100%;margin:10px 0}\n.nw-quote-source{text-align:left;font-size:.9em;font-style:normal}\n.nw-quote .nw-inline-link{font-style:italic}\n.nw-list-item{position:relative;margin:0 0 5px 0;padding-left:.8em;font-size:15px;font-weight:400;line-height:1.7}\n.nw-list-item::before{content:'•';position:absolute;left:0;top:.07em;font-size:1.3em;line-height:1}\n.nw-heading-number{font-weight:700;margin-right:5px}\n.nw-heading{margin:30px 0 15px 0;padding-bottom:3px;border-bottom:1px solid var(--nw-heading-underline);font-weight:700;display:flex;align-items:center}\n.nw-heading-1{font-size:26px}\n.nw-heading-2{font-size:23px}\n.nw-paragraph{font-size:15px;margin:0 0 15px 0;white-space:pre-wrap;font-weight:400}\n.nw-root del{color:var(--nw-strikethrough-text)!important;text-decoration:line-through}\n.nw-root b,.nw-root strong{font-weight:700!important}\n.nw-footnote{position:relative;display:inline;vertical-align:super;font-size:.8em;line-height:1}\n.nw-footnote-link{cursor:pointer}\n.nw-footnote .nw-footnote-content{visibility:hidden;background-color:var(--nw-footnote-bg);color:var(--nw-footnote-text)!important;text-align:left;border-radius:4px;padding:10px;position:absolute;z-index:1;bottom:150%;left:50%;transform:translateX(-50%);width:max-content;max-width:250px;font-size:13px;line-height:1.5;vertical-align:initial;font-weight:400}\n.nw-footnote .nw-footnote-content::after{content:\"\";position:absolute;top:100%;left:50%;margin-left:-5px;border-width:5px;border-style:solid;border-color:var(--nw-footnote-bg) transparent transparent transparent}\n.nw-footnote:hover .nw-footnote-content{visibility:visible;opacity:1}\n.nw-inline-link{background:none;border:none;padding:0;margin:0;color:var(--nw-link)!important;text-decoration:none;cursor:pointer;font-size:inherit;font-weight:inherit;line-height:inherit;display:inline;font-family:inherit}\n.nw-inline-link:hover{text-decoration:underline}\n.nw-bottom-bar{width:100%;padding:10px 15px;box-sizing:border-box;display:flex;flex-direction:column;gap:10px;margin-top:20px;border-top:1px dashed var(--nw-border)}\n.nw-bottom-top{display:flex;flex-direction:column;gap:10px;width:100%}\n.nw-bottom-bottom{display:flex;align-items:center;width:100%}\n.nw-search-btn{background-color:var(--nw-bg);border:2px solid var(--nw-heading-underline);border-radius:4px;padding:5px 8px;font-size:14px;font-weight:600;cursor:pointer;text-align:left;width:auto}\n.nw-recent-docs{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding-left:2px}\n.nw-related-docs{display:flex;align-items:center;flex-wrap:wrap;gap:8px;padding-left:2px}\n.nw-recent-label{font-weight:bold;font-size:15px}\n.nw-related-label{font-weight:bold;font-size:15px}\n.nw-related-btn,.nw-recent-btn{background-color:var(--nw-infobox-key-bg);border:1px solid var(--nw-border);border-radius:4px;padding:2px 5px;font-size:13px;font-weight:700;cursor:pointer;text-decoration:none;transition:background-color .2s}\n.nw-related-btn:hover,.nw-recent-btn:hover{background-color:var(--nw-infobox-header-bg)}\n.nw-reroll{display:flex;align-items:center;gap:6px;background-color:var(--nw-bg);border:1px solid var(--nw-border);border-radius:4px;padding:6px 10px;cursor:pointer;transition:background-color .2s;margin-left:auto}\n.nw-reroll:hover{background-color:var(--nw-infobox-key-bg)}\n.nw-reroll-icon{font-size:15px}\n.nw-reroll-text{font-size:13px;color:var(--nw-text)!important}\n.nw-table-wrap{width:100%;overflow-x:auto;margin:6px 0}\n.nw-table{width:100%;border-collapse:collapse;font-size:15px;line-height:1.5;background-color:var(--nw-bg)}\n.nw-table caption{font-weight:700;padding:5px;text-align:left;font-size:16px;margin-bottom:0px;color:var(--nw-text)}\n.nw-table th,.nw-table td{border:1px solid var(--nw-border);padding:4px 6px;text-align:left;vertical-align:middle;color:var(--nw-text)}\n.nw-table th{background-color:var(--nw-infobox-key-bg);font-weight:700;text-align:center}\n[data-id='lightboard-namuwiki'] th .nw-inline-link{color:inherit!important;text-decoration:underline!important}\n\n/* Category Table Collapsible Styles */\n.nw-category-details{margin-bottom:15px;border-radius:4px;overflow:hidden}\n.nw-category-summary{padding:8px;font-weight:bold;text-align:center;cursor:pointer;list-style:none;user-select:none}\n.nw-category-summary::-webkit-details-marker{display:none}\n.nw-category-summary::before{content:'▼';display:inline-block;margin-right:8px;transition:transform .2s;font-size:12px;transform:rotate(-90deg)}\n.nw-category-details[open] .nw-category-summary::before{transform:rotate(0deg)}\n.nw-category-details .nw-table-wrap{margin:0}\n.nw-category-table{border-top:none!important}\n\n/* Image Styles */\n.nw-inline-img{max-width:100%;height:auto;display:block;margin:0 auto}\n.nw-table .nw-inline-img{width:120px;height:120px;object-fit:cover;object-position:top;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,0.1);margin-bottom:2px}\n.nw-paragraph .nw-inline-img,.nw-list-item .nw-inline-img,.nw-quote .nw-inline-img{width:300px;height:300px;object-fit:cover;object-position:top;border-radius:4px;box-shadow:0 1px 3px rgba(0,0,0,0.1);display:block;margin:10px 0}\n.nw-img-wrap{display:inline-flex;flex-direction:column;align-items:center;width:fit-content;max-width:100%;margin:2px}\n.nw-paragraph .nw-img-wrap,.nw-list-item .nw-img-wrap,.nw-quote .nw-img-wrap{display:flex;margin:10px 0}\n.nw-paragraph .nw-img-wrap .nw-inline-img,.nw-list-item .nw-img-wrap .nw-inline-img,.nw-quote .nw-img-wrap .nw-inline-img{margin:0}\n.nw-img-caption{font-size:13px;margin-top:6px;text-align:center;color:var(--nw-text);opacity:0.7;word-wrap:break-word;word-break:keep-all;width:100%}\n.nw-img-caption::before{content:\"(\"}\n.nw-img-caption::after{content:\")\"}\n.nw-paragraph .nw-img-caption,.nw-list-item .nw-img-caption,.nw-quote .nw-img-caption{max-width:300px}\n.nw-table .nw-img-caption{max-width:180px}\n.nw-category-wrap{margin-bottom:6px}\n\n@media(min-width:768px){\n .nw-top-container{flex-direction:row;align-items:flex-start;gap:20px}\n .nw-infobox{margin:0}\n .nw-toc{margin:0;width:auto}\n .nw-toc-container{order:1;flex:0 1 auto}\n .nw-infobox-container{order:2;flex:1 1 auto;display:flex;justify-content:center}\n /* Adjusted Table Image Size on PC */\n .nw-table .nw-inline-img {\n width: 120px;\n height: 120px;\n }\n .nw-category-table .nw-inline-img {\n width: 180px;\n height: 180px;\n }\n}\n</style>",
"assets": [],
"customModuleToggle": "=🔦나무위키=group\nlightboard-namuwiki.mode=모드=select=끄기,메인,보조,자동\nlightboard-namuwiki.context=컨텍=select=제거,포함\nlightboard-namuwiki.maxLogs=포함채팅수=text\nlightboard-namuwiki.maxCtx=최대컨텍=text\n=포함채팅수, 최대컨텍을 덮어씀. 비우면 백엔드 설정=caption\nlightboard-namuwiki.perspective=관점=select=세계관 내부,현실의 위키\nlightboard-namuwiki.meta_info=메타 정보=textarea\n=현실의 위키일 경우 캐릭터가 등장하는 작품의 종류, 장르, 작가 등등등을 지정할 수 있음=caption\nlightboard-namuwiki.creativity=창의성=select=엄격하게 (내역만),적당히 추론,적극적 창작\n=현실의 위키일 경우 얼마나 자유롭게 작품 내용을 창작할지 정도를 정할 수 있음=caption\nlightboard-namuwiki.spoiler=스포일러=select=기본,접기\nlightboard-namuwiki.darkness=밝기=select=☀️라이트,🌙다크\nlightboard-namuwiki.length=분량=select=보통,적게,많이,더많이\nlightboard-namuwiki.search=검색어=text\nlightboard-namuwiki.direction=서술방식=text\nlightboard-namuwiki.lazy=발동=select=즉시,누르면\nlightboard-namuwiki.show_footnote=주석 표시=select=기본,펼치기\nlightboard-namuwiki.show_asset=에셋 표시=select=끄기,켜기\n==groupEnd",
"id": "8076e489-0a95-41b5-ba10-9fc09476e91f",
"icon": "assets/b949bb4af9b39db09a0d3b3c0b6f67e62c5d55c72381ce474af19b205dc87b8e.png",
"namespace": "namuwiki-kaizo-module"
}