Skip to content

Commit

Permalink
feat: Support highlight syntax (#31)
Browse files Browse the repository at this point in the history
* support callout

* fix eslint

* support hightlight syntax

* fix eslint
  • Loading branch information
obgnail authored and harttle committed Jan 25, 2024
1 parent c8141f8 commit 66af404
Show file tree
Hide file tree
Showing 5 changed files with 101 additions and 2 deletions.
13 changes: 13 additions & 0 deletions src/nodes/highlight.ts
@@ -0,0 +1,13 @@
import { NodeKind } from './node-kind'
import { Node } from './node'
import { Delimited } from './delimited'

export class Highlight extends Delimited implements Node {
readonly children: Node[] = []
readonly kind = NodeKind.Highlight

constructor (children: Node[]) {
super('==', '==')
this.children = children
}
}
3 changes: 2 additions & 1 deletion src/nodes/node-kind.ts
Expand Up @@ -24,6 +24,7 @@ export const enum NodeKind {
Math = 1 << 21,
BlockquoteItem = 1 << 22,
CalloutItem = 1 << 23,
Highlight = 1 << 24,

// combinations
All = -1,
Expand All @@ -33,7 +34,7 @@ export const enum NodeKind {
Code = InlineCode | BlockCode,
Link = InlineLink | ReferenceLink,
Image = InlineImage | ReferenceImage,
Style = Strong | Emphasis | Strikethrough,
Style = Strong | Emphasis | Strikethrough | Highlight,
Inline = NaturualConstructs | InlineCode | Link | Style | HTMLTag | InlineImage | ReferenceImage | Math,
Block = ~Inline,
}
13 changes: 12 additions & 1 deletion src/parser/parse.ts
Expand Up @@ -9,6 +9,7 @@ import { SquareQuoted } from '../nodes/square-quoted'
import { Emphasis, EmphasisDelimiter } from '../nodes/empasis'
import { Quoted } from '../nodes/quoted'
import { Strong, StrongDelimiter } from '../nodes/strong'
import { Highlight } from '../nodes/highlight'
import { Strikethrough } from '../nodes/strikethrough'
import { Document } from '../nodes/document'
import { compactTree } from '../transformers/compact'
Expand Down Expand Up @@ -178,7 +179,7 @@ export function parse (str: string, options :NormalizedPadMarkdownOptions): Docu
i++
}

// Strong, Emphasis, Strikethrough
// Strong, Emphasis, Strikethrough, highlight
else if (state === State.Emphasis && c === emphasisDelimiter && c === '_' && isWordBoundary(str[i + 1])) {
resolve(new Emphasis(popNodes(), emphasisDelimiter))
i++
Expand All @@ -195,6 +196,10 @@ export function parse (str: string, options :NormalizedPadMarkdownOptions): Docu
resolve(new Strikethrough(popNodes()))
i += 2
}
else if (state === State.Highlight && c2 === '==') {
resolve(new Highlight(popNodes()))
i += 2
}

// ListItems
else if (state === State.UnorderedListItem && c === '\n') {
Expand Down Expand Up @@ -278,6 +283,9 @@ export function parse (str: string, options :NormalizedPadMarkdownOptions): Docu
strongDelimiter = c2
i += 2
push(State.Strong)
} else if (c2 === '==' && allow(NodeKind.Highlight)) {
i += 2
push(State.Highlight)
} else if (c === '*' && allow(NodeKind.Emphasis)) {
emphasisDelimiter = c
i++
Expand Down Expand Up @@ -354,6 +362,9 @@ export function parse (str: string, options :NormalizedPadMarkdownOptions): Docu
case State.Strong:
resolve(...[...strongDelimiter].map(c => Punctuation.create(c)), ...popNodes())
break
case State.Highlight:
resolve(Punctuation.create('='), Punctuation.create('='), ...popNodes())
break
case State.InlineCode:
resolve(
...[...inlineCodeDelimiter].map(c => Punctuation.create(c)),
Expand Down
1 change: 1 addition & 0 deletions src/parser/state.ts
Expand Up @@ -20,6 +20,7 @@ export enum State {
UnorderedListItem, // *<space>
BlockquoteItem, // >
CalloutItem, // [!
Highlight, // ==

// natural language syntax
Quoted, // " in natural language
Expand Down
73 changes: 73 additions & 0 deletions test/parser/parse.spec.ts
Expand Up @@ -475,6 +475,79 @@ describe('parse()', () => {
})
})

describe('Highlight', () => {
it('should allow highlight', () => {
const doc = parse('==123==', options)
expect(doc.children).toHaveLength(1)

const highlight = doc.children[0]
expect(highlight).toMatchObject({
kind: NodeKind.Highlight
})

expect(highlight.children).toHaveLength(1)
const number = highlight.children[0]
expect(number).toMatchObject({
kind: NodeKind.AlphabetNumeric,
text: '123'
})

expect(highlight.toMarkdown()).toEqual('==123==')
})

it('should expand Highlight when EOF found', () => {
const doc = parse('==123', options)
expect(doc.children).toHaveLength(3)

const [p1, p2, a1] = doc.children
expect(p1).toMatchObject({
kind: NodeKind.Punctuation,
char: '='
})
expect(p2).toMatchObject({
kind: NodeKind.Punctuation,
char: '='
})
expect(a1).toMatchObject({
kind: NodeKind.AlphabetNumeric,
text: '123'
})
})

it('should expand repeatedly Highlight when NL found', () => {
const doc = parse('==foo\n==bar==', options)
expect(doc.children).toHaveLength(5)

const [p1, p2, a1, blank, highlight] = doc.children
expect(p1).toMatchObject({
kind: NodeKind.Punctuation,
char: '='
})
expect(p2).toMatchObject({
kind: NodeKind.Punctuation,
char: '='
})
expect(a1).toMatchObject({
kind: NodeKind.AlphabetNumeric,
text: 'foo'
})
expect(blank).toMatchObject({
kind: NodeKind.Blank,
char: '\n'
})
expect(highlight).toMatchObject({
kind: NodeKind.Highlight
})

expect(highlight.children).toHaveLength(1)
const alphabet = highlight.children[0]
expect(alphabet).toMatchObject({
kind: NodeKind.AlphabetNumeric,
text: 'bar'
})
})
})

describe('BlockCode', () => {
it('should parse block code', () => {
const doc = parse('```\ncode\n```', options)
Expand Down

0 comments on commit 66af404

Please sign in to comment.