Skip to content

Commit

Permalink
Merge pull request #2400 from codecrafters-io/code-mirror/demo-pages-…
Browse files Browse the repository at this point in the history
…cleanup

Cleanup and unify CodeMirror Demo pages
  • Loading branch information
VasylMarchuk authored Nov 19, 2024
2 parents 3a94ecc + ab780ac commit 9c86ba4
Show file tree
Hide file tree
Showing 9 changed files with 396 additions and 168 deletions.
81 changes: 2 additions & 79 deletions app/controllers/demo/code-mirror.ts
Original file line number Diff line number Diff line change
Expand Up @@ -5,29 +5,7 @@ import { tracked } from '@glimmer/tracking';
import { type Extension } from '@codemirror/state';
import type DarkModeService from 'codecrafters-frontend/services/dark-mode';
import { codeCraftersDark, codeCraftersLight } from 'codecrafters-frontend/utils/code-mirror-themes';

class ExampleDocument {
@tracked document!: string;
@tracked originalDocument!: string;
@tracked filename!: string;
@tracked language!: string;
constructor({
document,
originalDocument,
filename,
language,
}: {
document: string;
originalDocument?: string;
filename: string;
language: string;
}) {
this.document = document;
this.originalDocument = originalDocument || document;
this.filename = filename;
this.language = language;
}
}
import EXAMPLE_DOCUMENTS, { ExampleDocument } from 'codecrafters-frontend/utils/code-mirror-documents';

