fenced 블록 탐색 helper 통합
This commit is contained in:
@@ -48,7 +48,7 @@
|
||||
| lib/markdown-iframe-embed.js | 게시물 본문 iframe 블록의 코드 판별과 안전 속성 추출 |
|
||||
| lib/markdown-html-block.js | 게시물 본문 HTML 블록의 parser 기반 허용 태그·속성 sanitizer, 실행 URL·인라인 style 제거와 새 창 링크 rel 보정 |
|
||||
| lib/markdown-callout.js | 인용 막대 색상·콜아웃 배경색 옵션, 선언 줄 파싱·직렬화 |
|
||||
| lib/markdown-fenced-meta.js | 공개 Markdown fenced 블록 본문 수집과 북마크·회원가입·미디어 메타 파싱 |
|
||||
| lib/markdown-fenced-meta.js | Markdown fenced 블록 시작·종료 줄 탐색, 본문 수집, 북마크·회원가입·미디어 메타 파싱 |
|
||||
| lib/markdown-quote.js | 공개 Markdown 인용 줄 판별·옵션 파싱·라이브 편집 줄 변환 |
|
||||
| lib/brand-color.js | 사이트 브랜드 컬러 기본값·hex 검증·정규화 |
|
||||
| lib/markdown-image.js | 이미지 마크다운 직렬화·파싱, 단독 이미지 URL 판별 |
|
||||
@@ -110,7 +110,7 @@
|
||||
| tests/markdown-html-block.test.js | HTML sanitizer 단위 회귀 테스트 |
|
||||
| tests/content-in-article-ad.test.js | 공개 본문 인아티클 광고 삽입 위치 계산 단위 회귀 테스트 |
|
||||
| tests/markdown-block-context.test.js | 관리자 블록 설정 패널의 활성 블록 컨텍스트 단위 회귀 테스트 |
|
||||
| tests/markdown-fenced-meta.test.js | Markdown fenced 블록 본문 수집과 메타 파싱 단위 회귀 테스트 |
|
||||
| tests/markdown-fenced-meta.test.js | Markdown fenced 블록 시작·종료 줄 탐색, 본문 수집, 메타 파싱 단위 회귀 테스트 |
|
||||
| tests/markdown-quote.test.js | Markdown 인용 옵션 파싱과 편집 줄 변환 단위 회귀 테스트 |
|
||||
| tests/multipart-file-upload.test.js | multipart 스트리밍·제한 단위 회귀 테스트 |
|
||||
| tests/csp-report.test.js | CSP URL 최소화·payload 형식 단위 회귀 테스트 |
|
||||
|
||||
@@ -1,5 +1,11 @@
|
||||
# 업데이트 이력
|
||||
|
||||
## v1.11.53
|
||||
|
||||
- 관리자 블록 컨텍스트의 fenced 블록 시작·종료 줄 탐색 helper를 `lib/markdown-fenced-meta.js`로 통합.
|
||||
- fenced 블록 시작·종료 탐색과 닫힘 표식 경계 단위 테스트를 추가.
|
||||
- `markdown-block-context`는 활성 블록 종류별 컨텍스트 조립에 집중하도록 정리.
|
||||
|
||||
## v1.11.52
|
||||
|
||||
- 관리자 블록 컨텍스트의 인용 줄 판별·옵션 파싱 중복을 `lib/markdown-quote.js` 공통 helper로 통합.
|
||||
|
||||
@@ -3,64 +3,7 @@ import { CALLOUT_BACKGROUND_OPTIONS, parseCalloutOptions } from './markdown-call
|
||||
import { parseCodeFenceLine } from './markdown-code-block.js'
|
||||
import { parseToggleOpenerLine } from './markdown-toggle.js'
|
||||
import { getQuoteLineBody, isQuoteMarkerLine, parseQuoteOptions } from './markdown-quote.js'
|
||||
|
||||
/**
|
||||
* fenced 블록 시작 줄 인덱스를 찾는다.
|
||||
* @param {string[]} lines - 본문 줄 목록
|
||||
* @param {number} currentLine - 현재 줄
|
||||
* @param {string} opener - 시작 토큰
|
||||
* @returns {number} 시작 줄 또는 -1
|
||||
*/
|
||||
const findFencedBlockStart = (lines, currentLine, opener) => {
|
||||
for (let index = currentLine; index >= 0; index -= 1) {
|
||||
if ((lines[index] || '').trim() === opener) {
|
||||
return index
|
||||
}
|
||||
|
||||
if ((lines[index] || '').trim() === ':::') {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 조건에 맞는 fenced 블록 시작 줄 인덱스를 찾는다.
|
||||
* @param {string[]} lines - 본문 줄 목록
|
||||
* @param {number} currentLine - 현재 줄
|
||||
* @param {(line: string) => boolean} predicate - 시작 줄 판별 함수
|
||||
* @returns {number} 시작 줄 또는 -1
|
||||
*/
|
||||
const findFencedBlockStartBy = (lines, currentLine, predicate) => {
|
||||
for (let index = currentLine; index >= 0; index -= 1) {
|
||||
if (predicate((lines[index] || '').trim())) {
|
||||
return index
|
||||
}
|
||||
|
||||
if ((lines[index] || '').trim() === ':::') {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* fenced 블록 종료 줄 인덱스를 찾는다.
|
||||
* @param {string[]} lines - 본문 줄 목록
|
||||
* @param {number} startLine - 시작 줄
|
||||
* @returns {number} 종료 줄 또는 -1
|
||||
*/
|
||||
const findFencedBlockEnd = (lines, startLine) => {
|
||||
for (let index = startLine + 1; index < lines.length; index += 1) {
|
||||
if ((lines[index] || '').trim() === ':::') {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
import { findFencedBlockEnd, findFencedBlockStart, findFencedBlockStartBy } from './markdown-fenced-meta.js'
|
||||
|
||||
/**
|
||||
* 단독 URL 줄인지 확인한다.
|
||||
|
||||
@@ -1,3 +1,61 @@
|
||||
/**
|
||||
* fenced 블록 시작 줄 인덱스를 찾는다.
|
||||
* @param {string[]} lines - 본문 줄 목록
|
||||
* @param {number} currentLine - 현재 줄
|
||||
* @param {string} opener - 시작 토큰
|
||||
* @returns {number} 시작 줄 또는 -1
|
||||
*/
|
||||
export const findFencedBlockStart = (lines, currentLine, opener) => {
|
||||
for (let index = currentLine; index >= 0; index -= 1) {
|
||||
if ((lines[index] || '').trim() === opener) {
|
||||
return index
|
||||
}
|
||||
|
||||
if ((lines[index] || '').trim() === ':::') {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 조건에 맞는 fenced 블록 시작 줄 인덱스를 찾는다.
|
||||
* @param {string[]} lines - 본문 줄 목록
|
||||
* @param {number} currentLine - 현재 줄
|
||||
* @param {(line: string) => boolean} predicate - 시작 줄 판별 함수
|
||||
* @returns {number} 시작 줄 또는 -1
|
||||
*/
|
||||
export const findFencedBlockStartBy = (lines, currentLine, predicate) => {
|
||||
for (let index = currentLine; index >= 0; index -= 1) {
|
||||
if (predicate((lines[index] || '').trim())) {
|
||||
return index
|
||||
}
|
||||
|
||||
if ((lines[index] || '').trim() === ':::') {
|
||||
break
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* fenced 블록 종료 줄 인덱스를 찾는다.
|
||||
* @param {string[]} lines - 본문 줄 목록
|
||||
* @param {number} startLine - 시작 줄
|
||||
* @returns {number} 종료 줄 또는 -1
|
||||
*/
|
||||
export const findFencedBlockEnd = (lines, startLine) => {
|
||||
for (let index = startLine + 1; index < lines.length; index += 1) {
|
||||
if ((lines[index] || '').trim() === ':::') {
|
||||
return index
|
||||
}
|
||||
}
|
||||
|
||||
return -1
|
||||
}
|
||||
|
||||
/**
|
||||
* 닫힘 표식까지의 행 목록을 반환한다.
|
||||
* @param {Array<string>} lines - 전체 마크다운 행
|
||||
|
||||
4
package-lock.json
generated
4
package-lock.json
generated
@@ -1,12 +1,12 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.52",
|
||||
"version": "1.11.53",
|
||||
"lockfileVersion": 3,
|
||||
"requires": true,
|
||||
"packages": {
|
||||
"": {
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.52",
|
||||
"version": "1.11.53",
|
||||
"hasInstallScript": true,
|
||||
"dependencies": {
|
||||
"@nuxtjs/tailwindcss": "^6.14.0",
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "sori.studio",
|
||||
"version": "1.11.52",
|
||||
"version": "1.11.53",
|
||||
"private": true,
|
||||
"type": "module",
|
||||
"imports": {
|
||||
|
||||
@@ -2,11 +2,48 @@ import assert from 'node:assert/strict'
|
||||
import test from 'node:test'
|
||||
import {
|
||||
collectFencedLines,
|
||||
findFencedBlockEnd,
|
||||
findFencedBlockStart,
|
||||
findFencedBlockStartBy,
|
||||
parseBookmarkMeta,
|
||||
parseMediaMeta,
|
||||
parseSignupMeta
|
||||
} from '../lib/markdown-fenced-meta.js'
|
||||
|
||||
test('fenced 블록 시작과 종료 줄을 찾는다', () => {
|
||||
const lines = [
|
||||
'이전',
|
||||
':::gallery',
|
||||
'',
|
||||
':::',
|
||||
'다음'
|
||||
]
|
||||
|
||||
assert.equal(findFencedBlockStart(lines, 2, ':::gallery'), 1)
|
||||
assert.equal(findFencedBlockEnd(lines, 1), 3)
|
||||
})
|
||||
|
||||
test('닫힘 표식 너머의 fenced 블록 시작은 현재 블록으로 보지 않는다', () => {
|
||||
const lines = [
|
||||
':::gallery',
|
||||
'',
|
||||
':::',
|
||||
'본문'
|
||||
]
|
||||
|
||||
assert.equal(findFencedBlockStart(lines, 3, ':::gallery'), -1)
|
||||
})
|
||||
|
||||
test('조건 기반 fenced 블록 시작 줄을 찾는다', () => {
|
||||
const lines = [
|
||||
':::callout emoji=none bg=blue',
|
||||
'본문',
|
||||
':::'
|
||||
]
|
||||
|
||||
assert.equal(findFencedBlockStartBy(lines, 1, (line) => line.startsWith(':::callout')), 0)
|
||||
})
|
||||
|
||||
test('fenced 블록 닫힘 표식까지의 본문과 다음 줄을 수집한다', () => {
|
||||
assert.deepEqual(collectFencedLines([
|
||||
':::bookmark',
|
||||
|
||||
Reference in New Issue
Block a user