diff --git a/manifest.json b/manifest.json index 6fec098..5d60ed1 100644 --- a/manifest.json +++ b/manifest.json @@ -1,7 +1,7 @@ { "id": "obsidian-tweet-to-markdown", "name": "Tweet to Markdown", - "version": "1.1.3", + "version": "1.1.4", "minAppVersion": "0.12.16", "description": "Save tweets as Markdown files, along with their images, polls, etc.", "author": "kbravh", diff --git a/package.json b/package.json index c5a553b..f9be8ca 100644 --- a/package.json +++ b/package.json @@ -1,10 +1,10 @@ { "name": "obsidian-tweet-to-markdown", - "version": "1.1.3", + "version": "1.1.4", "description": "Save tweets as beautiful markdown files in Obsidian (https://obsidian.md)", "main": "main.js", "engines": { - "node": ">=10.0.0" + "node": ">=12.0.0" }, "scripts": { "dev": "rollup --config rollup.config.js -w", @@ -16,7 +16,7 @@ "license": "MIT", "devDependencies": { "@rollup/plugin-commonjs": "^18.0.0", - "@rollup/plugin-node-resolve": "^11.2.1", + "@rollup/plugin-node-resolve": "^13.0.6", "@rollup/plugin-typescript": "^8.2.1", "@types/node": "^14.14.37", "gts": "^3.1.0", diff --git a/rollup.config.js b/rollup.config.js index dd4d041..0fa0bf9 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,15 +1,14 @@ -import typescript from '@rollup/plugin-typescript'; -import {nodeResolve} from '@rollup/plugin-node-resolve'; -import commonjs from '@rollup/plugin-commonjs'; +import typescript from '@rollup/plugin-typescript' +import {nodeResolve} from '@rollup/plugin-node-resolve' +import commonjs from '@rollup/plugin-commonjs' -const isProd = (process.env.BUILD === 'production'); +const isProd = process.env.BUILD === 'production' -const banner = -`/* +const banner = `/* THIS IS A GENERATED/BUNDLED FILE BY ROLLUP -if you want to view the source visit the plugins github repository +if you want to view the source visit the plugin's github repository */ -`; +` export default { input: 'main.ts', @@ -22,9 +21,5 @@ export default { banner, }, external: ['obsidian'], - plugins: [ - typescript(), - nodeResolve({browser: true}), - commonjs(), - ] -}; \ No newline at end of file + plugins: [typescript(), nodeResolve({browser: true}), commonjs()], +} diff --git a/src/unicodeSubstring.ts b/src/unicodeSubstring.ts new file mode 100644 index 0000000..fa818d2 --- /dev/null +++ b/src/unicodeSubstring.ts @@ -0,0 +1,58 @@ +/** + * Credit: lautis/unicode-substring + * Rewritten for Obsidian mobile functionality. + */ + +const charAt = (string: string, index: number): string => { + const first = string.charCodeAt(index) + let second + if (first >= 0xd800 && first <= 0xdbff && string.length > index + 1) { + second = string.charCodeAt(index + 1) + if (second >= 0xdc00 && second <= 0xdfff) { + return string.substring(index, index + 2) + } + } + return string[index] +} + +const slice = (string: string, start: number, end: number): string => { + let accumulator = '' + let character + let stringIndex = 0 + let unicodeIndex = 0 + const length = string.length + + while (stringIndex < length) { + character = charAt(string, stringIndex) + if (unicodeIndex >= start && unicodeIndex < end) { + accumulator += character + } + stringIndex += character.length + unicodeIndex += 1 + } + return accumulator +} + +const toNumber = (value: string | number, fallback: number): number => { + if (value === undefined) { + return fallback + } else { + return Number(value) + } +} + +export const unicodeSubstring = ( + string: string, + start: number, + end: number +): string => { + const realStart = toNumber(start, 0) + const realEnd = toNumber(end, string.length) + if (realEnd === realStart) { + return '' + } else if (realEnd > realStart) { + return slice(string, realStart, realEnd) + } else { + return slice(string, realEnd, realStart) + } +} diff --git a/src/util.ts b/src/util.ts index d8b3704..12bd4e0 100644 --- a/src/util.ts +++ b/src/util.ts @@ -3,6 +3,7 @@ import {Media, Poll, Tweet} from './models' import {DownloadManager} from './downloadManager' import TTM from 'main' import {TTMSettings} from './settings' +import {unicodeSubstring} from './unicodeSubstring' /** * Parses out the tweet ID from the URL the user provided @@ -93,6 +94,12 @@ const reservedRe = /^\.+$/ const windowsReservedRe = /^(con|prn|aux|nul|com[0-9]|lpt[0-9])(\..*)?$/i const windowsTrailingRe = /[. ]+$/ +/** + * Sanitize a filename to remove any illegal characters. + * Also keeps the filename to 255 bytes or below. + * @param filename string + * @returns string + */ export const sanitizeFilename = (filename: string): string => { filename = filename .replace(illegalRe, '') @@ -100,7 +107,21 @@ export const sanitizeFilename = (filename: string): string => { .replace(reservedRe, '') .replace(windowsReservedRe, '') .replace(windowsTrailingRe, '') - return filename + return truncateBytewise(filename, 252) +} + +/** + * Truncate a string to a specified number of bytes + * @param string the string to truncate + * @param length the maximum length in bytes of the trimmed string + * @returns string + */ +export const truncateBytewise = (string: string, length: number): string => { + const originalLength = length + while (new TextEncoder().encode(string).length > originalLength) { + string = unicodeSubstring(string, 0, length--) + } + return string } /** diff --git a/versions.json b/versions.json index db0d43d..938a315 100644 --- a/versions.json +++ b/versions.json @@ -1,3 +1,3 @@ { - "1.1.3": "0.12.16" + "1.1.4": "0.12.16" } diff --git a/yarn.lock b/yarn.lock index 1429992..a48985a 100644 --- a/yarn.lock +++ b/yarn.lock @@ -93,10 +93,10 @@ magic-string "^0.25.7" resolve "^1.17.0" -"@rollup/plugin-node-resolve@^11.2.1": - version "11.2.1" - resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-11.2.1.tgz#82aa59397a29cd4e13248b106e6a4a1880362a60" - integrity sha512-yc2n43jcqVyGE2sqV5/YCmocy9ArjVAP/BeXyTtADTBBX6V0e5UMqwO8CdQ0kzjb6zu5P1qMzsScCMRvE9OlVg== +"@rollup/plugin-node-resolve@^13.0.6": + version "13.0.6" + resolved "https://registry.yarnpkg.com/@rollup/plugin-node-resolve/-/plugin-node-resolve-13.0.6.tgz#29629070bb767567be8157f575cfa8f2b8e9ef77" + integrity sha512-sFsPDMPd4gMqnh2gS0uIxELnoRUp5kBl5knxD2EO0778G1oOJv4G1vyT2cpWz75OU2jDVcXhjVUuTAczGyFNKA== dependencies: "@rollup/pluginutils" "^3.1.0" "@types/resolve" "1.17.1"