Skip to content

Commit

Permalink
Browse files Browse the repository at this point in the history
Use line-spans to help fold-link
  • Loading branch information
laobubu committed Oct 6, 2018
1 parent 8d048af commit b0f0048
Show file tree
Hide file tree
Showing 4 changed files with 49 additions and 23 deletions.
3 changes: 1 addition & 2 deletions docs/zh-CN/README.md
Expand Up @@ -6,8 +6,7 @@

[![NPM version](https://img.shields.io/npm/v/hypermd.svg?style=flat-square)](https://npmjs.org/package/hypermd) [![Build Status](https://travis-ci.org/laobubu/HyperMD.svg?branch=master)](https://travis-ci.org/laobubu/HyperMD)

[在线体验](https://laobubu.net/HyperMD/) | [功能演示][examples] |
[开发文档][doc]
[在线体验](https://laobubu.net/HyperMD/) | [功能演示][examples] | [开发文档][doc]

[English](../../README.md)

Expand Down
38 changes: 21 additions & 17 deletions src/addon/fold-link.ts
Expand Up @@ -7,6 +7,7 @@
import { FolderFunc, registerFolder, RequestRangeResult, breakMark } from "./fold";
import { Position } from "codemirror";
import { splitLink } from "./read-link";
import { getLineSpanExtractor, Span } from "../core/line-spans";

const DEBUG = false

Expand All @@ -16,26 +17,29 @@ export const LinkFolder: FolderFunc = function (stream, token) {
// a valid beginning must be ...
if (!(
token.string === '[' && // the leading [
token.state.linkText && // (double check)
token.state.linkText && // (double check) is link text
!token.state.linkTitle && // (double check) not image's title
!/\bimage\b/.test(token.type) // and is not a image mark
)) return null

// first, find the left parentheses of URL (aka. href)
var url_begin = stream.findNext((token, tokens, idx) => {
if (token.string !== '(' || !token.state.linkHref) return false
if (idx > 0 && /\bimage\b/.test(tokens[idx - 1].type)) return false
return true
}, /* maySpanLines = */ true)
if (!url_begin) return null

// then, find the right parentheses of URL (aka. href)
var url_end = stream.findNext(token => !token.state.linkHref, url_begin.i_token)
if (!url_end || url_end.token.string !== ')') return null

// now we get keypoints
const href_from: Position = { line: url_begin.lineNo, ch: url_begin.token.start }
const href_to: Position = { line: url_end.lineNo, ch: url_end.token.end }
const link_from: Position = { line: stream.lineNo, ch: token.start }
let spanExtractor = getLineSpanExtractor(cm)
let tmpSpans: Span[]

// first, find the link text span

let linkTextSpan = spanExtractor.findSpanWithTypeAt({ line: stream.lineNo, ch: token.start }, "linkText")
if (!linkTextSpan) return null

// then find the link href span

let linkHrefSpan = spanExtractor.findSpanWithTypeAt({ line: stream.lineNo, ch: linkTextSpan.end + 1 }, "linkHref")
if (!linkHrefSpan) return null

// now compose the ranges

const href_from: Position = { line: stream.lineNo, ch: linkHrefSpan.begin }
const href_to: Position = { line: stream.lineNo, ch: linkHrefSpan.end }
const link_from: Position = { line: stream.lineNo, ch: linkTextSpan.begin }
const link_to: Position = href_to

// and check if the range is OK
Expand Down
2 changes: 1 addition & 1 deletion src/addon/hide-token.ts
Expand Up @@ -52,7 +52,7 @@ export interface Options extends Addon.AddonOptions {
export const defaultOption: Options = {
enabled: false,
line: true,
tokenTypes: "em|strong|strikethrough|code|link|task".split("|"),
tokenTypes: "em|strong|strikethrough|code|linkText|task".split("|"),
}

export const suggestedOption: Partial<Options> = {
Expand Down
29 changes: 26 additions & 3 deletions src/core/line-spans.ts
@@ -1,6 +1,6 @@
import { cm_t } from "./type"
import { Token, Position, cmpPos } from "codemirror"
import { HyperMDState, LinkType } from "../mode/hypermd";
import { HyperMDState, LinkType, HashtagType } from "../mode/hypermd";
import { makeSymbol } from "./utils";

export interface Span {
Expand All @@ -17,7 +17,7 @@ export interface Span {
end: number
}

type SpanType = "em" | "strong" | "strikethrough" | "code" | "link" | "task"
type SpanType = "em" | "strong" | "strikethrough" | "code" | "linkText" | "linkHref" | "task" | "hashtag"

const enum SpanAction {
NOTHING = 0,
Expand Down Expand Up @@ -66,16 +66,27 @@ class LineSpanExtractor {
: prevState.code ? SpanAction.LEAVING_THIS_TYPE : SpanAction.NOTHING),

// linkText
link:
linkText:
(state.linkText ?
(state.hmdLinkType === LinkType.NORMAL || state.hmdLinkType === LinkType.BARELINK2 ? SpanAction.IS_THIS_TYPE : SpanAction.NOTHING) :
(prevState.linkText ? SpanAction.LEAVING_THIS_TYPE : SpanAction.NOTHING)
),

// linkHref
linkHref:
((state.linkHref && !state.linkText) ?
SpanAction.IS_THIS_TYPE :
(!state.linkHref && !state.linkText && prevState.linkHref && !prevState.linkText) ? SpanAction.LEAVING_THIS_TYPE : SpanAction.NOTHING
),

// task checkbox
task: (styles.indexOf(' formatting-task ') !== -1)
? (SpanAction.IS_THIS_TYPE | SpanAction.LEAVING_THIS_TYPE)
: (SpanAction.NOTHING),

// hashtag
hashtag: (state.hmdHashtag ? SpanAction.IS_THIS_TYPE :
prevState.hmdHashtag ? SpanAction.LEAVING_THIS_TYPE : SpanAction.NOTHING),
}
return ans
}
Expand Down Expand Up @@ -147,6 +158,18 @@ class LineSpanExtractor {

return ans
}

findSpanWithTypeAt(pos: Position, type: SpanType) {
let spans = this.extract(pos.line)
let ch = pos.ch
for (let i = 0; i < spans.length; i++) {
let span = spans[i]
if (span.begin > ch) break
if (ch >= span.begin && span.end >= ch && span.type === type) return span
}

return null
}
}

const extractor_symbol = makeSymbol("LineSpanExtractor")
Expand Down

0 comments on commit b0f0048

Please sign in to comment.