Skip to content

Commit d226ca6

Browse files
authored
Merge pull request #13 from hackmdio/fix/blockquote-position
Fix/blockquote position
2 parents 4881ab4 + 70b4a0a commit d226ca6

File tree

8 files changed

+40
-40
lines changed

8 files changed

+40
-40
lines changed

lib/common/utils.js

Lines changed: 5 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -289,37 +289,13 @@ function normalizeReference(str) {
289289
return str.toLowerCase().toUpperCase();
290290
}
291291

292-
/* eslint-env browser */
293-
var _g = typeof global !== 'undefined' ? global : window;
294-
var tokensRef = new _g.WeakMap();
295-
296-
// TODO: performance tweaks for emphasis **_* pattern which has only 1/10 performance after adding line offset
297-
function getLineOffset(state, tokenIdx) {
298-
var blockState = state.env.state_block;
299-
var parentToken = state.env.parentToken;
300-
var tokensBefore = typeof tokenIdx !== 'undefined' ? state.tokens.slice(0, tokenIdx) : state.tokens;
301-
302-
var resultsMap = tokensRef.get(state.tokens);
303-
if (resultsMap) {
304-
var cachedResult = resultsMap.get(tokenIdx);
305-
if (typeof cachedResult !== 'undefined') {
306-
return cachedResult;
307-
}
292+
function getLineOffset(state) {
293+
if (state.env.parentToken.parentType === 'blockquote') {
294+
const blockState = state.env.state_block;
295+
return blockState.lineOffsets[state.currentLine] ?? 0;
308296
} else {
309-
resultsMap = new _g.Map();
310-
tokensRef.set(state.tokens, resultsMap);
297+
return 0;
311298
}
312-
313-
var linesBefore = tokensBefore.filter(function (t) { return t.type === 'softbreak' || t.type === 'hardbreak'; }).length;
314-
315-
var lineOffset = 0;
316-
for (var i = 0; i < linesBefore; i++) {
317-
var startLine = i + parentToken.map[0] + 1;
318-
lineOffset += blockState.tShift[startLine];
319-
}
320-
321-
resultsMap.set(tokenIdx, lineOffset);
322-
return lineOffset;
323299
}
324300

325301
function trimLeftOffset(str) {

lib/rules_block/blockquote.js

Lines changed: 27 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -272,15 +272,38 @@ module.exports = function blockquote(state, startLine, endLine, silent) {
272272
state.parentType = oldParentType;
273273
lines[1] = state.line;
274274

275+
let totalLineOffset = 0;
275276
// Restore original tShift; this might not be necessary since the parser
276277
// has already been here, but just to make sure we can do that.
277278
for (i = 0; i < oldTShift.length; i++) {
278-
state.bMarks[i + startLine] = oldBMarks[i];
279-
state.tShift[i + startLine] = oldTShift[i];
280-
state.sCount[i + startLine] = oldSCount[i];
281-
state.bsCount[i + startLine] = oldBSCount[i];
279+
const lineNumber = i + startLine;
280+
if (state.lineOffsets[lineNumber] === null) {
281+
state.lineOffsets[lineNumber] = totalLineOffset;
282+
if (isNotEmptyLine(state, lineNumber)) {
283+
totalLineOffset += calcLineOffset(state, lineNumber);
284+
} else {
285+
totalLineOffset = 0;
286+
}
287+
}
288+
289+
state.bMarks[lineNumber] = oldBMarks[i];
290+
state.tShift[lineNumber] = oldTShift[i];
291+
state.sCount[lineNumber] = oldSCount[i];
292+
state.bsCount[lineNumber] = oldBSCount[i];
282293
}
283294
state.blkIndent = oldIndent;
284295

285296
return true;
286297
};
298+
299+
function calcLineOffset (state, lineNumber) {
300+
const previousLineEnd = state.eMarks[lineNumber - 1] + 1 || 0;
301+
return state.bMarks[lineNumber] - previousLineEnd;
302+
}
303+
304+
function isNotEmptyLine (state, lineNumber) {
305+
return (
306+
state.bMarks[lineNumber] + state.tShift[lineNumber] <
307+
state.eMarks[lineNumber]
308+
)
309+
}

lib/rules_block/lheading.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ module.exports = function lheading(state, startLine, endLine/*, silent*/) {
5959

6060
if (!level) {
6161
// Didn't find valid underline
62+
state.parentType = oldParentType;
6263
return false;
6364
}
6465

lib/rules_block/state_block.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ function StateBlock(src, md, env, tokens) {
3131
this.eMarks = []; // line end offsets for fast jumps
3232
this.tShift = []; // offsets of the first non-space characters (tabs not expanded)
3333
this.sCount = []; // indents for each line (tabs expanded)
34+
this.lineOffsets = [];
3435

3536
// An amount of virtual spaces (tabs expanded) between beginning
3637
// of each line (bMarks) and real beginning of that line.
@@ -92,6 +93,7 @@ function StateBlock(src, md, env, tokens) {
9293
this.tShift.push(indent);
9394
this.sCount.push(offset);
9495
this.bsCount.push(0);
96+
this.lineOffsets.push(null);
9597

9698
indent_found = false;
9799
indent = 0;
@@ -106,6 +108,7 @@ function StateBlock(src, md, env, tokens) {
106108
this.tShift.push(0);
107109
this.sCount.push(0);
108110
this.bsCount.push(0);
111+
this.lineOffsets.push(null);
109112

110113
this.lineMax = this.bMarks.length - 1; // don't count last fake line
111114
}

lib/rules_inline/emphasis.js

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2,9 +2,6 @@
22
//
33
'use strict';
44

5-
var getLineOffset = require('../common/utils').getLineOffset;
6-
7-
85
// Insert each marker as a separate text token, and add it to delimiter list
96
//
107
module.exports.tokenize = function emphasis(state, silent) {
@@ -107,7 +104,7 @@ function postProcess(state, delimiters) {
107104
token.nesting = 1;
108105
token.markup = isStrong ? ch + ch : ch;
109106
token.content = '';
110-
token.position = startDelim.position + getLineOffset(state, startDelim.token);
107+
token.position = startDelim.position;
111108

112109
token = state.tokens[endDelim.token];
113110
token.type = isStrong ? 'strong_close' : 'em_close';

lib/rules_inline/newline.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@ module.exports = function newline(state, silent) {
3434
token.position = pos;
3535
}
3636
}
37+
state.currentLine += 1;
3738

3839
pos++;
3940

lib/rules_inline/state_inline.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,7 @@ function StateInline(src, md, env, outTokens) {
3232
}
3333
});
3434
this.pendingLevel = 0;
35+
this.currentLine = env.parentToken.map[0];
3536

3637
// Stores { start: end } pairs. Useful for backtrack
3738
// optimization of pairs parse (emphasis, strikes).

lib/rules_inline/strikethrough.js

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22
//
33
'use strict';
44

5-
var getLineOffset = require('../common/utils').getLineOffset;
6-
75
// Insert each marker as a separate text token, and add it to delimiter list
86
//
97
module.exports.tokenize = function strikethrough(state, silent) {
@@ -76,7 +74,7 @@ function postProcess(state, delimiters) {
7674
token.nesting = 1;
7775
token.markup = '~~';
7876
token.content = '';
79-
token.position = startDelim.position + getLineOffset(state, startDelim.token);
77+
token.position = startDelim.position;
8078

8179
token = state.tokens[endDelim.token];
8280
token.type = 's_close';

0 commit comments

Comments
 (0)