From 96850b7b98ec542c66c028fdb0f48fa16a1acafe Mon Sep 17 00:00:00 2001 From: Henry Heino <46334387+personalizedrefrigerator@users.noreply.github.com> Date: Tue, 4 Jun 2024 01:50:18 -0700 Subject: [PATCH] Chore: Migrate `mime-utils.js` to TypeScript (#10536) --- .eslintignore | 1 + .gitignore | 1 + .../gui/NoteEditor/utils/resourceHandling.ts | 2 +- .../app-mobile/components/screens/Note.tsx | 2 +- packages/app-mobile/utils/shim-init-react.js | 2 +- packages/lib/import-enex.ts | 2 +- packages/lib/mime-utils.js | 50 ------------------- packages/lib/mime-utils.ts | 46 +++++++++++++++++ packages/lib/mimeUtils.test.js | 15 +++++- packages/lib/models/Resource.ts | 2 +- packages/lib/models/utils/resourceUtils.ts | 2 +- packages/lib/services/rest/routes/notes.ts | 2 +- packages/lib/shim-init-node.ts | 2 +- packages/server/src/models/ItemModel.ts | 2 +- packages/server/src/routes/default.ts | 2 +- packages/tools/fetchPatreonPosts.js | 2 +- 16 files changed, 72 insertions(+), 63 deletions(-) delete mode 100644 packages/lib/mime-utils.js create mode 100644 packages/lib/mime-utils.ts diff --git a/.eslintignore b/.eslintignore index 9c2c5d7cc..394452039 100644 --- a/.eslintignore +++ b/.eslintignore @@ -874,6 +874,7 @@ packages/lib/markdownUtils.js packages/lib/markdownUtils2.test.js packages/lib/markupLanguageUtils.js packages/lib/migrations/42.js +packages/lib/mime-utils.js packages/lib/models/Alarm.js packages/lib/models/BaseItem.test.js packages/lib/models/BaseItem.js diff --git a/.gitignore b/.gitignore index 4a5f4ad49..2949cf909 100644 --- a/.gitignore +++ b/.gitignore @@ -853,6 +853,7 @@ packages/lib/markdownUtils.js packages/lib/markdownUtils2.test.js packages/lib/markupLanguageUtils.js packages/lib/migrations/42.js +packages/lib/mime-utils.js packages/lib/models/Alarm.js packages/lib/models/BaseItem.test.js packages/lib/models/BaseItem.js diff --git a/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts b/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts index 18eb0f1d9..1cc0e5b96 100644 --- a/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts +++ b/packages/app-desktop/gui/NoteEditor/utils/resourceHandling.ts @@ -15,7 +15,7 @@ import markupRenderOptions from './markupRenderOptions'; import { fileExtension, filename, safeFileExtension, safeFilename } from '@joplin/utils/path'; const joplinRendererUtils = require('@joplin/renderer').utils; const { clipboard } = require('electron'); -const mimeUtils = require('@joplin/lib/mime-utils.js').mime; +import * as mimeUtils from '@joplin/lib/mime-utils'; const md5 = require('md5'); const path = require('path'); diff --git a/packages/app-mobile/components/screens/Note.tsx b/packages/app-mobile/components/screens/Note.tsx index 63359ea1d..071f509da 100644 --- a/packages/app-mobile/components/screens/Note.tsx +++ b/packages/app-mobile/components/screens/Note.tsx @@ -24,7 +24,7 @@ import NavService, { OnNavigateCallback as OnNavigateCallback } from '@joplin/li import BaseModel, { ModelType } from '@joplin/lib/BaseModel'; import ActionButton from '../ActionButton'; const { fileExtension, safeFileExtension } = require('@joplin/lib/path-utils'); -const mimeUtils = require('@joplin/lib/mime-utils.js').mime; +import * as mimeUtils from '@joplin/lib/mime-utils'; import ScreenHeader, { MenuOptionType } from '../ScreenHeader'; import NoteTagsDialog from './NoteTagsDialog'; import time from '@joplin/lib/time'; diff --git a/packages/app-mobile/utils/shim-init-react.js b/packages/app-mobile/utils/shim-init-react.js index 2725dfcc8..16bd2b053 100644 --- a/packages/app-mobile/utils/shim-init-react.js +++ b/packages/app-mobile/utils/shim-init-react.js @@ -7,7 +7,7 @@ const FsDriverRN = require('./fs-driver/fs-driver-rn').default; const { Buffer } = require('buffer'); const { Linking, Platform } = require('react-native'); const showMessageBox = require('./showMessageBox.js').default; -const mimeUtils = require('@joplin/lib/mime-utils.js').mime; +const mimeUtils = require('@joplin/lib/mime-utils.js'); const { basename, fileExtension } = require('@joplin/lib/path-utils'); const uuid = require('@joplin/lib/uuid').default; const Resource = require('@joplin/lib/models/Resource').default; diff --git a/packages/lib/import-enex.ts b/packages/lib/import-enex.ts index e5bc1ee5d..0edb1bb3c 100644 --- a/packages/lib/import-enex.ts +++ b/packages/lib/import-enex.ts @@ -16,7 +16,7 @@ const { enexXmlToHtml } = require('./import-enex-html-gen.js'); const md5 = require('md5'); const { Base64Decode } = require('base64-stream'); const md5File = require('md5-file'); -const { mime } = require('./mime-utils'); +import * as mime from './mime-utils'; // const Promise = require('promise'); const fs = require('fs-extra'); diff --git a/packages/lib/mime-utils.js b/packages/lib/mime-utils.js deleted file mode 100644 index 8d9626b2b..000000000 --- a/packages/lib/mime-utils.js +++ /dev/null @@ -1,50 +0,0 @@ -const mimeTypes = require('./mime-utils-types'); - -const mime = { - fromFileExtension(ext) { - ext = ext.toLowerCase(); - for (let i = 0; i < mimeTypes.length; i++) { - const t = mimeTypes[i]; - if (t.e.indexOf(ext) >= 0) { - return t.t; - } - } - return null; - }, - - fromFilename(name) { - if (!name) return null; - const splitted = name.trim().split('.'); - if (splitted.length <= 1) return null; - return mime.fromFileExtension(splitted[splitted.length - 1]); - }, - - toFileExtension(mimeType) { - mimeType = mimeType.toLowerCase(); - for (let i = 0; i < mimeTypes.length; i++) { - const t = mimeTypes[i]; - if (mimeType === t.t) { - // Return the first file extension that is 3 characters long - // If none exist return the first one in the list. - for (let j = 0; j < t.e.length; j++) { - if (t.e[j].length === 3) return t.e[j]; - } - return t.e[0]; - } - } - return null; - }, - - fromDataUrl(dataUrl) { - // Example: data:image/jpeg;base64,/9j/4AAQSkZJR..... - const defaultMime = 'text/plain'; - const p = dataUrl.substr(0, dataUrl.indexOf(',')).split(';'); - let s = p[0]; - s = s.split(':'); - if (s.length <= 1) return defaultMime; - s = s[1]; - return s.indexOf('/') >= 0 ? s : defaultMime; // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs - }, -}; - -module.exports = { mime }; diff --git a/packages/lib/mime-utils.ts b/packages/lib/mime-utils.ts new file mode 100644 index 000000000..e79eb4fba --- /dev/null +++ b/packages/lib/mime-utils.ts @@ -0,0 +1,46 @@ +const mimeTypes = require('./mime-utils-types'); + +export const fromFileExtension = (ext: string) => { + ext = ext.toLowerCase(); + for (let i = 0; i < mimeTypes.length; i++) { + const t = mimeTypes[i]; + if (t.e.indexOf(ext) >= 0) { + return t.t; + } + } + return null; +}; + +export const fromFilename = (name: string) => { + if (!name) return null; + const splitted = name.trim().split('.'); + if (splitted.length <= 1) return null; + return fromFileExtension(splitted[splitted.length - 1]); +}; + +export const toFileExtension = (mimeType: string) => { + mimeType = mimeType.toLowerCase(); + for (let i = 0; i < mimeTypes.length; i++) { + const t = mimeTypes[i]; + if (mimeType === t.t) { + // Return the first file extension that is 3 characters long + // If none exist return the first one in the list. + for (let j = 0; j < t.e.length; j++) { + if (t.e[j].length === 3) return t.e[j]; + } + return t.e[0]; + } + } + return null; +}; + +export const fromDataUrl = (dataUrl: string) => { + // Example: data:image/jpeg;base64,/9j/4AAQSkZJR..... + const defaultMime = 'text/plain'; + const p = dataUrl.substr(0, dataUrl.indexOf(',')).split(';'); + let s = p[0]; + const result = s.split(':'); + if (result.length <= 1) return defaultMime; + s = result[1]; + return s.indexOf('/') >= 0 ? s : defaultMime; // https://developer.mozilla.org/en-US/docs/Web/HTTP/Basics_of_HTTP/Data_URIs +}; diff --git a/packages/lib/mimeUtils.test.js b/packages/lib/mimeUtils.test.js index e2bb39e72..ccc97a66c 100644 --- a/packages/lib/mimeUtils.test.js +++ b/packages/lib/mimeUtils.test.js @@ -1,6 +1,6 @@ -const mimeUtils = require('./mime-utils.js').mime; +const mimeUtils = require('./mime-utils.js'); -describe('mimeUils', () => { +describe('mimeUtils', () => { @@ -18,4 +18,15 @@ describe('mimeUils', () => { expect(mimeUtils.fromFilename('test')).toBe(null); })); + it.each([ + ['Not a data URL.', 'text/plain'], + // No encoding type + ['data:image/svg+xml,%3csvg%3e%3cpath fill=\'%23fff\' d=\'M1,2,3z\'/%3e%3c/svg%3e', 'image/svg+xml'], + // Shouldn't need a full data URL + ['data:image/jpeg;base64,/9j/4AAQSkZJR...', 'image/jpeg'], + ['data:image/png;base64,iVBORw0KGgoAAAANSUhEU...', 'image/png'], + ])('should get MIME types from data URLs (case %#)', (url, expected) => { + expect(mimeUtils.fromDataUrl(url)).toBe(expected); + }); + }); diff --git a/packages/lib/models/Resource.ts b/packages/lib/models/Resource.ts index 492da303c..b14d715e8 100644 --- a/packages/lib/models/Resource.ts +++ b/packages/lib/models/Resource.ts @@ -9,7 +9,7 @@ import { ResourceEntity, ResourceLocalStateEntity, ResourceOcrStatus, SqlQuery } import ResourceLocalState from './ResourceLocalState'; import * as pathUtils from '../path-utils'; import { safeFilename } from '../path-utils'; -const { mime } = require('../mime-utils.js'); +import * as mime from '../mime-utils'; const { FsDriverDummy } = require('../fs-driver-dummy.js'); import JoplinError from '../JoplinError'; import itemCanBeEncrypted from './utils/itemCanBeEncrypted'; diff --git a/packages/lib/models/utils/resourceUtils.ts b/packages/lib/models/utils/resourceUtils.ts index aa70173f4..8218815c2 100644 --- a/packages/lib/models/utils/resourceUtils.ts +++ b/packages/lib/models/utils/resourceUtils.ts @@ -1,5 +1,5 @@ import type { ResourceEntity } from '../../services/database/types'; -const { mime } = require('../../mime-utils.js'); +import * as mime from '../../mime-utils'; import { filename } from '@joplin/utils/path'; // This file contains resource-related utilities that do not diff --git a/packages/lib/services/rest/routes/notes.ts b/packages/lib/services/rest/routes/notes.ts index 0e77d8c3f..9caa67a9d 100644 --- a/packages/lib/services/rest/routes/notes.ts +++ b/packages/lib/services/rest/routes/notes.ts @@ -16,7 +16,7 @@ import Tag from '../../../models/Tag'; import Resource from '../../../models/Resource'; import htmlUtils from '../../../htmlUtils'; import markupLanguageUtils from '../../../markupLanguageUtils'; -const mimeUtils = require('../../../mime-utils.js').mime; +import * as mimeUtils from '../../../mime-utils'; const md5 = require('md5'); import HtmlToMd from '../../../HtmlToMd'; const urlUtils = require('../../../urlUtils.js'); diff --git a/packages/lib/shim-init-node.ts b/packages/lib/shim-init-node.ts index 8a1a073b9..1ed487236 100644 --- a/packages/lib/shim-init-node.ts +++ b/packages/lib/shim-init-node.ts @@ -14,7 +14,7 @@ import replaceUnsupportedCharacters from './utils/replaceUnsupportedCharacters'; import { FetchBlobOptions } from './types'; import FileApiDriverLocal from './file-api-driver-local'; -const mimeUtils = require('./mime-utils.js').mime; +import * as mimeUtils from './mime-utils'; const { _ } = require('./locale'); const http = require('http'); const https = require('https'); diff --git a/packages/server/src/models/ItemModel.ts b/packages/server/src/models/ItemModel.ts index 488320c01..fa69e87d4 100644 --- a/packages/server/src/models/ItemModel.ts +++ b/packages/server/src/models/ItemModel.ts @@ -16,7 +16,7 @@ import { msleep } from '../utils/time'; import Logger, { LoggerWrapper } from '@joplin/utils/Logger'; import prettyBytes = require('pretty-bytes'); -const mimeUtils = require('@joplin/lib/mime-utils.js').mime; +import * as mimeUtils from '@joplin/lib/mime-utils'; // Converts "root:/myfile.txt:" to "myfile.txt" const extractNameRegex = /^root:\/(.*):$/; diff --git a/packages/server/src/routes/default.ts b/packages/server/src/routes/default.ts index e43568b72..ab8c568bd 100644 --- a/packages/server/src/routes/default.ts +++ b/packages/server/src/routes/default.ts @@ -7,7 +7,7 @@ import * as fs from 'fs-extra'; import { AppContext, RouteType } from '../utils/types'; import { localFileFromUrl } from '../utils/joplinUtils'; import { homeUrl, loginUrl } from '../utils/urlUtils'; -const { mime } = require('@joplin/lib/mime-utils.js'); +import * as mime from '@joplin/lib/mime-utils'; const publicDir = `${dirname(dirname(__dirname))}/public`; diff --git a/packages/tools/fetchPatreonPosts.js b/packages/tools/fetchPatreonPosts.js index f8a823a64..7afebacc0 100644 --- a/packages/tools/fetchPatreonPosts.js +++ b/packages/tools/fetchPatreonPosts.js @@ -7,7 +7,7 @@ const { patreonOauthToken } = require('./tool-utils'); const HtmlToMd = require('@joplin/lib/HtmlToMd').default; const { dirname, filename, basename } = require('@joplin/lib/path-utils'); const markdownUtils = require('@joplin/lib/markdownUtils').default; -const mimeUtils = require('@joplin/lib/mime-utils.js').mime; +const mimeUtils = require('@joplin/lib/mime-utils.js'); const { mimeTypeFromHeaders } = require('@joplin/lib/net-utils'); const shim = require('@joplin/lib/shim').default; const moment = require('moment');