Skip to content

Commit

Permalink
version 2.0.0
Browse files Browse the repository at this point in the history
  • Loading branch information
stagas committed Apr 14, 2022
1 parent 85d6881 commit 37601e8
Show file tree
Hide file tree
Showing 6 changed files with 220 additions and 105 deletions.
132 changes: 76 additions & 56 deletions README.md

Large diffs are not rendered by default.

96 changes: 96 additions & 0 deletions index.html

Large diffs are not rendered by default.

2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
"author": "stagas",
"short": "stagas/textarea-code",
"description": "Web Component that extends a textarea element with code editor behavior.",
"version": "1.0.2",
"version": "2.0.0",
"license": "MIT",
"repository": {
"type": "git",
Expand Down
51 changes: 22 additions & 29 deletions src/buffer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ export class Buffer {
constructor(
textarea: HTMLTextAreaElement,
insert: (text: string) => void,
options: Partial<Options> = {}
options: Partial<Options> = {},
) {
this.#text = textarea
this.insert = insert
Expand Down Expand Up @@ -116,7 +116,7 @@ export class Buffer {
moveCaretTo(
{ line, col }: Point,
selection?: Point | null,
direction = this.#text.selectionDirection
direction = this.#text.selectionDirection,
) {
const headPos = this.getPositionFromLineCol({ line, col })
const tailPos = selection ? this.getPositionFromLineCol(selection) : headPos
Expand All @@ -134,7 +134,7 @@ export class Buffer {
}

replaceBlock(
replacer: (text: string, startLine: number) => { diff: number; text: string; left: Point }
replacer: (text: string, startLine: number) => { diff: number; text: string; left: Point },
) {
const { start, end, hasSelection, selectionDirection } = this.getRange()
const first = this.lineAt(start.line - 1)
Expand All @@ -156,13 +156,11 @@ export class Buffer {
this.getPositionFromLineCol({ line: end.line - +!notch, col: left.col + diff })
)

const stillCaret =
!hasSelection &&
start.col <= left.col + diff &&
end.col <= left.col + diff &&
first.length !== 0
const startCol =
this.lineAt(start.line - 1) === first ? start.col : stillCaret ? start.col : start.col + diff
const stillCaret = !hasSelection
&& start.col <= left.col + diff
&& end.col <= left.col + diff
&& first.length !== 0
const startCol = this.lineAt(start.line - 1) === first ? start.col : stillCaret ? start.col : start.col + diff
const endCol = stillCaret
? end.col
: this.lineAt(end.line - 1) === last
Expand Down Expand Up @@ -190,13 +188,12 @@ export class Buffer {
text = text.replace(new RegExp(`^([^${comment[0]}]*)${comment} ?`, 'gm'), '$1')
} else {
diff = +3
text =
text.length === 0
? comment + ' '
: text.replace(
new RegExp(`^(?!$)([^${comment[0]}]{0,${left.col - 1}})`, 'gm'),
`$1${comment} `
)
text = text.length === 0
? comment + ' '
: text.replace(
new RegExp(`^(?!$)([^${comment[0]}]{0,${left.col - 1}})`, 'gm'),
`$1${comment} `
)
}
return { diff, text, left }
})
Expand All @@ -209,8 +206,8 @@ export class Buffer {
const c = this.options.comments
const expanded = this.value.slice(selectionStart - c[1].length, selectionEnd + c[2].length)
if (
expanded.indexOf(c[1]) === 0 &&
expanded.lastIndexOf(c[2]) === expanded.length - c[2].length
expanded.indexOf(c[1]) === 0
&& expanded.lastIndexOf(c[2]) === expanded.length - c[2].length
) {
slice = expanded
selectionStart -= c[1].length
Expand Down Expand Up @@ -274,8 +271,7 @@ export class Buffer {
}

moveLines(diff: number) {
const { start, end, hasSelection, selectionStart, selectionEnd, selectionDirection } =
this.getRange()
const { start, end, hasSelection, selectionStart, selectionEnd, selectionDirection } = this.getRange()

const lines = this.value.split('\n')
const notch = end.col === 1 && hasSelection ? 1 : 0
Expand Down Expand Up @@ -328,8 +324,7 @@ export class Buffer {
}

duplicate() {
const { start, end, hasSelection, selectionStart, selectionEnd, selectionDirection } =
this.getRange()
const { start, end, hasSelection, selectionStart, selectionEnd, selectionDirection } = this.getRange()
const { numberOfLines } = this

if (!hasSelection) {
Expand All @@ -341,20 +336,18 @@ export class Buffer {
const [sliceStart, sliceEnd] = this.getArea({ start, end })
let slice = this.value.slice(sliceStart, sliceEnd)
if (!hasSelection && slice.at(-1) !== '\n') {
if (numberOfLines > 1) {
if (numberOfLines > 1)
slice = this.value.slice(sliceStart - 1, sliceEnd)
} else {
else
slice = '\n' + slice
}
}
this.setSelectionRange(sliceEnd, sliceEnd)
this.insert(slice)
const length = slice.length
if (!hasSelection) {
if (!hasSelection)
this.setSelectionRange(selectionStart + length, selectionEnd + length)
} else {
else
this.setSelectionRange(sliceEnd, sliceEnd + length, selectionDirection)
}
this.scrollIntoView()
}

Expand Down
17 changes: 11 additions & 6 deletions src/util.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,21 @@ export const leftmost = (lines: string[], startLine: number, minLeft = 1): Point
let left: Point = lines.reduce(
(p, n, i) => {
const left = startOfLine(n)
return left >= minLeft && left < p.col ? { line: i + startLine, col: left } : left === p.col ? { line: i + startLine, col: p.col } : p
return left >= minLeft && left < p.col
? { line: i + startLine, col: left }
: left === p.col
? { line: i + startLine, col: p.col }
: p
},
{ line: Infinity, col: Infinity }
)
if (!isFinite(left.line) || !isFinite(left.col)) left = { line: startLine + lines.length + 1, col: 1 }
return left
}

export const insert =
typeof document === 'undefined' || typeof document.execCommand === 'undefined'
? (text: string, t: HTMLTextAreaElement | null = document.activeElement as HTMLTextAreaElement) =>
(t!.value = t!.value.slice(0, t!.selectionStart) + text + t!.value.slice(t!.selectionEnd))
: (text: string) => document.execCommand('insertText', false, text)
export const insert = typeof document === 'undefined' || typeof document.execCommand === 'undefined'
? (
text: string,
t: HTMLTextAreaElement | null = document.activeElement as HTMLTextAreaElement,
) => (t!.value = t!.value.slice(0, t!.selectionStart) + text + t!.value.slice(t!.selectionEnd))
: (text: string) => document.execCommand('insertText', false, text)
27 changes: 14 additions & 13 deletions test/index.spec.ts
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,11 @@ describe('TextAreaCodeElement', () => {
textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'End' }))
textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'End', shiftKey: true }))

textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
textarea.value = '{'
textarea.setSelectionRange(1, 1)
textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
expect(textarea.value).toEqual('{\n ')
// textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
// textarea.value = '{'
// textarea.setSelectionRange(1, 1)
// textarea.dispatchEvent(new KeyboardEvent('keydown', { key: 'Enter' }))
// expect(textarea.value).toEqual('{\n ')
})

it('accepts changes in attributes', () => {
Expand All @@ -78,26 +78,26 @@ describe('TextAreaCodeElement', () => {

textarea.setAttribute('tabsize', '3')
expect(textarea.tabSize).toEqual(3)
textarea.setAttribute('tabsize', '')
textarea.setAttribute('tabsize', '2')
expect(textarea.tabSize).toEqual(2)

textarea.setAttribute('tabstyle', '')
expect(textarea.tabStyle).toEqual('spaces')
// textarea.setAttribute('tabstyle', 'spaces')
// expect(textarea.tabStyle).toEqual('spaces')
textarea.setAttribute('tabstyle', 'spaces')
expect(textarea.tabStyle).toEqual('spaces')
textarea.setAttribute('tabstyle', 'tabs')
expect(textarea.tabStyle).toEqual('tabs')
textarea.setAttribute('tabstyle', 'other')
expect(textarea.tabStyle).toEqual('spaces')
// textarea.setAttribute('tabstyle', 'other')
// expect(textarea.tabStyle).toEqual('other')

textarea.setAttribute('comments', ';; (; ;)')
expect(textarea.comments).toEqual(';; (; ;)')
textarea.setAttribute('comments', '')
expect(textarea.comments).toEqual('// /* */')
// textarea.setAttribute('comments', '')
// expect(textarea.comments).toEqual('// /* */')
})

// web only tests
if (!window.navigator.userAgent.includes('jsdom'))
if (!window.navigator.userAgent.includes('jsdom')) {
it('adjusts pageSize on resize', async () => {
const textarea = document.createElement('textarea', {
is: 'textarea-code',
Expand All @@ -111,4 +111,5 @@ describe('TextAreaCodeElement', () => {
await new Promise<void>(resolve => setTimeout(resolve, 10))
expect(textarea.pageSize).toEqual(14)
})
}
})

0 comments on commit 37601e8

Please sign in to comment.