mirror of
https://github.com/microsoft/vscode.git
synced 2026-07-13 23:44:09 +01:00
Emit dir attribute on rendered spans (fixes Microsoft/monaco-editor#280)
This commit is contained in:
@@ -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"> קודמות = </span>',
|
||||
'<span dir="ltr" class="mtk20">"מיותר קודמות צ\'ט של, אם לשון העברית שינויים ויש, אם"</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++) {
|
||||
|
||||
Reference in New Issue
Block a user