Design system.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

index.ts 2.9 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. import LanguageDetect from 'languagedetect';
  2. import {languages} from 'prismjs/components';
  3. const RESOLVED_ALIASES = Object.fromEntries(
  4. Object
  5. .entries(languages)
  6. .reduce(
  7. (resolved, [languageId, languageDefinition]) => {
  8. if (Array.isArray(languageDefinition.alias)) {
  9. return [
  10. ...resolved,
  11. ...(languageDefinition.alias.map((a: string) => [a, { aliasOf: languageId, title: languageDefinition.title, extension: `.${a}`} ])),
  12. [languageId, { title: languageDefinition.title, extension: `.${languageId}`}],
  13. ];
  14. }
  15. if (typeof languageDefinition.alias === 'string') {
  16. return [
  17. ...resolved,
  18. [languageDefinition.alias, { aliasOf: languageId, title: languageDefinition.title, extension: `.${languageDefinition.alias}`}],
  19. [languageId, { title: languageDefinition.title, extension: `.${languageId}`}],
  20. ];
  21. }
  22. return [
  23. ...resolved,
  24. [languageId, { title: languageDefinition.title, extension: `.${languageId}`}],
  25. ];
  26. },
  27. [] as [string, { aliasOf?: string, title: string, extension: string }][]
  28. )
  29. );
  30. type Language = string;
  31. type LanguageProbability = number;
  32. type LanguageMatch = [Language, LanguageProbability];
  33. export interface TextMetadata {
  34. contents?: string;
  35. scheme?: string;
  36. schemeTitle?: string;
  37. languageMatches?: LanguageMatch[];
  38. lineCount?: number;
  39. linesOfCode?: number;
  40. }
  41. const countLinesOfCode = (lines: string[], scheme: string): number => {
  42. // TODO count loc depending on scheme
  43. //return lines.filter((line) => !line.trim().startsWith('//')).length;
  44. return lines.filter((line) => line.trim().length > 0).length;
  45. };
  46. export const getTextMetadata = (contents: string, filename?: string): Promise<TextMetadata> => {
  47. const lineNormalizedContents = contents.replace(/\r\n/g, '\n').replace(/\r/g, '\n');
  48. const lines = lineNormalizedContents.split('\n');
  49. const lineCount = lines.length;
  50. const metadata = Object.entries(RESOLVED_ALIASES).reduce(
  51. (theMetadata, [key, value]) => {
  52. if (typeof theMetadata.scheme === 'undefined' && filename?.endsWith(value.extension)) {
  53. if (value.aliasOf) {
  54. return {
  55. ...theMetadata,
  56. scheme: value.aliasOf,
  57. schemeTitle: value.title,
  58. linesOfCode: countLinesOfCode(lines, value.aliasOf),
  59. };
  60. }
  61. return {
  62. ...theMetadata,
  63. scheme: key,
  64. schemeTitle: value.title,
  65. linesOfCode: countLinesOfCode(lines, key),
  66. };
  67. }
  68. return theMetadata;
  69. },
  70. {
  71. contents,
  72. lineCount,
  73. } as TextMetadata,
  74. );
  75. if (typeof metadata.scheme !== 'string') {
  76. const naturalLanguageDetector = new LanguageDetect();
  77. metadata.languageMatches = naturalLanguageDetector.detect(contents);
  78. }
  79. return Promise.resolve(metadata);
  80. };