提交 8b1cb964 编写于 作者: A Alex Dima

Emit dir attribute on rendered spans (fixes Microsoft/monaco-editor#280)

上级 9543056d
......@@ -94,9 +94,10 @@ export class Colorizer {
});
}
public static colorizeLine(line: string, tokens: ViewLineToken[], tabSize: number = 4): string {
public static colorizeLine(line: string, mightContainRTL: boolean, tokens: ViewLineToken[], tabSize: number = 4): string {
let renderResult = renderViewLine(new RenderLineInput(
line,
mightContainRTL,
0,
tokens,
[],
......@@ -113,7 +114,7 @@ export class Colorizer {
let content = model.getLineContent(lineNumber);
let tokens = model.getLineTokens(lineNumber, false);
let inflatedTokens = tokens.inflate();
return this.colorizeLine(content, inflatedTokens, tabSize);
return this.colorizeLine(content, model.mightContainRTL(), inflatedTokens, tabSize);
}
}
......@@ -129,6 +130,7 @@ function _fakeColorize(lines: string[], tabSize: number): string {
let renderResult = renderViewLine(new RenderLineInput(
line,
false,
0,
[new ViewLineToken(line.length, '')],
[],
......@@ -157,6 +159,7 @@ function _actualColorize(lines: string[], tabSize: number, tokenizationSupport:
let lineTokens = new LineTokens(colorMap, tokenizeResult.tokens, line);
let renderResult = renderViewLine(new RenderLineInput(
line,
true/* check for RTL */,
0,
lineTokens.inflate(),
[],
......
......@@ -102,6 +102,7 @@ export class ViewLine implements IVisibleLineData {
let renderLineInput = new RenderLineInput(
model.getLineContent(lineNumber),
model.mightContainRTL(),
model.getLineMinColumn(lineNumber) - 1,
model.getLineTokens(lineNumber),
actualInlineDecorations,
......
......@@ -134,7 +134,7 @@ export abstract class CodeEditorWidget extends CommonCodeEditor implements edito
let tokens = model.getLineTokens(lineNumber, false);
let inflatedTokens = tokens.inflate();
let tabSize = model.getOptions().tabSize;
return Colorizer.colorizeLine(content, inflatedTokens, tabSize);
return Colorizer.colorizeLine(content, model.mightContainRTL(), inflatedTokens, tabSize);
}
public getView(): editorBrowser.IView {
return this._view;
......
......@@ -1889,6 +1889,7 @@ class InlineViewZonesComputer extends ViewZonesComputer {
let r = renderViewLine(new RenderLineInput(
lineContent,
originalModel.mightContainRTL(),
0,
[new ViewLineToken(lineContent.length, '')],
actualDecorations,
......
......@@ -18,6 +18,7 @@ export const enum RenderWhitespace {
export class RenderLineInput {
public readonly lineContent: string;
public readonly mightContainRTL: boolean;
public readonly fauxIndentLength: number;
public readonly lineTokens: ViewLineToken[];
public readonly lineDecorations: Decoration[];
......@@ -29,6 +30,7 @@ export class RenderLineInput {
constructor(
lineContent: string,
mightContainRTL: boolean,
fauxIndentLength: number,
lineTokens: ViewLineToken[],
lineDecorations: Decoration[],
......@@ -39,6 +41,7 @@ export class RenderLineInput {
renderControlCharacters: boolean,
) {
this.lineContent = lineContent;
this.mightContainRTL = mightContainRTL;
this.fauxIndentLength = fauxIndentLength;
this.lineTokens = lineTokens;
this.lineDecorations = lineDecorations;
......@@ -58,6 +61,7 @@ export class RenderLineInput {
public equals(other: RenderLineInput): boolean {
return (
this.lineContent === other.lineContent
&& this.mightContainRTL === other.mightContainRTL
&& this.fauxIndentLength === other.fauxIndentLength
&& this.tabSize === other.tabSize
&& this.spaceWidth === other.spaceWidth
......@@ -213,6 +217,7 @@ class ResolvedRenderLineInput {
public readonly tokens: ViewLineToken[],
public readonly lineDecorations: Decoration[],
public readonly tabSize: number,
public readonly emitLTRDir: boolean,
public readonly spaceWidth: number,
public readonly renderWhitespace: RenderWhitespace,
public readonly renderControlCharacters: boolean,
......@@ -243,6 +248,11 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
tokens = _applyInlineDecorations(lineContent, len, tokens, input.lineDecorations);
}
let emitLTRDir = false;
if (input.mightContainRTL) {
emitLTRDir = strings.containsRTL(lineContent);
}
return new ResolvedRenderLineInput(
lineContent,
len,
......@@ -250,6 +260,7 @@ function resolveRenderLineInput(input: RenderLineInput): ResolvedRenderLineInput
tokens,
input.lineDecorations,
input.tabSize,
emitLTRDir,
input.spaceWidth,
input.renderWhitespace,
input.renderControlCharacters
......@@ -424,6 +435,7 @@ function _renderLine(input: ResolvedRenderLineInput): RenderLineOutput {
const isOverflowing = input.isOverflowing;
const tokens = input.tokens;
const tabSize = input.tabSize;
const emitLTRDir = input.emitLTRDir;
const spaceWidth = input.spaceWidth;
const renderWhitespace = input.renderWhitespace;
const renderControlCharacters = input.renderControlCharacters;
......@@ -534,7 +546,11 @@ function _renderLine(input: ResolvedRenderLineInput): RenderLineOutput {
charOffsetInPart++;
}
out += `<span class="${tokenType}">${partContent}</span>`;
if (emitLTRDir) {
out += `<span dir="ltr" class="${tokenType}">${partContent}</span>`;
} else {
out += `<span class="${tokenType}">${partContent}</span>`;
}
}
}
......
......@@ -58,6 +58,7 @@ suite('Editor ViewLayout - ViewLineParts', () => {
function testCreateLineParts(lineContent: string, tokens: ViewLineToken[], fauxIndentLength: number, renderWhitespace: 'none' | 'boundary' | 'all', expected: string): void {
let actual = renderViewLine(new RenderLineInput(
lineContent,
false,
fauxIndentLength,
tokens,
[],
......@@ -267,6 +268,7 @@ suite('Editor ViewLayout - ViewLineParts', () => {
test('createLineParts can handle unsorted inline decorations', () => {
let actual = renderViewLine(new RenderLineInput(
'Hello world',
false,
0,
[new ViewLineToken(11, '')],
[
......@@ -371,6 +373,7 @@ suite('Editor ViewLayout - ViewLineParts', () => {
function createTestGetColumnOfLinePartOffset(lineContent: string, tabSize: number, parts: ViewLineToken[]): (partIndex: number, partLength: number, offset: number, expected: number) => void {
let renderLineOutput = renderViewLine(new RenderLineInput(
lineContent,
false,
0,
parts,
[],
......
......@@ -18,6 +18,7 @@ suite('viewLineRenderer.renderLine', () => {
function assertCharacterReplacement(lineContent: string, tabSize: number, expected: string, expectedCharOffsetInPart: number[][]): void {
let _actual = renderViewLine(new RenderLineInput(
lineContent,
false,
0,
[new ViewLineToken(lineContent.length, '')],
[],
......@@ -62,6 +63,7 @@ suite('viewLineRenderer.renderLine', () => {
function assertParts(lineContent: string, tabSize: number, parts: ViewLineToken[], expected: string, expectedCharOffsetInPart: number[][]): void {
let _actual = renderViewLine(new RenderLineInput(
lineContent,
false,
0,
parts,
[],
......@@ -95,6 +97,7 @@ suite('viewLineRenderer.renderLine', () => {
test('overflow', () => {
let _actual = renderViewLine(new RenderLineInput(
'Hello world!',
false,
0,
[
createPart(1, '0'),
......@@ -190,6 +193,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
lineText,
false,
0,
lineParts,
[],
......@@ -246,6 +250,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
lineText,
false,
0,
lineParts,
[],
......@@ -302,6 +307,7 @@ suite('viewLineRenderer.renderLine', () => {
let _actual = renderViewLine(new RenderLineInput(
lineText,
false,
0,
lineParts,
[],
......@@ -316,6 +322,39 @@ suite('viewLineRenderer.renderLine', () => {
assertCharacterMapping(_actual.characterMapping, expectedOffsetsArr);
});
test('issue Microsoft/monaco-editor#280: Improved source code rendering for RTL languages', () => {
let lineText = 'var קודמות = \"מיותר קודמות צ\'ט של, אם לשון העברית שינויים ויש, אם\";';
let lineParts = [
createPart(3, 'mtk6'),
createPart(13, 'mtk1'),
createPart(66, 'mtk20'),
createPart(67, 'mtk1'),
];
let expectedOutput = [
'<span dir="ltr" class="mtk6">var</span>',
'<span dir="ltr" class="mtk1">&nbsp;קודמות&nbsp;=&nbsp;</span>',
'<span dir="ltr" class="mtk20">"מיותר&nbsp;קודמות&nbsp;צ\'ט&nbsp;של,&nbsp;אם&nbsp;לשון&nbsp;העברית&nbsp;שינויים&nbsp;ויש,&nbsp;אם"</span>',
'<span dir="ltr" class="mtk1">;</span>'
].join('');
let _actual = renderViewLine(new RenderLineInput(
lineText,
true,
0,
lineParts,
[],
4,
10,
-1,
'none',
false
));
assert.equal(_actual.output, '<span>' + expectedOutput + '</span>');
});
function assertCharacterMapping(actual: CharacterMapping, expected: number[][]): void {
let charOffset = 0;
for (let partIndex = 0; partIndex < expected.length; partIndex++) {
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册