format button wasnt working, will add playwright test so we don't regress again (#2340)

* add test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add another test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add another test

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* off by one error

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* add two tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix typos

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* updates

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix semantic tokens for commants

Signed-off-by: Jess Frazelle <github@jessfraz.com>

* fix tests

Signed-off-by: Jess Frazelle <github@jessfraz.com>

---------

Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
Jess Frazelle
2024-05-10 15:30:40 -07:00
committed by GitHub
parent da323e22d4
commit d0f9ae475f
173 changed files with 540 additions and 56 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -264,6 +264,85 @@ test('Can moving camera', async ({ page, context }) => {
}, [1, -94, -94])
})
test('if you click the format button it formats your code', async ({
page,
}) => {
const u = getUtils(page)
await page.setViewportSize({ width: 1000, height: 500 })
await page.goto('/')
await u.waitForAuthSkipAppStart()
// check no error to begin with
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
await page.click('.cm-content')
await page.keyboard.type(`const part001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> close(%)`)
await page.click('#code-pane button:first-child')
await page.click('button:has-text("Format code")')
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> close(%)`)
})
test('if you use the format keyboard binding it formats your code', async ({
page,
}) => {
test.skip(
true,
"I can't figure out how to get the keyboard shortcut to work (in playwright)"
)
const u = getUtils(page)
await page.setViewportSize({ width: 1000, height: 500 })
const lspStartPromise = page.waitForEvent('console', async (message) => {
// it would be better to wait for a message that the kcl lsp has started by looking for the message message.text().includes('[lsp] [window/logMessage]')
// but that doesn't seem to make it to the console for macos/safari :(
if (message.text().includes('start kcl lsp')) {
await new Promise((resolve) => setTimeout(resolve, 200))
return true
}
return false
})
await page.goto('/')
await u.waitForAuthSkipAppStart()
await lspStartPromise
// check no error to begin with
await expect(page.locator('.cm-lint-marker-error')).not.toBeVisible()
await page.click('.cm-content')
await page.keyboard.type(`const part001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> close(%)`)
await page.click('.cm-content')
// Hit alt+shift+f to format the code
await page.keyboard.press('Alt+Shift+KeyF')
await expect(page.locator('.cm-content'))
.toHaveText(`const part001 = startSketchOn('XY')
|> startProfileAt([-10, -10], %)
|> line([20, 0], %)
|> line([0, 20], %)
|> line([-20, 0], %)
|> close(%)`)
})
test('if you write invalid kcl you get inlined errors', async ({ page }) => {
const u = getUtils(page)
await page.setViewportSize({ width: 1000, height: 500 })
@ -529,10 +608,6 @@ test.describe('Can create sketches on all planes and their back sides', () => {
})
test('Auto complete works', async ({ page }) => {
test.skip(
true,
'CORS issue stopping the kcl lsp from working, enable again later'
)
const u = getUtils(page)
// const PUR = 400 / 37.5 //pixeltoUnitRatio
await page.setViewportSize({ width: 1200, height: 500 })

View File

@ -79,6 +79,7 @@ export default class CodeManager {
if (this._code !== code) {
this.code = code
this.#updateState(code)
this.updateCodeEditor(code)
}
}

View File

@ -1895,7 +1895,7 @@ dependencies = [
[[package]]
name = "kcl-lib"
version = "0.1.54"
version = "0.1.55"
dependencies = [
"anyhow",
"approx 0.5.1",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 80 KiB

After

Width:  |  Height:  |  Size: 80 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 82 KiB

After

Width:  |  Height:  |  Size: 82 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 79 KiB

After

Width:  |  Height:  |  Size: 79 KiB

View File

@ -1,7 +1,7 @@
[package]
name = "kcl-lib"
description = "KittyCAD Language implementation and tools"
version = "0.1.54"
version = "0.1.55"
edition = "2021"
license = "MIT"
repository = "https://github.com/KittyCAD/modeling-app"

View File

@ -3297,6 +3297,144 @@ fn ghi = (x) => {
assert_eq!(symbols.len(), 7);
}
#[test]
fn test_recast_bug_extra_parens() {
let some_program_string = r#"// Ball Bearing
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
// Define constants like ball diameter, inside diameter, overhange length, and thickness
const sphereDia = 0.5
const insideDia = 1
const thickness = 0.25
const overHangLength = .4
// Sketch and revolve the inside bearing piece
const insideRevolve = startSketchOn('XZ')
|> startProfileAt([insideDia / 2, 0], %)
|> line([0, thickness + sphereDia / 2], %)
|> line([overHangLength, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, -sphereDia], %)
|> line([overHangLength - thickness, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
const sphere = startSketchOn('XZ')
|> startProfileAt([
0.05 + insideDia / 2 + thickness,
0 - 0.05
], %)
|> line([sphereDia - 0.1, 0], %)
|> arc({
angle_start: 0,
angle_end: -180,
radius: sphereDia / 2 - 0.05
}, %)
|> close(%)
|> revolve({ axis: 'x' }, %)
|> patternCircular3d({
axis: [0, 0, 1],
center: [0, 0, 0],
repetitions: 10,
arcDegrees: 360,
rotateDuplicates: true
}, %)
// Sketch and revolve the outside bearing
const outsideRevolve = startSketchOn('XZ')
|> startProfileAt([
insideDia / 2 + thickness + sphereDia,
0
], %)
|> line([0, sphereDia / 2], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, thickness], %)
|> line([overHangLength, 0], %)
|> line([0, -2 * thickness - sphereDia], %)
|> line([-overHangLength, 0], %)
|> line([0, thickness], %)
|> line([overHangLength - thickness, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)"#;
let tokens = crate::token::lexer(some_program_string).unwrap();
let parser = crate::parser::Parser::new(tokens);
let program = parser.ast().unwrap();
println!("{:#?}", program);
let recasted = program.recast(&Default::default(), 0);
assert_eq!(
recasted,
r#"// Ball Bearing
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
// Define constants like ball diameter, inside diameter, overhange length, and thickness
const sphereDia = 0.5
const insideDia = 1
const thickness = 0.25
const overHangLength = .4
// Sketch and revolve the inside bearing piece
const insideRevolve = startSketchOn('XZ')
|> startProfileAt([insideDia / 2, 0], %)
|> line([0, thickness + sphereDia / 2], %)
|> line([overHangLength, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, -sphereDia], %)
|> line([overHangLength - thickness, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
const sphere = startSketchOn('XZ')
|> startProfileAt([
0.05 + insideDia / 2 + thickness,
0 - 0.05
], %)
|> line([sphereDia - 0.1, 0], %)
|> arc({
angle_start: 0,
angle_end: -180,
radius: sphereDia / 2 - 0.05
}, %)
|> close(%)
|> revolve({ axis: 'x' }, %)
|> patternCircular3d({
axis: [0, 0, 1],
center: [0, 0, 0],
repetitions: 10,
arcDegrees: 360,
rotateDuplicates: true
}, %)
// Sketch and revolve the outside bearing
const outsideRevolve = startSketchOn('XZ')
|> startProfileAt([
insideDia / 2 + thickness + sphereDia,
0
], %)
|> line([0, sphereDia / 2], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, thickness], %)
|> line([overHangLength, 0], %)
|> line([0, -2 * thickness - sphereDia], %)
|> line([-overHangLength, 0], %)
|> line([0, thickness], %)
|> line([overHangLength - thickness, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)
"#
);
}
#[test]
fn test_recast_empty_file() {
let some_program_string = r#""#;

View File

@ -313,6 +313,28 @@ impl Backend {
let source_range: SourceRange = token.clone().into();
let position = source_range.start_to_lsp_position(&params.text);
// We need to check if we are on the last token of the line.
// If we are starting from the end of the last line just add 1 to the line.
// Check if we are on the last token of the line.
if let Some(line) = params.text.lines().nth(position.line as usize) {
if line.len() == position.character as usize {
// We are on the last token of the line.
// We need to add a new line.
let semantic_token = SemanticToken {
delta_line: position.line - last_position.line + 1,
delta_start: 0,
length: token.value.len() as u32,
token_type: token_type_index as u32,
token_modifiers_bitset: 0,
};
semantic_tokens.push(semantic_token);
last_position = Position::new(position.line + 1, 0);
continue;
}
}
let semantic_token = SemanticToken {
delta_line: position.line - last_position.line,
delta_start: if position.line != last_position.line {
@ -1011,7 +1033,7 @@ impl LanguageServer for Backend {
},
0,
);
let source_range = SourceRange([0, current_code.len() - 1]);
let source_range = SourceRange([0, current_code.len()]);
let range = source_range.to_lsp_range(current_code);
Ok(Some(vec![TextEdit {
new_text: recast,

View File

@ -1014,15 +1014,86 @@ async fn test_kcl_lsp_semantic_tokens() {
if let tower_lsp::lsp_types::SemanticTokensResult::Tokens(semantic_tokens) = semantic_tokens {
assert_eq!(semantic_tokens.data.len(), 2);
assert_eq!(semantic_tokens.data[0].length, 13);
assert_eq!(semantic_tokens.data[0].delta_start, 0);
assert_eq!(semantic_tokens.data[0].delta_line, 0);
assert_eq!(semantic_tokens.data[0].token_type, 8);
assert_eq!(semantic_tokens.data[1].length, 4);
assert_eq!(semantic_tokens.data[1].delta_start, 14);
assert_eq!(semantic_tokens.data[1].delta_line, 0);
assert_eq!(semantic_tokens.data[1].token_type, 3);
} else {
panic!("Expected semantic tokens");
}
}
#[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_semantic_tokens_multiple_comments() {
let server = kcl_lsp_server(false).await.unwrap();
// Send open file.
server
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
text_document: tower_lsp::lsp_types::TextDocumentItem {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"// Ball Bearing
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
// Define constants like ball diameter, inside diameter, overhange length, and thickness
const sphereDia = 0.5"#.to_string(),
},
})
.await;
server.wait_on_handle().await;
// Send semantic tokens request.
let semantic_tokens = server
.semantic_tokens_full(tower_lsp::lsp_types::SemanticTokensParams {
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
partial_result_params: Default::default(),
work_done_progress_params: Default::default(),
})
.await
.unwrap()
.unwrap();
// Check the semantic tokens.
if let tower_lsp::lsp_types::SemanticTokensResult::Tokens(semantic_tokens) = semantic_tokens {
assert_eq!(semantic_tokens.data.len(), 7);
assert_eq!(semantic_tokens.data[0].length, 15);
assert_eq!(semantic_tokens.data[0].delta_start, 0);
assert_eq!(semantic_tokens.data[0].delta_line, 0);
assert_eq!(semantic_tokens.data[0].token_type, 6);
assert_eq!(semantic_tokens.data[1].length, 232);
assert_eq!(semantic_tokens.data[1].delta_start, 0);
assert_eq!(semantic_tokens.data[1].delta_line, 1);
assert_eq!(semantic_tokens.data[1].token_type, 6);
assert_eq!(semantic_tokens.data[2].length, 88);
assert_eq!(semantic_tokens.data[2].delta_start, 0);
assert_eq!(semantic_tokens.data[2].delta_line, 2);
assert_eq!(semantic_tokens.data[2].token_type, 6);
assert_eq!(semantic_tokens.data[3].length, 5);
assert_eq!(semantic_tokens.data[3].delta_start, 0);
assert_eq!(semantic_tokens.data[3].delta_line, 1);
assert_eq!(semantic_tokens.data[3].token_type, 4);
assert_eq!(semantic_tokens.data[4].length, 9);
assert_eq!(semantic_tokens.data[4].delta_start, 6);
assert_eq!(semantic_tokens.data[4].delta_line, 0);
assert_eq!(semantic_tokens.data[4].token_type, 1);
assert_eq!(semantic_tokens.data[5].length, 1);
assert_eq!(semantic_tokens.data[5].delta_start, 10);
assert_eq!(semantic_tokens.data[5].token_type, 2);
assert_eq!(semantic_tokens.data[6].length, 3);
assert_eq!(semantic_tokens.data[6].delta_start, 2);
assert_eq!(semantic_tokens.data[6].token_type, 0);
} else {
panic!("Expected semantic tokens");
}
}
#[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_document_symbol() {
let server = kcl_lsp_server(false).await.unwrap();
@ -1112,6 +1183,183 @@ async fn test_kcl_lsp_formatting() {
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_formatting_extra_parens() {
let server = kcl_lsp_server(false).await.unwrap();
// Send open file.
server
.did_open(tower_lsp::lsp_types::DidOpenTextDocumentParams {
text_document: tower_lsp::lsp_types::TextDocumentItem {
uri: "file:///test.kcl".try_into().unwrap(),
language_id: "kcl".to_string(),
version: 1,
text: r#"// Ball Bearing
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
// Define constants like ball diameter, inside diameter, overhange length, and thickness
const sphereDia = 0.5
const insideDia = 1
const thickness = 0.25
const overHangLength = .4
// Sketch and revolve the inside bearing piece
const insideRevolve = startSketchOn('XZ')
|> startProfileAt([insideDia / 2, 0], %)
|> line([0, thickness + sphereDia / 2], %)
|> line([overHangLength, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, -sphereDia], %)
|> line([overHangLength - thickness, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
const sphere = startSketchOn('XZ')
|> startProfileAt([
0.05 + insideDia / 2 + thickness,
0 - 0.05
], %)
|> line([sphereDia - 0.1, 0], %)
|> arc({
angle_start: 0,
angle_end: -180,
radius: sphereDia / 2 - 0.05
}, %)
|> close(%)
|> revolve({ axis: 'x' }, %)
|> patternCircular3d({
axis: [0, 0, 1],
center: [0, 0, 0],
repetitions: 10,
arcDegrees: 360,
rotateDuplicates: true
}, %)
// Sketch and revolve the outside bearing
const outsideRevolve = startSketchOn('XZ')
|> startProfileAt([
insideDia / 2 + thickness + sphereDia,
0
], %)
|> line([0, sphereDia / 2], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, thickness], %)
|> line([overHangLength, 0], %)
|> line([0, -2 * thickness - sphereDia], %)
|> line([-overHangLength, 0], %)
|> line([0, thickness], %)
|> line([overHangLength - thickness, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)"#
.to_string(),
},
})
.await;
server.wait_on_handle().await;
// Send formatting request.
let formatting = server
.formatting(tower_lsp::lsp_types::DocumentFormattingParams {
text_document: tower_lsp::lsp_types::TextDocumentIdentifier {
uri: "file:///test.kcl".try_into().unwrap(),
},
options: tower_lsp::lsp_types::FormattingOptions {
tab_size: 2,
insert_spaces: true,
properties: Default::default(),
trim_trailing_whitespace: None,
insert_final_newline: None,
trim_final_newlines: None,
},
work_done_progress_params: Default::default(),
})
.await
.unwrap()
.unwrap();
// Check the formatting.
assert_eq!(formatting.len(), 1);
assert_eq!(
formatting[0].range,
tower_lsp::lsp_types::Range {
start: tower_lsp::lsp_types::Position { line: 0, character: 0 },
end: tower_lsp::lsp_types::Position {
line: 60,
character: 30
}
}
);
assert_eq!(
formatting[0].new_text,
r#"// Ball Bearing
// A ball bearing is a type of rolling-element bearing that uses balls to maintain the separation between the bearing races. The primary purpose of a ball bearing is to reduce rotational friction and support radial and axial loads.
// Define constants like ball diameter, inside diameter, overhange length, and thickness
const sphereDia = 0.5
const insideDia = 1
const thickness = 0.25
const overHangLength = .4
// Sketch and revolve the inside bearing piece
const insideRevolve = startSketchOn('XZ')
|> startProfileAt([insideDia / 2, 0], %)
|> line([0, thickness + sphereDia / 2], %)
|> line([overHangLength, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, -sphereDia], %)
|> line([overHangLength - thickness, 0], %)
|> line([0, -thickness], %)
|> line([-overHangLength, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)
// Sketch and revolve one of the balls and duplicate it using a circular pattern. (This is currently a workaround, we have a bug with rotating on a sketch that touches the rotation axis)
const sphere = startSketchOn('XZ')
|> startProfileAt([
0.05 + insideDia / 2 + thickness,
0 - 0.05
], %)
|> line([sphereDia - 0.1, 0], %)
|> arc({
angle_start: 0,
angle_end: -180,
radius: sphereDia / 2 - 0.05
}, %)
|> close(%)
|> revolve({ axis: 'x' }, %)
|> patternCircular3d({
axis: [0, 0, 1],
center: [0, 0, 0],
repetitions: 10,
arcDegrees: 360,
rotateDuplicates: true
}, %)
// Sketch and revolve the outside bearing
const outsideRevolve = startSketchOn('XZ')
|> startProfileAt([
insideDia / 2 + thickness + sphereDia,
0
], %)
|> line([0, sphereDia / 2], %)
|> line([-overHangLength + thickness, 0], %)
|> line([0, thickness], %)
|> line([overHangLength, 0], %)
|> line([0, -2 * thickness - sphereDia], %)
|> line([-overHangLength, 0], %)
|> line([0, thickness], %)
|> line([overHangLength - thickness, 0], %)
|> close(%)
|> revolve({ axis: 'y' }, %)"#
);
}
#[tokio::test(flavor = "multi_thread")]
async fn test_kcl_lsp_rename() {
let server = kcl_lsp_server(false).await.unwrap();

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 128 KiB

After

Width:  |  Height:  |  Size: 128 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 124 KiB

After

Width:  |  Height:  |  Size: 124 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 109 KiB

After

Width:  |  Height:  |  Size: 109 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 125 KiB

After

Width:  |  Height:  |  Size: 125 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 126 KiB

After

Width:  |  Height:  |  Size: 126 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 138 KiB

After

Width:  |  Height:  |  Size: 139 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 131 KiB

After

Width:  |  Height:  |  Size: 131 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 122 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 129 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 132 KiB

After

Width:  |  Height:  |  Size: 132 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 113 KiB

After

Width:  |  Height:  |  Size: 108 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 140 KiB

After

Width:  |  Height:  |  Size: 140 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 136 KiB

After

Width:  |  Height:  |  Size: 136 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 123 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 211 KiB

After

Width:  |  Height:  |  Size: 211 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 112 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 137 KiB

After

Width:  |  Height:  |  Size: 137 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 112 KiB

After

Width:  |  Height:  |  Size: 111 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 117 KiB

After

Width:  |  Height:  |  Size: 117 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 87 KiB

After

Width:  |  Height:  |  Size: 87 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 195 KiB

After

Width:  |  Height:  |  Size: 195 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 251 KiB

After

Width:  |  Height:  |  Size: 250 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 150 KiB

After

Width:  |  Height:  |  Size: 150 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 147 KiB

After

Width:  |  Height:  |  Size: 147 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 167 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 168 KiB

After

Width:  |  Height:  |  Size: 168 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 127 KiB

After

Width:  |  Height:  |  Size: 127 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 115 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 143 KiB

After

Width:  |  Height:  |  Size: 143 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 133 KiB

After

Width:  |  Height:  |  Size: 133 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 134 KiB

After

Width:  |  Height:  |  Size: 134 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 135 KiB

After

Width:  |  Height:  |  Size: 135 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 155 KiB

After

Width:  |  Height:  |  Size: 154 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 104 KiB

After

Width:  |  Height:  |  Size: 104 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 115 KiB

After

Width:  |  Height:  |  Size: 114 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 107 KiB

After

Width:  |  Height:  |  Size: 107 KiB

Some files were not shown because too many files have changed in this diff Show More