const THEME_EXTENSIONS: {
[key: string]: Extension;
Expand All @@ -50,61 +28,6 @@ const LINE_SEPARATORS = [
{ name: '\\r', symbol: '\r' },
];

const EXAMPLE_DOCUMENTS = [
new ExampleDocument({
document:
'An example plain-text document 1\nAn example plain-text document 2\nAn example plain-text document 3\nAn example plain-text document 4\nAn example plain-text document 5\nAn example plain-text document 6\nAn example plain-text document 7\nAn example plain-text document NEW LINE\nAn example plain-text document 8\nAn example plain-text document 9\nNEW LINE\nAn example plain-text document 10\nAn example plain-text document 11\nAn example plain-text document 12\nAn example plain-text document 13\nAn example plain-text document 14\nAn example plain-text document 15\nAn example plain-text document 16\nAn example plain-text document 17\nAn example plain-text document 18\nAn example plain-text document 19\nAn example plain-text document 20\nAn example plain-text document 21\nAn example plain-text document NEW LINE\nAn example plain-text document 22\nAn example plain-text document 23\nAn example plain-text document 24\nAn example plain-text MODIFIED document 25\nAn example plain-text document 26\nAn example plain-text document 27\nAn example plain-text document 28\nAn example plain-text document 29\nAn example plain-text document 30\nAn example plain-text document 31\nAn example plain-text document 32\nAn example plain-text document 33\nAn example plain-text document 34\nAn example plain-text document 35',
originalDocument:
'An example plain-text document 1\nAn example plain-text document 2\nAn example plain-text document 3\nAn example plain-text document 4\nAn example plain-text document 5\nAn example plain-text document 6\nAn example plain-text document 7\nAn example plain-text document 8\nAn example plain-text document 9\nAn example plain-text document 10\nAn example plain-text document 11\nAn example plain-text document 12\nAn example plain-text document 13\nAn example plain-text document 14\nAn example plain-text document 15\nAn example plain-text document 16\nAn example plain-text document 17\nAn example plain-text document 18\nAn example plain-text document 19\nAn example plain-text document 20\nAn example plain-text document 21\nAn example plain-text document 22\nAn example plain-text document 23\nAn example plain-text document 24\nAn example plain-text document 25\nAn example plain-text document 26\nAn example plain-text document 27\nAn example plain-text document 28\nAn example plain-text document 29\nAn example plain-text document 30\nAn example plain-text document 31\nAn example plain-text document 32\nAn example plain-text document 33\nAn example plain-text document 34\nAn example plain-text document 35',
filename: 'test.txt',
language: 'text',
}),
new ExampleDocument({
document:
"// Some comment\n\nvar x = function functionName() { return `test ${abc}`; };\n\nconst LONG_CONSTANT = \"A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. \";\n\n/**\n * Useful comment about method foo()\n * Some trailing whitespace: \n * Tab charachers: \t\t\t ≪—— here\n * Some invisible characters: ‎‎‎ ≪—— here\n*/\n\nasync function foo() {\n var x = 1;\n alert('123' + x);\n}\n\nasync function fooTwo() {\n var x = 1;\n alert('123' + x);\n}\n\nasync function fooThree() {\n var x = 1;\n alert('123' + x);\n}\n",
originalDocument:
'// Some comment\n\nvar x = function functionName() { return `test ${abc}`; };\n\n/**\n *Completely irrelevant comment\n*/\n\nconst SOME_CONSTANT = "A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. ";\n\n/**\n * Un-useful comment about method foo()\n * More information about the method\n*/\n\nasync function foo() {\n var x = 1;\n alert("123" + x);\n}\n\nasync function fooTwo() {\n var x = 1;\n alert("123" + x);\n}\n\nasync function fooThree() {\n var x = 1;\n alert("123" + x);\n}\n',
filename: 'test.js',
language: 'javascript',
}),
new ExampleDocument({
document: '<html>\n\t<body>\n\t\tAn example HTML document\n\t\tWith an invisible -> ‎ <- characer\n\t</body>\n</html>',
originalDocument: '<html><body>An example HTML document</body></html>',
filename: 'test.html',
language: 'html',
}),
new ExampleDocument({
document:
'# Assign a numeric value\nnumber = 70\n\n# Check the value is more than 70 or not\nif (number >= 70):\n\tprint("You have passed")\nelse:\n\tprint("You have not passed")',
originalDocument:
'# Assign a numeric value\nnumber = 70\n\n# Check the is more than 70 or not\nif (number >= 70):\n\tprint("They have passed")\nelse:\n\tprint("They have not passed")',
filename: 'test.py',
language: 'python',
}),
new ExampleDocument({
document:
'-- Table: customer\nCREATE TABLE customer (\n\tid int NOT NULL IDENTITY(1, 1),\n\tcustomer_name varchar(255) NOT NULL,\n\tcity_id int NOT NULL,\n\tcustomer_address varchar(255) NOT NULL,\n\tnext_call_date date NULL,\n\tts_inserted datetime NOT NULL,\n\tCONSTRAINT customer_pk PRIMARY KEY (id)\n);\n\n-- Table: customer_backup3\nCREATE TABLE customer_backup3 (\n\tid int NOT NULL IDENTITY(1, 1),\n\tcustomer_name varchar(255) NOT NULL,\n\tcity_id int NOT NULL,\n\tcustomer_address varchar(255) NOT NULL,\n\tnext_call_date date NULL,\n\tts_inserted datetime NOT NULL,\n\tCONSTRAINT customer_pk PRIMARY KEY (id)\n);\n\n-- Extra comment\n-- Extra comment\n-- Extra comment\n-- Extra comment\n-- Extra comment\n\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment',
originalDocument:
'-- Table: customer\nCREATE TABLE customer (\n\tid int NOT NULL IDENTITY(1, 1),\n\tcustomer_name varchar(255) NOT NULL,\n\tcity_id int NOT NULL,\n\tcustomer_address varchar(255) NOT NULL,\n\tnext_call_date date NULL,\n\tts_inserted datetime NOT NULL,\n\tCONSTRAINT customer_pk PRIMARY KEY (id)\n);\n\n-- Table: customer_backup\nCREATE TABLE customer_backup (\n\tid int NOT NULL IDENTITY(1, 1),\n\tcustomer_name varchar(255) NOT NULL,\n\tcity_id int NOT NULL,\n\tcustomer_address varchar(255) NOT NULL,\n\tnext_call_date date NULL,\n\tts_inserted datetime NOT NULL,\n\tCONSTRAINT customer_pk PRIMARY KEY (id)\n);\n\n-- Table: customer_backup3\nCREATE TABLE customer_backup3 (\n\tid int NOT NULL IDENTITY(1, 1),\n\tcustomer_name varchar(255) NOT NULL,\n\tcity_id int NOT NULL,\n\tcustomer_address varchar(255) NOT NULL,\n\tnext_call_date date NULL,\n\tts_inserted datetime NOT NULL,\n\tCONSTRAINT customer_pk PRIMARY KEY (id)\n);\n\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment\n-- Unchanged comment',
filename: 'test.sql',
language: 'sql',
}),
new ExampleDocument({
document:
"# Example Markdown document\n### Another header\n###### Another header\n-----------\n__Bold text__\n_Italic text_\n\nThis in a example document with code snippets\n\n```ts\nfunction myTestFunction({ world = 'world' } : { world!: string } = {}) {\n return window.confirm(`Hello ${world}!`)\n}\n```\n\n```html\n<body>\n <head></head>\n</body>\n```",
originalDocument: '### Example Markdown document',
filename: 'test.md',
language: 'markdown',
}),
new ExampleDocument({
document:
'# syntax=docker/dockerfile:1.7-labs\nFROM mcr.microsoft.com/dotnet/sdk:8.0-alpine\n\nWORKDIR /app\n\n# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses\nCOPY --exclude=.git --exclude=README.md . /app\n\n# This saves nuget packages to ~/.nuget\nRUN dotnet build --configuration Release .\n\n# This seems to cause a caching issue with the dotnet build command, where old contents are used\n# TODO: See if this needs to be brought back?\n# RUN rm -rf /app/obj\n# RUN rm -rf /app/bin\n\nRUN echo "cd \\${CODECRAFTERS_SUBMISSION_DIR} && dotnet build --configuration Release ." > /codecrafters-precompile.sh\nRUN chmod +x /codecrafters-precompile.sh\n\nENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="codecrafters-redis.csproj,codecrafters-redis.sln"\n\n# Once the heavy steps are done, we can copy all files back\nCOPY . /app\n\n',
originalDocument: '# syntax=docker/dockerfile:1.7-labs\n',
filename: 'Dockerfile',
language: 'dockerfile',
}),
];

const OPTION_DEFAULTS = {
allowMultipleSelections: true,
autocompletion: true,
Expand Down Expand Up @@ -268,7 +191,7 @@ export default class DemoCodeMirrorController extends Controller {
@tracked unchangedMinSizes = [1, 2, 3, 4, 5, 8, 16];

get selectedDocument() {
return this.documents[this.selectedDocumentIndex];
return this.documents[this.selectedDocumentIndex] || ExampleDocument.createEmpty();
}

get selectedIndentUnit() {
Expand Down
81 changes: 22 additions & 59 deletions app/controllers/demo/file-contents-card.ts
Original file line number Diff line number Diff line change
@@ -1,73 +1,36 @@
import Controller from '@ember/controller';
import { action } from '@ember/object';
import { tracked } from '@glimmer/tracking';
import EXAMPLE_DOCUMENTS, { ExampleDocument } from 'codecrafters-frontend/utils/code-mirror-documents';

class ExampleDocument {
@tracked document: string;
@tracked filename: string;
@tracked language: string;
constructor({ document, filename, language }: { document: string; filename: string; language: string }) {
this.document = document;
this.filename = filename;
this.language = language;
}
}
const OPTION_DEFAULTS = {
foldGutter: true,
headerTooltipText: false,
isCollapsed: false,
isCollapsible: false,
scrollIntoViewOnCollapse: true,
selectedDocumentIndex: 1,
};

export default class DemoFileContentsCardController extends Controller {
@tracked documents: ExampleDocument[] = [
new ExampleDocument({
document: 'An example plain-text document',
filename: 'test.txt',
language: 'text',
}),
new ExampleDocument({
document:
"// Some comment\n\nvar x = function functionName() { return `test ${abc}`; };\n\nconst LONG_CONSTANT = \"A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. A very long constant. \";\n\n/**\n * Useful comment about method foo()\n * Some trailing whitespace: \n * Tab charachers: \t\t\t ≪—— here\n * Some invisible characters: ‎‎‎ ≪—— here\n*/\n\nasync function foo() {\n var x = 1;\n alert('123' + x);\n}\n\nasync function fooTwo() {\n var x = 1;\n alert('123' + x);\n}\n\nasync function fooThree() {\n var x = 1;\n alert('123' + x);\n}\n",
filename: 'test.js',
language: 'javascript',
}),
new ExampleDocument({
document: '<html>\n\t<body>\n\t\tAn example HTML document\n\t\tWith an invisible -> ‎ <- characer\n\t</body>\n</html>',
filename: 'test.html',
language: 'html',
}),
new ExampleDocument({
document:
'# Assign a numeric value\nnumber = 70\n\n# Check the value is more than 70 or not\nif (number >= 70):\n\tprint("You have passed")\nelse:\n\tprint("You have not passed")',
filename: 'test.py',
language: 'python',
}),
new ExampleDocument({
document:
'-- Table: customer\nCREATE TABLE customer (\n\tid int NOT NULL IDENTITY(1, 1),\n\tcustomer_name varchar(255) NOT NULL,\n\tcity_id int NOT NULL,\n\tcustomer_address varchar(255) NOT NULL,\n\tnext_call_date date NULL,\n\tts_inserted datetime NOT NULL,\n\tCONSTRAINT customer_pk PRIMARY KEY (id)\n);',
filename: 'test.sql',
language: 'sql',
}),
new ExampleDocument({
document:
"# Example Markdown document\n### Another header\n###### Another header\n-----------\n__Bold text__\n_Italic text_\n\nThis in a example document with code snippets\n\n```ts\nfunction myTestFunction({ world = 'world' } : { world!: string } = {}) {\n return window.confirm(`Hello ${world}!`)\n}\n```\n\n```html\n<body>\n <head></head>\n</body>\n```",
filename: 'test.md',
language: 'markdown',
}),
new ExampleDocument({
document:
'# syntax=docker/dockerfile:1.7-labs\nFROM mcr.microsoft.com/dotnet/sdk:8.0-alpine\n\nWORKDIR /app\n\n# .git & README.md are unique per-repository. We ignore them on first copy to prevent cache misses\nCOPY --exclude=.git --exclude=README.md . /app\n\n# This saves nuget packages to ~/.nuget\nRUN dotnet build --configuration Release .\n\n# This seems to cause a caching issue with the dotnet build command, where old contents are used\n# TODO: See if this needs to be brought back?\n# RUN rm -rf /app/obj\n# RUN rm -rf /app/bin\n\nRUN echo "cd \\${CODECRAFTERS_SUBMISSION_DIR} && dotnet build --configuration Release ." > /codecrafters-precompile.sh\nRUN chmod +x /codecrafters-precompile.sh\n\nENV CODECRAFTERS_DEPENDENCY_FILE_PATHS="codecrafters-redis.csproj,codecrafters-redis.sln"\n\n# Once the heavy steps are done, we can copy all files back\nCOPY . /app\n\n',
filename: 'Dockerfile',
language: 'dockerfile',
}),
];
queryParams = ['foldGutter', 'headerTooltipText', 'isCollapsed', 'isCollapsible', 'scrollIntoViewOnCollapse', 'selectedDocumentIndex'];

@tracked selectedDocumentIndex: number = 1;
@tracked documents: ExampleDocument[] = EXAMPLE_DOCUMENTS;

@tracked foldGutter: boolean = OPTION_DEFAULTS.foldGutter;
@tracked headerTooltipText: boolean = OPTION_DEFAULTS.headerTooltipText;
@tracked isCollapsed: boolean = OPTION_DEFAULTS.isCollapsed;
@tracked isCollapsible: boolean = OPTION_DEFAULTS.isCollapsible;
@tracked scrollIntoViewOnCollapse: boolean = OPTION_DEFAULTS.scrollIntoViewOnCollapse;
@tracked selectedDocumentIndex: number = OPTION_DEFAULTS.selectedDocumentIndex;

get selectedDocument() {
return this.documents[this.selectedDocumentIndex] || new ExampleDocument({ document: '', filename: 'unknown.txt', language: 'text' });
return this.documents[this.selectedDocumentIndex] || ExampleDocument.createEmpty();
}

@tracked isCollapsible: boolean = false;
@tracked isCollapsed: boolean = false;
@tracked scrollIntoViewOnCollapse: boolean = true;
@tracked headerTooltipText: boolean = false;
@tracked foldGutter: boolean = true;
@action resetAllOptions() {
Object.assign(this, OPTION_DEFAULTS);
}

@action selectedDocumentIndexDidChange(event: Event) {
const target: HTMLSelectElement = event.target as HTMLSelectElement;
Expand Down
22 changes: 2 additions & 20 deletions app/helpers/diff-to-document.ts
Original file line number Diff line number Diff line change
@@ -1,26 +1,8 @@
import { helper } from '@ember/component/helper';
import parseDiffAsDocument from 'codecrafters-frontend/utils/parse-diff-as-document';

const diffToDocument = helper(function diffToDocument([diff = '']: [string | undefined]) {
const diffLines = diff.split('\n');

const current = [];
const original = [];

for (const line of diffLines) {
if (line.startsWith('-')) {
original.push(line.substring(1));
} else if (line.startsWith('+')) {
current.push(line.substring(1));
} else {
original.push(line.substring(1));
current.push(line.substring(1));
}
}

return {
current: current.join('\n'),
original: original.join('\n'),
};
return parseDiffAsDocument(diff);
});

export default diffToDocument;
Expand Down
16 changes: 15 additions & 1 deletion app/routes/demo/file-contents-card.ts
Original file line number Diff line number Diff line change
@@ -1,3 +1,17 @@
import Route from '@ember/routing/route';

export default class DemoFileContentsCardRoute extends Route {}
const QUERY_PARAMS = ['foldGutter', 'headerTooltipText', 'isCollapsed', 'isCollapsible', 'scrollIntoViewOnCollapse', 'selectedDocumentIndex'];

interface QueryParamOptions {
[key: string]: {
replace: boolean;
};
}

export default class DemoFileContentsCardRoute extends Route {
queryParams = QUERY_PARAMS.reduce<QueryParamOptions>((acc, param) => {
acc[param] = { replace: true };

return acc;
}, {});
}
16 changes: 8 additions & 8 deletions app/templates/demo.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -20,24 +20,24 @@
>CodeMirror</span>
</LinkTo>
<LinkTo
@route="demo.dark-mode-toggle"
@route="demo.file-contents-card"
role="button"
class="flex flex-shrink-0 items-center px-3 py-2 mr-2 border-b-2 text-sm
{{if (eq this.router.currentRouteName 'demo.dark-mode-toggle') 'border-teal-500' 'border-gray-100 dark:border-gray-700'}}"
{{if (eq this.router.currentRouteName 'demo.file-contents-card') 'border-teal-500' 'border-gray-100 dark:border-gray-700'}}"
>
<span
class={{if (eq this.router.currentRouteName "demo.dark-mode-toggle") "font-medium text-teal-500" "text-gray-600 dark:text-gray-200"}}
>DarkModeToggle</span>
class={{if (eq this.router.currentRouteName "demo.file-contents-card") "font-medium text-teal-500" "text-gray-600 dark:text-gray-200"}}
>FileContentsCard</span>
</LinkTo>
<LinkTo
@route="demo.file-contents-card"
@route="demo.dark-mode-toggle"
role="button"
class="flex flex-shrink-0 items-center px-3 py-2 mr-2 border-b-2 text-sm
{{if (eq this.router.currentRouteName 'demo.file-contents-card') 'border-teal-500' 'border-gray-100 dark:border-gray-700'}}"
{{if (eq this.router.currentRouteName 'demo.dark-mode-toggle') 'border-teal-500' 'border-gray-100 dark:border-gray-700'}}"
>
<span
class={{if (eq this.router.currentRouteName "demo.file-contents-card") "font-medium text-teal-500" "text-gray-600 dark:text-gray-200"}}
>FileContentsCard</span>
class={{if (eq this.router.currentRouteName "demo.dark-mode-toggle") "font-medium text-teal-500" "text-gray-600 dark:text-gray-200"}}
>DarkModeToggle</span>
</LinkTo>
</div>

Expand Down
10 changes: 9 additions & 1 deletion app/templates/demo/file-contents-card.hbs
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,15 @@
@foldGutter={{this.foldGutter}}
@onExpand={{fn (mut this.isCollapsed) false}}
@onCollapse={{fn (mut this.isCollapsed) true}}
class="my-4"
class="mt-4"
/>

<div class="my-2 text-right">
<span
role="button"
class="text-xs text-blue-600 hover:text-blue-800 dark:text-blue-200 dark:hover:text-blue-400 underline cursor-pointer"
{{on "click" this.resetAllOptions}}
>Reset all options</span>
</div>

{{outlet}}
Loading

0 comments on commit 9c86ba4

Please sign in to comment.