Extend grammar markup style continued
This commit is contained in:
parent
53fc05a2f8
commit
bb822f0bbc
18
Readme.md
18
Readme.md
@ -87,6 +87,24 @@ Kategorije pravopisnih pravil so:
|
|||||||
| BESANA_CAT_5 | slovnične napake |
|
| BESANA_CAT_5 | slovnične napake |
|
||||||
| BESANA_CAT_6 | nomotehnične napake (potrebuje posebno licenco) |
|
| BESANA_CAT_6 | nomotehnične napake (potrebuje posebno licenco) |
|
||||||
|
|
||||||
|
### 4. Nastavljanje videza korekturnih znamenj
|
||||||
|
|
||||||
|
Privzeto servis uporablja podčrtovanje pravopisnih napak (nastavitev `'underline'`). Videz lahko spreminjamo.
|
||||||
|
|
||||||
|
<img src="samples/markup_underline.png" alt="underline" width="448"/>
|
||||||
|
<img src="samples/markup_lector.png" alt="lector" width="448"/>
|
||||||
|
|
||||||
|
Levo `'underline'`, desno `'lector'`.
|
||||||
|
|
||||||
|
Primer:
|
||||||
|
|
||||||
|
```JavaScript
|
||||||
|
// Registriramo servis za naš urejevalnik.
|
||||||
|
BesService
|
||||||
|
.registerByElement(el)
|
||||||
|
.setMarkupStyle('lector')
|
||||||
|
```
|
||||||
|
|
||||||
## Navodila za razvijalce
|
## Navodila za razvijalce
|
||||||
|
|
||||||
Programsko kodo v tem repozitoriju razvijamo s programom Visual Studio Code. Potrebna je namestitev vtičnika `esbenp.prettier-vscode`.
|
Programsko kodo v tem repozitoriju razvijamo s programom Visual Studio Code. Potrebna je namestitev vtičnika `esbenp.prettier-vscode`.
|
||||||
|
BIN
samples/markup_lector.png
Normal file
BIN
samples/markup_lector.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 174 KiB |
BIN
samples/markup_underline.png
Normal file
BIN
samples/markup_underline.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 151 KiB |
504
service.js
504
service.js
@ -362,50 +362,36 @@ class BesService {
|
|||||||
*/
|
*/
|
||||||
addMistakeMarkup(match) {
|
addMistakeMarkup(match) {
|
||||||
const range = match.range
|
const range = match.range
|
||||||
const ruleId = match.match.rule.id
|
|
||||||
const scrollPanelRect = this.scrollPanel.getBoundingClientRect()
|
const scrollPanelRect = this.scrollPanel.getBoundingClientRect()
|
||||||
const dpr = window.devicePixelRatio
|
const scrollX = scrollPanelRect.left
|
||||||
const markerX = this.canvasPanel.width * dpr
|
const scrollY = scrollPanelRect.top
|
||||||
match.highlights = Array.from(range.getClientRects())
|
match.highlights = Array.from(range.getClientRects())
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
this.ctx.lineWidth = 2 * dpr // Use 2 for clearer visibility
|
this.ctx.lineWidth = 2 * dpr // Use 2 for clearer visibility
|
||||||
|
const ruleId = match.match.rule.id
|
||||||
this.ctx.strokeStyle = ruleId.startsWith('MORFOLOGIK_RULE')
|
this.ctx.strokeStyle = ruleId.startsWith('MORFOLOGIK_RULE')
|
||||||
? 'rgba(255, 115, 0, 0.5)'
|
? 'rgba(0, 123, 255, 0.8)'
|
||||||
: 'rgba(0, 123, 255, 0.5)'
|
: 'rgba(255, 115, 0, 0.8)'
|
||||||
const drawSideMarker = (y1, y2) => {
|
this.ctx.fillStyle = ruleId.startsWith('MORFOLOGIK_RULE')
|
||||||
this.ctx.beginPath()
|
? 'rgba(0, 123, 255, 0.8)'
|
||||||
this.ctx.moveTo(markerX, y1 * dpr)
|
: 'rgba(255, 115, 0, 0.8)'
|
||||||
this.ctx.lineTo(markerX, y2 * dpr)
|
let markerY1, markerY2
|
||||||
this.ctx.stroke()
|
|
||||||
}
|
|
||||||
switch (this.markupStyle) {
|
switch (this.markupStyle) {
|
||||||
case 'lector':
|
case 'lector':
|
||||||
if (match.match.replacements && match.match.replacements.length) {
|
if (ruleId === 'BESANA_6' /*PR_VNAP_V_STAVKU_MANJKA_VEJICA*/) {
|
||||||
const drawMissingComma = (x, y) => {
|
// Thou we should draw ┘ after the word before match.match.offset, if there is a line break inbetween,
|
||||||
this.ctx.beginPath()
|
// the correction markup would be drawn in one line and the highlight rectangle for onClick would reside
|
||||||
this.ctx.moveTo((x - 2) * dpr, y * dpr)
|
// in another line, making a confusing UX.
|
||||||
this.ctx.lineTo((x + 2) * dpr, y * dpr)
|
markerY1 = match.highlights[0].top
|
||||||
this.ctx.lineTo((x + 2) * dpr, (y - 4) * dpr)
|
markerY2 = match.highlights[0].bottom
|
||||||
this.ctx.stroke()
|
const scale = (markerY2 - markerY1) / 18
|
||||||
}
|
const x = match.highlights[0].left
|
||||||
const drawWrongSpacing = (x, y1, y2) => {
|
const y = match.highlights[0].bottom
|
||||||
this.ctx.beginPath()
|
this.drawMissingComma(x - scrollX, y - scrollY, scale, '?')
|
||||||
this.ctx.moveTo((x - 4) * dpr, (y1 + 4) * dpr)
|
break
|
||||||
this.ctx.lineTo(x * dpr, y1 * dpr)
|
|
||||||
this.ctx.lineTo((x + 4) * dpr, (y1 + 4) * dpr)
|
|
||||||
this.ctx.moveTo(x * dpr, y1 * dpr)
|
|
||||||
this.ctx.lineTo(x * dpr, y2 * dpr)
|
|
||||||
this.ctx.moveTo((x - 4) * dpr, (y2 - 4) * dpr)
|
|
||||||
this.ctx.lineTo(x * dpr, y2 * dpr)
|
|
||||||
this.ctx.lineTo((x + 4) * dpr, (y2 - 4) * dpr)
|
|
||||||
this.ctx.stroke()
|
|
||||||
}
|
|
||||||
const drawExcessiveText = (x1, y1, x2, y2) => {
|
|
||||||
this.ctx.beginPath()
|
|
||||||
this.ctx.moveTo(x1 * dpr, y1 * dpr)
|
|
||||||
this.ctx.lineTo(x2 * dpr, y2 * dpr)
|
|
||||||
this.ctx.stroke()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (match.match.replacements && match.match.replacements.length === 1) {
|
||||||
const context = match.match.context.text.substr(
|
const context = match.match.context.text.substr(
|
||||||
match.match.context.offset,
|
match.match.context.offset,
|
||||||
match.match.context.length
|
match.match.context.length
|
||||||
@ -418,52 +404,81 @@ class BesService {
|
|||||||
) {
|
) {
|
||||||
// Something to insert before
|
// Something to insert before
|
||||||
const toInsert = replacement.substr(0, lengthDiff)
|
const toInsert = replacement.substr(0, lengthDiff)
|
||||||
|
markerY1 = match.highlights[0].top
|
||||||
|
markerY2 = match.highlights[0].bottom
|
||||||
|
const scale = (markerY2 - markerY1) / 18
|
||||||
|
|
||||||
if (toInsert === ',') {
|
if (toInsert === ',') {
|
||||||
const x = match.highlights[0].left - scrollPanelRect.left
|
// Thou we should draw ┘ after the word before match.match.offset, if there is a line break inbetween,
|
||||||
const y = match.highlights[0].bottom - scrollPanelRect.top
|
// the correction markup would be drawn in one line and the highlight rectangle for onClick would reside
|
||||||
drawMissingComma(x, y)
|
// in another line, making a confusing UX.
|
||||||
|
const x = match.highlights[0].left
|
||||||
|
const y = match.highlights[0].bottom
|
||||||
|
this.drawMissingComma(x - scrollX, y - scrollY, scale)
|
||||||
} else if (/^\s+$/.test(toInsert)) {
|
} else if (/^\s+$/.test(toInsert)) {
|
||||||
const x = match.highlights[0].left - scrollPanelRect.left
|
const x = match.highlights[0].left
|
||||||
const y1 = match.highlights[0].bottom - scrollPanelRect.top - 2
|
const y1 = match.highlights[0].bottom - 2 * scale
|
||||||
const y2 = match.highlights[0].top - scrollPanelRect.top + 2
|
const y2 = match.highlights[0].top + 2 * scale
|
||||||
drawWrongSpacing(x, y1, y2)
|
this.drawWrongSpacing(
|
||||||
} else {
|
x - scrollX,
|
||||||
// TODO
|
y1 - scrollY,
|
||||||
}
|
y2 - scrollY,
|
||||||
|
scale
|
||||||
drawSideMarker(
|
|
||||||
match.highlights[0].top - scrollPanelRect.top,
|
|
||||||
match.highlights[0].bottom - scrollPanelRect.top
|
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
const x = match.highlights[0].left - 1 * scale
|
||||||
|
const y1 = match.highlights[0].bottom
|
||||||
|
const y2 = match.highlights[0].top
|
||||||
|
this.drawMissingText(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale,
|
||||||
|
replacement.substr(lengthDiff).trim()
|
||||||
|
)
|
||||||
|
}
|
||||||
} else if (replacement.substr(0, context.length) === context) {
|
} else if (replacement.substr(0, context.length) === context) {
|
||||||
// Something to insert after
|
// Something to insert after
|
||||||
const toInsert = replacement.substr(-lengthDiff)
|
const toInsert = replacement.substr(-lengthDiff)
|
||||||
|
markerY1 = match.highlights.at(-1).top
|
||||||
|
markerY2 = match.highlights.at(-1).bottom
|
||||||
|
const scale = (markerY2 - markerY1) / 18
|
||||||
|
|
||||||
if (toInsert === ',') {
|
if (toInsert === ',') {
|
||||||
const x = match.highlights.at(-1).right - scrollPanelRect.left
|
const x = match.highlights.at(-1).right
|
||||||
const y = match.highlights.at(-1).bottom - scrollPanelRect.top
|
const y = match.highlights.at(-1).bottom
|
||||||
drawMissingComma(x, y)
|
this.drawMissingComma(x - scrollX, y - scrollY, scale)
|
||||||
} else if (/^\s+$/.test(toInsert)) {
|
} else if (/^\s+$/.test(toInsert)) {
|
||||||
const x = match.highlights.at(-1).right - scrollPanelRect.left
|
const x = match.highlights.at(-1).right
|
||||||
const y1 =
|
const y1 = match.highlights.at(-1).bottom - 2 * scale
|
||||||
match.highlights.at(-1).bottom - scrollPanelRect.top - 2
|
const y2 = match.highlights.at(-1).top + 2 * scale
|
||||||
const y2 = match.highlights.at(-1).top - scrollPanelRect.top + 2
|
this.drawWrongSpacing(
|
||||||
drawWrongSpacing(x, y1, y2)
|
x - scrollX,
|
||||||
} else {
|
y1 - scrollY,
|
||||||
// TODO
|
y2 - scrollY,
|
||||||
}
|
scale
|
||||||
|
|
||||||
drawSideMarker(
|
|
||||||
match.highlights.at(-1).top - scrollPanelRect.top,
|
|
||||||
match.highlights.at(-1).bottom - scrollPanelRect.top
|
|
||||||
)
|
)
|
||||||
|
} else {
|
||||||
|
const x = match.highlights.at(-1).right + 1 * scale
|
||||||
|
const y1 = match.highlights.at(-1).bottom
|
||||||
|
const y2 = match.highlights.at(-1).top
|
||||||
|
this.drawMissingText(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale,
|
||||||
|
replacement.substr(-lengthDiff).trim()
|
||||||
|
)
|
||||||
|
}
|
||||||
} else if (
|
} else if (
|
||||||
lengthDiff < 0 &&
|
lengthDiff < 0 &&
|
||||||
context.substr(-replacement.length) === replacement
|
context.substr(-replacement.length) === replacement
|
||||||
) {
|
) {
|
||||||
// Something to remove before
|
// Something to remove before
|
||||||
const toRemove = context.substr(0, -lengthDiff)
|
const toRemove = context.substr(0, -lengthDiff)
|
||||||
|
markerY1 = match.highlights[0].top
|
||||||
|
markerY2 = match.highlights[0].bottom
|
||||||
|
const scale = (markerY2 - markerY1) / 18
|
||||||
|
|
||||||
if (/^\s+$/.test(toRemove)) {
|
if (/^\s+$/.test(toRemove)) {
|
||||||
const rect = this.makeRange(
|
const rect = this.makeRange(
|
||||||
@ -471,31 +486,34 @@ class BesService {
|
|||||||
match.match.offset,
|
match.match.offset,
|
||||||
match.match.offset - lengthDiff
|
match.match.offset - lengthDiff
|
||||||
)?.getClientRects()[0]
|
)?.getClientRects()[0]
|
||||||
const x = (rect.left + rect.right) / 2 - scrollPanelRect.left
|
const x = (rect.left + rect.right) / 2
|
||||||
const y1 = rect.top - scrollPanelRect.top
|
const y1 = rect.top
|
||||||
const y2 = rect.bottom - scrollPanelRect.top
|
const y2 = rect.bottom
|
||||||
drawWrongSpacing(x, y1, y2)
|
this.drawWrongSpacing(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
for (let rect of this.makeRange(
|
for (let rect of this.makeRange(
|
||||||
match.data,
|
match.data,
|
||||||
match.match.offset,
|
match.match.offset,
|
||||||
match.match.offset - lengthDiff
|
match.match.offset - lengthDiff
|
||||||
)?.getClientRects())
|
)?.getClientRects())
|
||||||
drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollPanelRect.left,
|
rect.left - scrollX,
|
||||||
rect.bottom - scrollPanelRect.top,
|
rect.bottom - scrollY,
|
||||||
rect.right - scrollPanelRect.left,
|
rect.right - scrollX,
|
||||||
rect.top - scrollPanelRect.top
|
rect.top - scrollY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
drawSideMarker(
|
|
||||||
match.highlights[0].top - scrollPanelRect.top,
|
|
||||||
match.highlights[0].bottom - scrollPanelRect.top
|
|
||||||
)
|
|
||||||
} else if (context.substr(0, replacement.length) === replacement) {
|
} else if (context.substr(0, replacement.length) === replacement) {
|
||||||
// Something to remove after
|
// Something to remove after
|
||||||
const toRemove = context.substr(lengthDiff)
|
const toRemove = context.substr(lengthDiff)
|
||||||
|
markerY1 = match.highlights.at(-1).top
|
||||||
|
markerY2 = match.highlights.at(-1).bottom
|
||||||
|
const scale = (markerY2 - markerY1) / 18
|
||||||
|
|
||||||
if (/^\s+$/.test(toRemove)) {
|
if (/^\s+$/.test(toRemove)) {
|
||||||
const rect = this.makeRange(
|
const rect = this.makeRange(
|
||||||
@ -503,86 +521,308 @@ class BesService {
|
|||||||
match.match.offset + match.match.length + lengthDiff,
|
match.match.offset + match.match.length + lengthDiff,
|
||||||
match.match.offset + match.match.length
|
match.match.offset + match.match.length
|
||||||
)?.getClientRects()[0]
|
)?.getClientRects()[0]
|
||||||
const x = (rect.left + rect.right) / 2 - scrollPanelRect.left
|
const x = (rect.left + rect.right) / 2
|
||||||
const y1 = rect.top - scrollPanelRect.top
|
const y1 = rect.top
|
||||||
const y2 = rect.bottom - scrollPanelRect.top
|
const y2 = rect.bottom
|
||||||
drawWrongSpacing(x, y1, y2)
|
this.drawWrongSpacing(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale
|
||||||
|
)
|
||||||
} else {
|
} else {
|
||||||
for (let rect of this.makeRange(
|
for (let rect of this.makeRange(
|
||||||
match.data,
|
match.data,
|
||||||
match.match.offset + match.match.length + lengthDiff,
|
match.match.offset + match.match.length + lengthDiff,
|
||||||
match.match.offset + match.match.length
|
match.match.offset + match.match.length
|
||||||
)?.getClientRects())
|
)?.getClientRects())
|
||||||
drawExcessiveText(
|
this.drawExcessiveText(
|
||||||
rect.left - scrollPanelRect.left,
|
rect.left - scrollX,
|
||||||
rect.bottom - scrollPanelRect.top,
|
rect.bottom - scrollY,
|
||||||
rect.right - scrollPanelRect.left,
|
rect.right - scrollX,
|
||||||
rect.top - scrollPanelRect.top
|
rect.top - scrollY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
drawSideMarker(
|
|
||||||
match.highlights.at(-1).top - scrollPanelRect.top,
|
|
||||||
match.highlights.at(-1).bottom - scrollPanelRect.top
|
|
||||||
)
|
|
||||||
} else {
|
} else {
|
||||||
// Sugesstion and context are different.
|
// Sugesstion and context are different.
|
||||||
// TODO
|
const lengthL = BesService.commonPrefixLength(context, replacement)
|
||||||
|
const lengthR = BesService.commonSuffixLength(context, replacement)
|
||||||
|
if (
|
||||||
|
lengthL + lengthR <
|
||||||
|
Math.min(context.length, replacement.length) * 0.6
|
||||||
|
) {
|
||||||
|
// Replace everything.
|
||||||
|
markerY1 = Math.min(...match.highlights.map(rect => rect.top))
|
||||||
|
markerY2 = Math.max(...match.highlights.map(rect => rect.bottom))
|
||||||
|
const scale =
|
||||||
|
(match.highlights[0].bottom - match.highlights[0].top) / 18
|
||||||
|
let first = true
|
||||||
|
for (let rect of match.highlights) {
|
||||||
|
if (first) {
|
||||||
|
this.drawWrongText(
|
||||||
|
rect.left - scrollX,
|
||||||
|
rect.bottom - scrollY,
|
||||||
|
rect.right - scrollX,
|
||||||
|
rect.top - scrollY,
|
||||||
|
scale,
|
||||||
|
replacement
|
||||||
|
)
|
||||||
|
first = false
|
||||||
|
} else {
|
||||||
|
this.drawExcessiveText(
|
||||||
|
rect.left - scrollX,
|
||||||
|
rect.bottom - scrollY,
|
||||||
|
rect.right - scrollX,
|
||||||
|
rect.top - scrollY
|
||||||
|
)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
// Patch differences.
|
||||||
|
const rects = Array.from(
|
||||||
|
this.makeRange(
|
||||||
|
match.data,
|
||||||
|
match.match.offset + lengthL,
|
||||||
|
match.match.offset + match.match.length - lengthR
|
||||||
|
)?.getClientRects()
|
||||||
|
)
|
||||||
|
markerY1 = Math.min(...rects.map(rect => rect.top))
|
||||||
|
markerY2 = Math.max(...rects.map(rect => rect.bottom))
|
||||||
|
|
||||||
drawSideMarker(
|
if (lengthL + lengthR === context.length) {
|
||||||
Math.min(...match.highlights.map(rect => rect.top)) -
|
// Something to insert
|
||||||
scrollPanelRect.top,
|
const toInsert = replacement.substring(
|
||||||
Math.max(...match.highlights.map(rect => rect.bottom)) -
|
lengthL,
|
||||||
scrollPanelRect.top
|
replacement.length - lengthR
|
||||||
|
)
|
||||||
|
const scale = (rects[0].bottom - rects[0].top) / 18
|
||||||
|
const x = rects[0].left
|
||||||
|
|
||||||
|
if (/^\s+$/.test(toInsert)) {
|
||||||
|
const y1 = rects[0].bottom - 2 * scale
|
||||||
|
const y2 = rects[0].top + 2 * scale
|
||||||
|
this.drawWrongSpacing(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
const y1 = rects[0].bottom
|
||||||
|
const y2 = rects[0].top
|
||||||
|
this.drawMissingText(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale,
|
||||||
|
toInsert.trim()
|
||||||
|
)
|
||||||
|
}
|
||||||
|
} else if (lengthL + lengthR === replacement.length) {
|
||||||
|
// Something to remove
|
||||||
|
const toRemove = context.substring(
|
||||||
|
lengthL,
|
||||||
|
replacement.length - lengthR
|
||||||
|
)
|
||||||
|
const scale = (rects[0].bottom - rects[0].top) / 18
|
||||||
|
|
||||||
|
if (/^\s+$/.test(toRemove)) {
|
||||||
|
const x = (rects[0].left + rects[0].right) / 2
|
||||||
|
const y1 = rects[0].top
|
||||||
|
const y2 = rects[0].bottom
|
||||||
|
this.drawWrongSpacing(
|
||||||
|
x - scrollX,
|
||||||
|
y1 - scrollY,
|
||||||
|
y2 - scrollY,
|
||||||
|
scale
|
||||||
|
)
|
||||||
|
} else {
|
||||||
|
for (let rect of rects)
|
||||||
|
this.drawExcessiveText(
|
||||||
|
rect.left - scrollX,
|
||||||
|
rect.bottom - scrollY,
|
||||||
|
rect.right - scrollX,
|
||||||
|
rect.top - scrollY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// TODO
|
// Something to replace
|
||||||
|
const toReplace = replacement.substring(
|
||||||
drawSideMarker(
|
lengthL,
|
||||||
Math.min(...match.highlights.map(rect => rect.top)) -
|
replacement.length - lengthR
|
||||||
scrollPanelRect.top,
|
)
|
||||||
Math.max(...match.highlights.map(rect => rect.bottom)) -
|
const scale = (rects[0].bottom - rects[0].top) / 18
|
||||||
scrollPanelRect.top
|
let first = true
|
||||||
|
for (let rect of rects) {
|
||||||
|
if (first) {
|
||||||
|
this.drawWrongText(
|
||||||
|
rect.left - scrollX,
|
||||||
|
rect.bottom - scrollY,
|
||||||
|
rect.right - scrollX,
|
||||||
|
rect.top - scrollY,
|
||||||
|
scale,
|
||||||
|
toReplace
|
||||||
|
)
|
||||||
|
first = false
|
||||||
|
} else {
|
||||||
|
this.drawExcessiveText(
|
||||||
|
rect.left - scrollX,
|
||||||
|
rect.bottom - scrollY,
|
||||||
|
rect.right - scrollX,
|
||||||
|
rect.top - scrollY
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
}
|
||||||
// for (let rect of match.highlights) {
|
}
|
||||||
// const x = (rect.left - scrollPanelRect.left) * dpr
|
}
|
||||||
// const y = (rect.top - scrollPanelRect.top) * dpr
|
}
|
||||||
// const width = rect.width * dpr
|
|
||||||
// const height = rect.height * dpr
|
|
||||||
|
|
||||||
// // MOCKUP text drawing
|
|
||||||
// this.ctx.font = `5px ${this.textFont}` // Font se lahko doda na sledeč način: `25px 'Times New Roman', serif`
|
|
||||||
// const text = 'To je izmišljeno besedilo'
|
|
||||||
// const textLength = this.ctx.measureText(text)
|
|
||||||
// console.log(`Dolžina texta: ${textLength.width}px`) // Dolžina texta
|
|
||||||
// this.ctx.fillText(text, x, y)
|
|
||||||
// }
|
|
||||||
break
|
break
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
for (let rect of match.highlights) {
|
for (let rect of match.highlights) {
|
||||||
const x = (rect.left - scrollPanelRect.left) * dpr
|
const x1 = rect.left
|
||||||
const y = (rect.top - scrollPanelRect.top) * dpr
|
const x2 = rect.right
|
||||||
const width = rect.width * dpr
|
const y = rect.bottom
|
||||||
const height = rect.height * dpr
|
const scale = (rect.bottom - rect.top) / 18
|
||||||
|
this.drawAttentionRequired(
|
||||||
|
x1 - scrollX,
|
||||||
|
x2 - scrollX,
|
||||||
|
y - scrollY,
|
||||||
|
scale
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
// Draw the underline.
|
markerY1 = Math.min(...match.highlights.map(rect => rect.top))
|
||||||
|
markerY2 = Math.max(...match.highlights.map(rect => rect.bottom))
|
||||||
|
}
|
||||||
|
|
||||||
|
this.drawSideMarker(markerY1 - scrollY, markerY2 - scrollY)
|
||||||
|
}
|
||||||
|
|
||||||
|
static commonPrefixLength(s1, s2) {
|
||||||
|
let i = 0
|
||||||
|
let len = Math.min(s1.length, s2.length)
|
||||||
|
while (i < len && s1[i] === s2[i]) i++
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
static commonSuffixLength(s1, s2) {
|
||||||
|
let i = 0
|
||||||
|
let i1 = s1.length
|
||||||
|
let i2 = s2.length
|
||||||
|
while (0 < i1-- && 0 < i2-- && s1[i1] === s2[i2]) i++
|
||||||
|
return i
|
||||||
|
}
|
||||||
|
|
||||||
|
drawSideMarker(y1, y2) {
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
const markerX = this.canvasPanel.width - 5 * dpr
|
||||||
this.ctx.beginPath()
|
this.ctx.beginPath()
|
||||||
this.ctx.moveTo(x, y + height)
|
this.ctx.moveTo(markerX, y1 * dpr)
|
||||||
this.ctx.lineTo(x + width, y + height)
|
this.ctx.lineTo(markerX, y2 * dpr)
|
||||||
this.ctx.stroke()
|
this.ctx.stroke()
|
||||||
}
|
}
|
||||||
|
|
||||||
drawSideMarker(
|
drawMissingComma(x, y, scale, comment) {
|
||||||
Math.min(...match.highlights.map(rect => rect.top)) -
|
const dpr = window.devicePixelRatio
|
||||||
scrollPanelRect.top,
|
this.ctx.beginPath()
|
||||||
Math.max(...match.highlights.map(rect => rect.bottom)) -
|
this.ctx.moveTo((x - 2 * scale) * dpr, y * dpr)
|
||||||
scrollPanelRect.top
|
this.ctx.lineTo((x + 2 * scale) * dpr, y * dpr)
|
||||||
|
this.ctx.lineTo((x + 2 * scale) * dpr, (y - 4 * scale) * dpr)
|
||||||
|
this.ctx.stroke()
|
||||||
|
|
||||||
|
if (comment) {
|
||||||
|
this.ctx.font = `${12 * scale * dpr}px ${this.textFont}`
|
||||||
|
this.ctx.textAlign = 'center'
|
||||||
|
this.ctx.textBaseline = 'bottom'
|
||||||
|
this.ctx.fillText('?', (x + 2 * scale) * dpr, (y - 6 * scale) * dpr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
drawWrongSpacing(x, y1, y2, scale) {
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
this.ctx.beginPath()
|
||||||
|
this.ctx.moveTo((x - 4 * scale) * dpr, (y1 + 4 * scale) * dpr)
|
||||||
|
this.ctx.lineTo(x * dpr, y1 * dpr)
|
||||||
|
this.ctx.lineTo((x + 4 * scale) * dpr, (y1 + 4 * scale) * dpr)
|
||||||
|
this.ctx.moveTo(x * dpr, y1 * dpr)
|
||||||
|
this.ctx.lineTo(x * dpr, y2 * dpr)
|
||||||
|
this.ctx.moveTo((x - 4 * scale) * dpr, (y2 - 4 * scale) * dpr)
|
||||||
|
this.ctx.lineTo(x * dpr, y2 * dpr)
|
||||||
|
this.ctx.lineTo((x + 4 * scale) * dpr, (y2 - 4 * scale) * dpr)
|
||||||
|
this.ctx.stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
drawExcessiveText(x1, y1, x2, y2) {
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
this.ctx.beginPath()
|
||||||
|
this.ctx.moveTo(x1 * dpr, y1 * dpr)
|
||||||
|
this.ctx.lineTo(x2 * dpr, y2 * dpr)
|
||||||
|
this.ctx.stroke()
|
||||||
|
}
|
||||||
|
|
||||||
|
drawWrongText(x1, y1, x2, y2, scale, text) {
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
this.ctx.beginPath()
|
||||||
|
this.ctx.moveTo(x1 * dpr, (y1 - 6 * scale) * dpr)
|
||||||
|
this.ctx.lineTo(x2 * dpr, (y2 + 6 * scale) * dpr)
|
||||||
|
this.ctx.stroke()
|
||||||
|
|
||||||
|
this.ctx.font = `${12 * scale * dpr}px ${this.textFont}`
|
||||||
|
this.ctx.textAlign = 'left' // Thou we want the text to be centered, we align it manually to prevent it getting off canvas.
|
||||||
|
this.ctx.textBaseline = 'bottom'
|
||||||
|
const textMetrics = this.ctx.measureText(text)
|
||||||
|
this.ctx.fillText(
|
||||||
|
text,
|
||||||
|
Math.max(
|
||||||
|
Math.min(
|
||||||
|
((x1 + x2) / 2) * dpr - textMetrics.width / 2,
|
||||||
|
this.canvasPanel.width - textMetrics.width
|
||||||
|
),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
(y2 + 6 * scale) * dpr
|
||||||
)
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
drawMissingText(x, y1, y2, scale, text) {
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
this.ctx.beginPath()
|
||||||
|
this.ctx.moveTo((x - 6 * scale) * dpr, y1 * dpr)
|
||||||
|
this.ctx.lineTo((x + 6 * scale) * dpr, y1 * dpr)
|
||||||
|
this.ctx.moveTo(x * dpr, y1 * dpr)
|
||||||
|
this.ctx.lineTo(x * dpr, (y2 + 6 * scale) * dpr)
|
||||||
|
this.ctx.stroke()
|
||||||
|
|
||||||
|
this.ctx.font = `${12 * scale * dpr}px ${this.textFont}`
|
||||||
|
this.ctx.textAlign = 'left' // Thou we want the text to be centered, we align it manually to prevent it getting off canvas.
|
||||||
|
this.ctx.textBaseline = 'bottom'
|
||||||
|
const textMetrics = this.ctx.measureText(text)
|
||||||
|
this.ctx.fillText(
|
||||||
|
text,
|
||||||
|
Math.max(
|
||||||
|
Math.min(
|
||||||
|
x * dpr - textMetrics.width / 2,
|
||||||
|
this.canvasPanel.width - textMetrics.width
|
||||||
|
),
|
||||||
|
0
|
||||||
|
),
|
||||||
|
(y2 + 6 * scale) * dpr
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
drawAttentionRequired(x1, x2, y, scale) {
|
||||||
|
const dpr = window.devicePixelRatio
|
||||||
|
this.ctx.beginPath()
|
||||||
|
this.ctx.moveTo(x1 * dpr, (y - scale) * dpr)
|
||||||
|
for (let x = x1; ; ) {
|
||||||
|
if (x >= x2) break
|
||||||
|
this.ctx.lineTo((x += 2 * scale) * dpr, (y + scale) * dpr)
|
||||||
|
if (x >= x2) break
|
||||||
|
this.ctx.lineTo((x += 2 * scale) * dpr, (y - scale) * dpr)
|
||||||
|
}
|
||||||
|
this.ctx.stroke()
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -15,11 +15,11 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
.bes-highlight-spelling-rect {
|
.bes-highlight-spelling-rect {
|
||||||
background: rgb(255, 115, 0);
|
background: rgb(0, 123, 255);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bes-highlight-grammar-rect {
|
.bes-highlight-grammar-rect {
|
||||||
background: rgb(0, 123, 255);
|
background: rgb(255, 115, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
.bes-canvas {
|
.bes-canvas {
|
||||||
|
Loading…
x
Reference in New Issue
Block a user