Skip to content

Commit e3adbf6

Browse files
committed
implement copilot suggestions
1 parent 7c63181 commit e3adbf6

6 files changed

Lines changed: 93 additions & 12 deletions

File tree

src/SourceEditor.ts renamed to src/components/sourceEditor/SourceEditor.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import { Compartment } from '@codemirror/state'
33
import { EditorView } from '@codemirror/view'
44
import type { ThemeMode } from 'pane-registry'
5+
import { darkThemeExtension } from './themes/dark'
56

67
export class SourceEditor {
78
private _view: EditorView | null = null
@@ -41,7 +42,7 @@ export class SourceEditor {
4142
const state = EditorState.create({
4243
doc: initialDoc,
4344
extensions: [
44-
theme === 'dark' ? oneDark : [],
45+
theme === 'dark' ? darkThemeExtension : [],
4546
this._languageCompartment.of(languageExtension),
4647
this._editableCompartment.of(EditorView.editable.of(true)),
4748
syntaxHighlighting(defaultHighlightStyle, { fallback: true }),
@@ -62,6 +63,11 @@ export class SourceEditor {
6263
})
6364
}
6465

66+
destroy() {
67+
this._view?.destroy()
68+
this._view = null
69+
}
70+
6571
getValue(): string {
6672
return this._view ? this._view.state.doc.toString() : '';
6773
}

src/components/sourceEditor/SourceEditorCard.ts

Lines changed: 9 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ import { fetchContentAndMetadata, setUnedited } from '../../helpers'
66
import styles from './SourceEditorCard.styles.css'
77
import WebComponent from '../../primitives/WebComponent'
88
import { SourcePaneState } from '../../types'
9-
import { SourceEditor } from '../../SourceEditor'
9+
import { SourceEditor } from './SourceEditor'
1010
import { getStatusSection } from '../../StatusSection'
1111

1212
@customElement('source-editor-card')
1313
export default class SourceEditorCard extends WebComponent {
1414
static styles = styles
15-
private _editor!: SourceEditor
15+
private _editor?: SourceEditor
1616
private _editorMount = createRef<HTMLDivElement>()
1717

1818
@property({ attribute: false })
@@ -24,25 +24,26 @@ export default class SourceEditorCard extends WebComponent {
2424
@property({ attribute: false })
2525
accessor sourcePaneState!: SourcePaneState
2626

27-
private _getFileName (uri: string) {
27+
private _getFileName (uri?: string) {
28+
if (!uri) return ''
2829
const url = new URL(uri).pathname // remove #me and #this
2930
return url.substring(url.lastIndexOf('/') + 1)
3031
}
3132

3233
getValue () {
33-
return this._editor.getValue()
34+
return this._editor?.getValue()
3435
}
3536

3637
focusEditor () {
37-
this._editor.focusEditor()
38+
this._editor?.focusEditor()
3839
}
3940

4041
setReadOnly (readOnly: boolean) {
41-
this._editor.setReadOnly(readOnly)
42+
this._editor?.setReadOnly(readOnly)
4243
}
4344

4445
setValue (text: string) {
45-
this._editor.replaceContent(text)
46+
this._editor?.replaceContent(text)
4647
}
4748

4849
private async _initializeEditor () {
@@ -66,7 +67,7 @@ export default class SourceEditorCard extends WebComponent {
6667
disconnectedCallback() {
6768
super.disconnectedCallback()
6869
if (this._editor) {
69-
// this._editor.destroy?.() need to write a destroy method.
70+
this._editor.destroy()
7071
this._editor = undefined
7172
}
7273
}
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
import { EditorView } from '@codemirror/view';
2+
import { HighlightStyle, syntaxHighlighting } from '@codemirror/language'
3+
import { tags as t } from '@lezer/highlight';
4+
5+
/* The base styles were copied from google
6+
highlighting was modified to fit our design and needs */
7+
const darkTheme = EditorView.theme({
8+
// Targets the outermost editor container
9+
'&': {
10+
color: '#e0e0e0',
11+
backgroundColor: '#1e1e1e',
12+
height: '100%'
13+
},
14+
15+
// Targets the active editing area where text lives
16+
'.cm-content': {
17+
caretColor: '#ff0055', // Custom cursor color
18+
fontFamily: 'monospace'
19+
},
20+
21+
// Targets the line that the cursor is currently on
22+
'.cm-activeLine': {
23+
backgroundColor: '#2a2a2a'
24+
},
25+
26+
// Targets the line numbers sidebar panel
27+
'.cm-gutters': {
28+
backgroundColor: '#1e1e1e',
29+
color: '#858585',
30+
border: 'none'
31+
},
32+
33+
// Targets the active line number specifically
34+
'.cm-activeLineGutter': {
35+
color: '#fff',
36+
backgroundColor: '#2a2a2a'
37+
},
38+
39+
// Targets text highlighted/selected by the user
40+
'.cm-selectionBackground, ::selection': {
41+
backgroundColor: '#3e4451 !important'
42+
}
43+
}, { dark: true })
44+
45+
const darkHighlightStyle = HighlightStyle.define([
46+
{ tag: t.keyword, color: '#FFFF8A', fontWeight: 'bold' },
47+
{ tag: t.string, color: '#FF5CFF' },
48+
{ tag: t.comment, color: '#6272a4', fontStyle: 'italic' },
49+
{ tag: t.function(t.variableName), color: '#50fa7b' },
50+
{ tag: t.variableName, color: '#f8f8f2' },
51+
{ tag: t.number, color: '#bd93f9' },
52+
{ tag: t.integer, color: '#bd93f9' },
53+
{ tag: t.float, color: '#bd93f9' },
54+
{ tag: t.url, color: '#FFFF00'},
55+
{ tag: t.className, color: '#ff5555' },
56+
{ tag: t.namespace, color: '#9b59b6' },
57+
{ tag: t.meta, color: '#c678dd' },
58+
{ tag: t.propertyName, color: '#00D100' },
59+
{ tag: t.unit, color: '#9b59b6'},
60+
{ tag: t.punctuation, color: '#ffffff' },
61+
{ tag: t.literal, color: '#f1fa8c' },
62+
{ tag: t.docString, color: '#6272a4', fontStyle: 'italic' },
63+
{ tag: t.processingInstruction, color: '#ffffff' },
64+
{ tag: t.angleBracket, color: '#f65353' },
65+
{ tag: t.tagName, color: '#f65353' },
66+
{ tag: t.attributeName, color: '#66d9ef' },
67+
])
68+
69+
export const darkThemeExtension = [
70+
darkTheme,
71+
syntaxHighlighting(darkHighlightStyle)
72+
]

src/helpers.ts

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -140,9 +140,10 @@ export function setUnedited (subject: NamedNode, sourcePaneState: SourcePaneStat
140140
const saveButton = document.querySelector('.sourcePaneSaveButton') as HTMLElement
141141
const myEditButton = document.querySelector('.sourcePaneEditButton') as HTMLElement
142142
const myCompactButton = document.querySelector('.sourcePaneCompactButton') as HTMLElement
143-
const { broken, contentType } = sourcePaneState
143+
const { broken, contentType, allowed } = sourcePaneState
144144
if (broken) return
145-
setControlVisible(myEditButton, !subject.uri.endsWith('/'))
145+
const canEdit = !subject.uri.endsWith('/') && (!allowed || allowed.includes('PUT'))
146+
setControlVisible(myEditButton, canEdit)
146147
setControlVisible(saveButton, false)
147148
setControlVisible(myCompactButton, !!(contentType && compactable[contentType.split(';')[0]]))
148149
editorCard?.setReadOnly(true)

test/helpers.test.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,7 @@ describe('helpers', () => {
9696

9797
expect(editorCard.setReadOnly).toHaveBeenCalledWith(true)
9898
expect(saveButton.className).toContain('sourcePaneControlHidden')
99-
expect(editButton.className).toContain('sourcePaneControlVisible')
99+
expect(editButton.className).toContain('sourcePaneControlHidden')
100100
expect(compactButton.className).toContain('sourcePaneControlVisible')
101101
})
102102
})

test/sourceEditorCard.test.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ jest.mock('../src/components/sourceEditor/SourceEditor', () => {
1111
focusEditor: jest.fn(),
1212
setReadOnly: jest.fn(),
1313
replaceContent: jest.fn(),
14+
destroy: jest.fn(),
1415
})),
1516
}
1617
})

0 commit comments

Comments
 (0)