Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Language recognition for code blocks #16263

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
11 changes: 10 additions & 1 deletion packages/ckeditor5-autoformat/src/autoformat.ts
Original file line number Diff line number Diff line change
Expand Up @@ -192,7 +192,16 @@ export default class Autoformat extends Plugin {
const selection = editor.model.document.selection;

if ( editor.commands.get( 'codeBlock' ) ) {
blockAutoformatEditing( editor, this, /^```$/, () => {
blockAutoformatEditing( editor, this, /^```(\S+)\s$/, match => {
const blockLanguage = match.match[ 1 ];
if ( selection.getFirstPosition()!.parent.is( 'element', 'listItem' ) ) {
return false;
}
this.editor.execute( 'codeBlock', {
language: blockLanguage, forceValue: true }
);
} );
blockAutoformatEditing( editor, this, /^```\s$/, () => {
if ( selection.getFirstPosition()!.parent.is( 'element', 'listItem' ) ) {
return false;
}
Expand Down
84 changes: 60 additions & 24 deletions packages/ckeditor5-autoformat/tests/autoformat.js
Original file line number Diff line number Diff line change
Expand Up @@ -509,57 +509,57 @@ describe( 'Autoformat', () => {

describe( 'Code block', () => {
it( 'should replace triple grave accents with a code block', () => {
setData( model, '<paragraph>``[]</paragraph>' );
setData( model, '<paragraph>```[]</paragraph>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="plaintext">[]</codeBlock>' );
} );

it( 'should replace triple grave accents in a heading', () => {
setData( model, '<heading1>``[]</heading1>' );
setData( model, '<heading1>```[]</heading1>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="plaintext">[]</codeBlock>' );
} );

it( 'should replace triple grave accents in a non-empty paragraph', () => {
setData( model, '<paragraph>``[]let foo = 1;</paragraph>' );
setData( model, '<paragraph>```[]let foo = 1;</paragraph>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="plaintext">[]let foo = 1;</codeBlock>' );
} );

it( 'should not replace triple grave accents in a numbered list', () => {
setData( model, '<listItem listIndent="0" listType="numbered">``[]let foo = 1;</listItem>' );
setData( model, '<listItem listIndent="0" listType="numbered">```[]let foo = 1;</listItem>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="numbered">```[]let foo = 1;</listItem>' );
expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="numbered">``` []let foo = 1;</listItem>' );
} );

it( 'should not replace triple grave accents in a bulleted list', () => {
setData( model, '<listItem listIndent="0" listType="bulleted">``[]let foo = 1;</listItem>' );
setData( model, '<listItem listIndent="0" listType="bulleted">```[]let foo = 1;</listItem>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="bulleted">```[]let foo = 1;</listItem>' );
expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="bulleted">``` []let foo = 1;</listItem>' );
} );

it( 'should not replace triple grave accents when already in a code block', () => {
setData( model, '<codeBlock language="plaintext">``[]</codeBlock>' );
setData( model, '<codeBlock language="plaintext">```[]</codeBlock>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="plaintext">```[]</codeBlock>' );
expect( getData( model ) ).to.equal( '<codeBlock language="plaintext">``` []</codeBlock>' );
} );

it( 'should remember the last used language', () => {
Expand All @@ -571,19 +571,55 @@ describe( 'Autoformat', () => {

// Typing '```' in a single change does not trigger the autoformat feature.
model.change( writer => {
writer.insertText( '``', doc.selection.getFirstPosition() );
writer.insertText( '```', doc.selection.getFirstPosition() );
} );

model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="cpp">[]</codeBlock>' );
} );

it( 'should replace triple grave accents followed by a language with a code block of that language', () => {
setData( model, '<paragraph>```python[]</paragraph>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="python">[]</codeBlock>' );
} );

it( 'should not replace triple grave accents with language in a numbered list', () => {
setData( model, '<listItem listIndent="0" listType="numbered">```python[]let foo = 1;</listItem>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="numbered">```python []let foo = 1;</listItem>' );
} );

it( 'should not replace triple grave accents with language in a bulleted list', () => {
setData( model, '<listItem listIndent="0" listType="bulleted">```python[]let foo = 1;</listItem>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="bulleted">```python []let foo = 1;</listItem>' );
} );

it( 'should not replace triple grave accents with language when already in a code block', () => {
setData( model, '<codeBlock language="plaintext">```python[]</codeBlock>' );
model.change( writer => {
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<codeBlock language="plaintext">```python []</codeBlock>' );
} );
} );

describe( 'Horizontal line', () => {
it( 'should replace three dashes with a horizontal line', () => {
it( 'should replace three dashes with with language a horizontal line', () => {
setData( model, '<paragraph>--[]</paragraph>' );
model.change( writer => {
writer.insertText( '-', doc.selection.getFirstPosition() );
Expand Down Expand Up @@ -613,21 +649,21 @@ describe( 'Autoformat', () => {
} );

it( 'should not replace triple grave accents when inside todo list', () => {
setData( model, '<listItem listIndent="0" listType="todo">``[]</listItem>' );
setData( model, '<listItem listIndent="0" listType="todo">```[]</listItem>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="todo">```[]</listItem>' );
expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="todo">``` []</listItem>' );
} );

it( 'should not replace triple grave accents when inside checked todo list', () => {
setData( model, '<listItem listIndent="0" listType="todo" todoListChecked="true">``[]</listItem>' );
setData( model, '<listItem listIndent="0" listType="todo" todoListChecked="true">```[]</listItem>' );
model.change( writer => {
writer.insertText( '`', doc.selection.getFirstPosition() );
writer.insertText( ' ', doc.selection.getFirstPosition() );
} );

expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="todo" todoListChecked="true">```[]</listItem>' );
expect( getData( model ) ).to.equal( '<listItem listIndent="0" listType="todo" todoListChecked="true">``` []</listItem>' );
} );
} );

Expand Down
4 changes: 3 additions & 1 deletion packages/ckeditor5-autoformat/tests/manual/autoformat.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,9 @@ Note: autoformat should not work in a code blocks.

1. Type `~~foobar~~` to strikethrough `foobar`. `~~` should be removed.

1. Type `` ``` `` in a new line to create an empty code block. `` ``` `` should be removed.
1. Type `` ``` `` followed by a language to create an empty code block with that language. `` ```[language] `` should be removed.

1. Type `` ``` `` (``` followed by any whitespace) in a new line to create an empty code block. `` ``` `` should be removed.

1. Type `---` in a new line to create a horizontal line. `---` should be removed.

Expand Down