Skip to content

Commit

Permalink
implement code highlighting interface,, remove prismjs and highlight.…
Browse files Browse the repository at this point in the history
…js references
  • Loading branch information
Totto16 committed Apr 20, 2024
1 parent dd931d0 commit 900bf0d
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 207 deletions.
6 changes: 4 additions & 2 deletions src/components/codePanoItem.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,11 @@ import { markupCode } from '@pano/utils/pango';
export class CodePanoItem extends PanoItem {
private codeItemSettings: Gio.Settings;
private label: St.Label;
private language: string;

constructor(ext: ExtensionBase, clipboardManager: ClipboardManager, dbItem: DBItem) {
constructor(ext: ExtensionBase, clipboardManager: ClipboardManager, dbItem: DBItem, language: string) {
super(ext, clipboardManager, dbItem);
this.language = language;
this.codeItemSettings = this.settings.get_child('code-item');

this.label = new St.Label({
Expand All @@ -41,7 +43,7 @@ export class CodePanoItem extends PanoItem {
this.body.set_style(`background-color: ${bodyBgColor}`);
this.label.set_style(`font-size: ${bodyFontSize}px; font-family: ${bodyFontFamily};`);

this.label.clutterText.set_markup(markupCode(this.dbItem.content.trim(), characterLength));
this.label.clutterText.set_markup(markupCode(this.language, this.dbItem.content.trim()));
}

private setClipboardContent(): void {
Expand Down
115 changes: 13 additions & 102 deletions src/utils/pango.ts
Original file line number Diff line number Diff line change
@@ -1,109 +1,20 @@
import { logger } from '@pano/utils/shell';
import PrismJS from 'prismjs';

const debug = logger('pango');

const INVISIBLE_SPACE = '​';

const CLASS_NAMES = [
{ classNames: 'comment', fgcolor: '#636f88' },
{ classNames: 'prolog', fgcolor: '#636f88' },
{ classNames: 'doctype', fgcolor: '#636f88' },
{ classNames: 'cdata', fgcolor: '#636f88' },
{ classNames: 'punctuation', fgcolor: '#81A1C1' },
{ classNames: 'interpolation-punctuation', fgcolor: '#81A1C1' },
{ classNames: 'template-punctuation', fgcolor: '#81A1C1' },
{ classNames: 'property', fgcolor: '#81A1C1' },
{ classNames: 'string-property', fgcolor: '#81A1C1' },
{ classNames: 'parameter', fgcolor: '#81A1C1' },
{ classNames: 'literal-property', fgcolor: '#81A1C1' },
{ classNames: 'tag', fgcolor: '#81A1C1' },
{ classNames: 'constant', fgcolor: '#81A1C1' },
{ classNames: 'symbol', fgcolor: '#81A1C1' },
{ classNames: 'deleted', fgcolor: '#81A1C1' },
{ classNames: 'number', fgcolor: '#B48EAD' },
{ classNames: 'boolean', fgcolor: '#81A1C1' },
{ classNames: 'selector', fgcolor: '#A3BE8C' },
{ classNames: 'attr-name', fgcolor: '#A3BE8C' },
{ classNames: 'string', fgcolor: '#A3BE8C' },
{ classNames: 'template-string', fgcolor: '#A3BE8C' },
{ classNames: 'char', fgcolor: '#A3BE8C' },
{ classNames: 'builtin', fgcolor: '#A3BE8C' },
{ classNames: 'interpolation', fgcolor: '#A3BE8C' },
{ classNames: 'inserted', fgcolor: '#A3BE8C' },
{ classNames: 'operator', fgcolor: '#81A1C1' },
{ classNames: 'entity', fgcolor: '#81A1C1' },
{ classNames: 'url', fgcolor: '#81A1C1' },
{ classNames: 'variable', fgcolor: '#81A1C1' },
{ classNames: 'function-variable', fgcolor: '#81A1C1' },
{ classNames: 'atrule', fgcolor: '#88C0D0' },
{ classNames: 'attr-value', fgcolor: '#88C0D0' },
{ classNames: 'function', fgcolor: '#88C0D0' },
{ classNames: 'class-name', fgcolor: '#88C0D0' },
{ classNames: 'keyword', fgcolor: '#81A1C1' },
{ classNames: 'regex', fgcolor: '#EBCB8B' },
{ classNames: 'regex-delimiter', fgcolor: '#EBCB8B' },
{ classNames: 'regex-source', fgcolor: '#EBCB8B' },
{ classNames: 'regex-flags', fgcolor: '#EBCB8B' },
{ classNames: 'important', fgcolor: '#EBCB8B' },
];

const getColor = (classNames: string): string => {
const item = CLASS_NAMES.find((n) => classNames === n.classNames);

if (!item) {
debug(`class names not found: ${classNames}`);
return '#fff';
}

return item.fgcolor;
};

type Env = {
type: string;
content: string;
tag: string;
classes: string[];
attributes: Record<string, string>;
export type Language = {
relevance: number;
language: string;
};

const stringify = (o: string | PrismJS.TokenStream, language: string) => {
if (typeof o == 'string') {
return o;
}
if (Array.isArray(o)) {
let s = '';
o.forEach(function (e) {
s += stringify(e, language);
});
return s;
}

const env: Env = {
type: o.type,
content: stringify(o.content, language),
tag: 'span',
classes: [o.type],
attributes: {},
language: language,
};

let attributes = '';
for (const name in env.attributes) {
attributes += ` ${name}="${(env.attributes[name] || '').replace(/"/g, '&quot;')}"`;
}

return `<${env.tag} fgcolor="${getColor(env.classes.join(' '))}" ${attributes}>${env.content}</${env.tag}>`;
};

export const markupCode = (text: string, charLength: number): string => {
const result =
INVISIBLE_SPACE +
stringify(
PrismJS.util.encode(PrismJS.tokenize(text.slice(0, charLength), PrismJS.languages['javascript']!)),
'javascript',
);

return result;
};
export function detectLanguage(text: string): Language | undefined {
//TODO: implement language detection
debug('TODO');
return undefined;
}

export function markupCode(language: string, text: string): string {
//TODO implement code highlighting
debug('TODO');
return '';
}
158 changes: 55 additions & 103 deletions src/utils/panoItemFactory.ts
Original file line number Diff line number Diff line change
Expand Up @@ -26,92 +26,16 @@ import {
} from '@pano/utils/shell';
import { notify } from '@pano/utils/ui';
import convert from 'hex-color-converter';
import hljs from 'highlight.js/lib/core';
import bash from 'highlight.js/lib/languages/bash';
import c from 'highlight.js/lib/languages/c';
import cpp from 'highlight.js/lib/languages/cpp';
import csharp from 'highlight.js/lib/languages/csharp';
import dart from 'highlight.js/lib/languages/dart';
import go from 'highlight.js/lib/languages/go';
import groovy from 'highlight.js/lib/languages/groovy';
import haskell from 'highlight.js/lib/languages/haskell';
import java from 'highlight.js/lib/languages/java';
import javascript from 'highlight.js/lib/languages/javascript';
import julia from 'highlight.js/lib/languages/julia';
import kotlin from 'highlight.js/lib/languages/kotlin';
import lua from 'highlight.js/lib/languages/lua';
import markdown from 'highlight.js/lib/languages/markdown';
import perl from 'highlight.js/lib/languages/perl';
import php from 'highlight.js/lib/languages/php';
import python from 'highlight.js/lib/languages/python';
import ruby from 'highlight.js/lib/languages/ruby';
import rust from 'highlight.js/lib/languages/rust';
import scala from 'highlight.js/lib/languages/scala';
import shell from 'highlight.js/lib/languages/shell';
import sql from 'highlight.js/lib/languages/sql';
import swift from 'highlight.js/lib/languages/swift';
import typescript from 'highlight.js/lib/languages/typescript';
import yaml from 'highlight.js/lib/languages/yaml';
import isUrl from 'is-url';
import prettyBytes from 'pretty-bytes';
import { validateHTMLColorHex, validateHTMLColorName, validateHTMLColorRgb } from 'validate-color';

hljs.registerLanguage('python', python);
hljs.registerLanguage('markdown', markdown);
hljs.registerLanguage('yaml', yaml);
hljs.registerLanguage('java', java);
hljs.registerLanguage('javascript', javascript);
hljs.registerLanguage('csharp', csharp);
hljs.registerLanguage('cpp', cpp);
hljs.registerLanguage('c', c);
hljs.registerLanguage('php', php);
hljs.registerLanguage('typescript', typescript);
hljs.registerLanguage('swift', swift);
hljs.registerLanguage('kotlin', kotlin);
hljs.registerLanguage('go', go);
hljs.registerLanguage('rust', rust);
hljs.registerLanguage('ruby', ruby);
hljs.registerLanguage('scala', scala);
hljs.registerLanguage('dart', dart);
hljs.registerLanguage('lua', lua);
hljs.registerLanguage('groovy', groovy);
hljs.registerLanguage('perl', perl);
hljs.registerLanguage('julia', julia);
hljs.registerLanguage('haskell', haskell);
hljs.registerLanguage('sql', sql);
hljs.registerLanguage('bash', bash);
hljs.registerLanguage('shell', shell);

const SUPPORTED_LANGUAGES = [
'python',
'markdown',
'yaml',
'java',
'javascript',
'csharp',
'cpp',
'c',
'php',
'typescript',
'swift',
'kotlin',
'go',
'rust',
'ruby',
'scala',
'dart',
'sql',
'lua',
'groovy',
'perl',
'julia',
'haskell',
'bash',
'shell',
];
import { detectLanguage } from './pango';

const debug = logger('pano-item-factory');

const MINIMUM_LANGUAGE_RELEVANCE = 0.1;

const isValidUrl = (text: string) => {
try {
return isUrl(text) && GLib.uri_parse(text, GLib.UriFlags.NONE) !== null;
Expand Down Expand Up @@ -168,6 +92,7 @@ const findOrCreateDbItem = async (ext: ExtensionBase, clip: ClipboardContent): P
.join('')}`,
metaData: value.operation,
});

case ContentType.IMAGE:
const checksum = GLib.compute_checksum_for_bytes(GLib.ChecksumType.MD5, new GLib.Bytes(value));
if (!checksum) {
Expand All @@ -189,6 +114,7 @@ const findOrCreateDbItem = async (ext: ExtensionBase, clip: ClipboardContent): P
size: value.length,
}),
});

case ContentType.TEXT:
const trimmedValue = value.trim();

Expand Down Expand Up @@ -252,37 +178,42 @@ const findOrCreateDbItem = async (ext: ExtensionBase, clip: ClipboardContent): P
searchValue: trimmedValue,
});
}
const highlightResult = hljs.highlightAuto(trimmedValue.slice(0, 2000), SUPPORTED_LANGUAGES);
if (highlightResult.relevance < 10) {
if (/^\p{Extended_Pictographic}*$/u.test(trimmedValue)) {
return db.save({
content: trimmedValue,
copyDate: new Date(),
isFavorite: false,
itemType: 'EMOJI',
matchValue: trimmedValue,
searchValue: trimmedValue,
});
} else {
return db.save({
content: value,
copyDate: new Date(),
isFavorite: false,
itemType: 'TEXT',
matchValue: value,
searchValue: value,
});
}
} else {

if (/^\p{Extended_Pictographic}*$/u.test(trimmedValue)) {
return db.save({
content: trimmedValue,
copyDate: new Date(),
isFavorite: false,
itemType: 'EMOJI',
matchValue: trimmedValue,
searchValue: trimmedValue,
});
}
const detectedLanguage = detectLanguage(trimmedValue);

if (detectedLanguage && detectedLanguage.relevance >= MINIMUM_LANGUAGE_RELEVANCE) {
return db.save({
content: value,
copyDate: new Date(),
isFavorite: false,
itemType: 'CODE',
matchValue: value,
searchValue: value,
metaData: JSON.stringify({
language: detectedLanguage.language,
}),
});
}

return db.save({
content: value,
copyDate: new Date(),
isFavorite: false,
itemType: 'TEXT',
matchValue: value,
searchValue: value,
});

default:
return null;
}
Expand Down Expand Up @@ -332,9 +263,30 @@ export const createPanoItemFromDb = (
case 'TEXT':
panoItem = new TextPanoItem(ext, clipboardManager, dbItem);
break;
case 'CODE':
panoItem = new CodePanoItem(ext, clipboardManager, dbItem);
case 'CODE': {
let language: string | undefined;

if (dbItem.metaData && dbItem.metaData !== '') {
const metaData: { language: string | undefined } = JSON.parse(dbItem.metaData);
language = metaData.language;
}

if (!language) {
const detectedLanguage = detectLanguage(dbItem.content.trim());
if (detectedLanguage && detectedLanguage.relevance >= MINIMUM_LANGUAGE_RELEVANCE) {
language = detectedLanguage.language;
}
}

if (language) {
panoItem = new CodePanoItem(ext, clipboardManager, dbItem, language);
} else {
panoItem = new TextPanoItem(ext, clipboardManager, dbItem);
}

break;
}

case 'LINK':
panoItem = new LinkPanoItem(ext, clipboardManager, dbItem);
break;
Expand Down

0 comments on commit 900bf0d

Please sign in to comment.