Skip to content

Commit

Permalink
Convert media package to TypeScript
Browse files Browse the repository at this point in the history
  • Loading branch information
swissspidy committed Aug 18, 2022
1 parent 328288b commit 0fa250f
Show file tree
Hide file tree
Showing 43 changed files with 445 additions and 104 deletions.
21 changes: 18 additions & 3 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

9 changes: 6 additions & 3 deletions packages/media/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,13 @@
},
"customExports": {
".": {
"default": "./src/index.js"
"default": "./src/index.ts"
}
},
"main": "dist/index.js",
"module": "dist-module/index.js",
"source": "src/index.js",
"types": "dist-types/index.js",
"source": "src/index.ts",
"publishConfig": {
"access": "public"
},
Expand All @@ -43,5 +44,7 @@
"mime": "^3.0.0",
"prop-types": "^15.8.1"
},
"devDependencies": {}
"devDependencies": {
"@types/mime": "^3.0.1"
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,8 +14,16 @@
* limitations under the License.
*/

const aspectRatiosApproximatelyMatch = (obj1, obj2) => {
/**
* Internal dependencies
*/
import type { Dimensions } from './types';

function aspectRatiosApproximatelyMatch(
obj1: Dimensions,
obj2: Dimensions
): boolean {
return Math.abs(obj1.width / obj1.height - obj2.width / obj2.height) < 0.01;
};
}

export default aspectRatiosApproximatelyMatch;
21 changes: 9 additions & 12 deletions packages/media/src/blob/index.js → packages/media/src/blob.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,17 @@
* limitations under the License.
*/

/**
* Blob cache.
*
* @type {Object.<string, File>}
*/
const blobCache = {};
type CacheObject = File | Blob | MediaSource;

const blobCache: Record<string, CacheObject> = {};

/**
* Create a blob URL from a file.
*
* @param {File|Blob|MediaSource} file File object.
* @param {CacheObject} file File object.
* @return {string} Blob URL.
*/
export function createBlob(file) {
export function createBlob(file: CacheObject): string {
const url = window.URL.createObjectURL(file);

blobCache[url] = file;
Expand All @@ -39,9 +36,9 @@ export function createBlob(file) {
* Get file by blob URL if it exists.
*
* @param {string} url Blob URL.
* @return {?File} File if exists.
* @return {?CacheObject} File if exists.
*/
export function getBlob(url) {
export function getBlob(url: string): CacheObject {
return blobCache[url];
}

Expand All @@ -51,7 +48,7 @@ export function getBlob(url) {
* @param {string} url Blob URL.
* @return {void}
*/
export function revokeBlob(url) {
export function revokeBlob(url: string): void {
if (getBlob(url)) {
window.URL.revokeObjectURL(url);
}
Expand All @@ -65,6 +62,6 @@ export function revokeBlob(url) {
* @param {string} url The URL.
* @return {boolean} Is the url a blob url?
*/
export function isBlobURL(url) {
export function isBlobURL(url: string): boolean {
return url?.startsWith('blob:');
}
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
* @param {string} type Mime type.
* @return {File} File object.
*/
function blobToFile(blob, filename, type) {
function blobToFile(blob: Blob, filename: string, type: string): File {
return new File([blob], filename, { type });
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
* Internal dependencies
*/
import aspectRatiosApproximatelyMatch from './aspectRatiosApproximatelyMatch';
import type { Resource, ResourceSize } from './types';

/**
* Encodes a text string as a valid Uniform Resource Identifier (URI)
Expand All @@ -28,7 +29,7 @@ import aspectRatiosApproximatelyMatch from './aspectRatiosApproximatelyMatch';
* @param {string} str A value representing an encoded URI.
* @return {string} Encoded URI
*/
function maybeEncodeURI(str) {
function maybeEncodeURI(str: string): string {
if (str.includes('%')) {
return str;
}
Expand All @@ -39,11 +40,11 @@ function maybeEncodeURI(str) {
/**
* Returns a valid srcSet attribute value for the given media resource.
*
* @param {import('@googleforcreators/media').Resource} resource The resource.
* @param {Resource} resource The resource.
* @return {?string} The srcSet value, or null if the resource has no `sizes`
* attribute.
*/
function calculateSrcSet(resource) {
function calculateSrcSet(resource: Resource): string | null {
if (!resource.sizes) {
return null;
}
Expand All @@ -55,7 +56,7 @@ function calculateSrcSet(resource) {
// Remove duplicates. Given it's already ordered in descending width order, we can be
// more efficient and just check the last item in each reduction.
.reduce(
(unique, s) =>
(unique: Array<ResourceSize>, s) =>
unique.length &&
Number(unique[unique.length - 1].width) === Number(s.width)
? unique
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,13 +13,13 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const createFileReader = (file) => {
function createFileReader(file: File): Promise<FileReader> {
const reader = new window.FileReader();
return new Promise((resolve, reject) => {
reader.onload = () => resolve(reader);
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
};
}

export default createFileReader;
Original file line number Diff line number Diff line change
Expand Up @@ -19,12 +19,18 @@
*/
import getTypeFromMime from './getTypeFromMime';
import normalizeResourceSizes from './normalizeResourceSizes';
import type {
GifResource,
Resource,
VideoResource,
ResourceInput,
} from './types';

/**
* Creates a resource object.
*
* @param {import('./types').Attachment} attachment WordPress Attachment object.
* @return {import('./types').Resource} Resource object.
* @param {ResourceInput} data Resource data.
* @return {Resource} Resource object.
*/
function createResource({
baseColor,
Expand All @@ -50,7 +56,7 @@ function createResource({
isExternal = false,
trimData,
needsProxy = false,
}) {
}: ResourceInput): Resource | VideoResource | GifResource {
return {
baseColor,
blurHash,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,14 +20,12 @@
* @param {string} url URL of file.
* @return {Promise<Blob>} Blob object.
*/
async function fetchRemoteBlob(url) {
async function fetchRemoteBlob(url: string): Promise<Blob> {
const response = await fetch(url);
if (!response.ok) {
throw new Error(`An error has occured: ${response.status}`);
throw new Error(`An error has occurred: ${response.status}`);
}
const data = await response.blob();

return data;
return response.blob();
}

export default fetchRemoteBlob;
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import fetchRemoteBlob from './fetchRemoteBlob';
import blobToFile from './blobToFile';
import getFileBasename from './getFileBasename';

function generateFileName(url) {
function generateFileName(url: string): string {
const currentFileName = getFileNameFromUrl(url);
const currentFileExt = getFileBasename({ name: currentFileName });

Expand All @@ -39,7 +39,7 @@ function generateFileName(url) {
* @param {string} mimeType Mime type of file.
* @return {Promise<File>} File object.
*/
async function fetchRemoteFile(url, mimeType) {
async function fetchRemoteFile(url: string, mimeType: string): Promise<File> {
const data = await fetchRemoteBlob(url);
const name = generateFileName(url);
return blobToFile(data, name, mimeType);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,12 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
const formatDuration = (time) => {

function formatDuration(time: number): string {
return time.toLocaleString('en-US', {
minimumIntegerDigits: 2,
useGrouping: false,
});
};
}

export default formatDuration;
Original file line number Diff line number Diff line change
Expand Up @@ -25,14 +25,14 @@ import formatDuration from './formatDuration';
* @param {number} ms Original length in milliseconds.
* @return {string} Formatted length.
*/
function formatMsToHMS(ms) {
function formatMsToHMS(ms: number): string {
if (!ms) {
return '00:00:00';
}
let seconds = ms / 1000;
const hours = parseInt(seconds / 3600);
const hours = Math.floor(seconds / 3600);
seconds = seconds % 3600;
const minutes = parseInt(seconds / 60);
const minutes = Math.floor(seconds / 60);
seconds = seconds % 60;

return `${formatDuration(hours)}:${formatDuration(minutes)}:${formatDuration(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,19 +20,40 @@
import getMediaSizePositionProps from './getMediaSizePositionProps';
import preloadVideo from './preloadVideo';
import seekVideo from './seekVideo';
import type { VideoResource } from './types';

const CACHE = new Map();

interface FlipSettings {
vertical: boolean;
horizontal: boolean;
}

// TODO(#12126): Use improved Element type from shared package.
interface Element {
width: number;
height: number;
scale: number;
focalX: number;
focalY: number;
flip: FlipSettings;
}

/**
* Returns an image data URL with a video strip of the frames of the video.
*
* @param {Object} element Canvas element with information about size, scale, and focal point.
* @param {Object} resource Resource object with url and video length.
* @param {number} stripWidth Target strip width.
* @param {number} stripHeight Video src URL.
* @return {Promise<string>} The video strip as a data URL.
* @return {Promise<string|null>} The video strip as a data URL or null if there was an error.
*/
async function generateVideoStrip(element, resource, stripWidth, stripHeight) {
async function generateVideoStrip(
element: Element,
resource: VideoResource,
stripWidth: number,
stripHeight: number
) {
const {
width: frameWidth,
height: frameHeight,
Expand Down Expand Up @@ -106,10 +127,16 @@ async function generateVideoStrip(element, resource, stripWidth, stripHeight) {
canvas.height = stripHeight;
const ctx = canvas.getContext('2d');

// If the contextType doesn't match a possible drawing context,
// or differs from the first contextType requested, null is returned.
if (!ctx) {
return Promise.resolve(null);
}

// Create a function to grab the current frame and either schedule next or abort
let timeOffset = 0;
let frame = 0;
const grabFrame = async () => {
const grabFrame: () => Promise<void> = async () => {
// Seek to the next offset
await seekVideo(video, timeOffset);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -14,11 +14,11 @@
* limitations under the License.
*/

function getCanvasBlob(canvasEl) {
function getCanvasBlob(canvasEl: HTMLCanvasElement): Promise<Blob | null> {
return new Promise(function (resolve) {
canvasEl.toBlob((blob) => {
resolve(blob, 'image/jpeg');
});
resolve(blob);
}, 'image/jpeg');
});
}

Expand Down
Loading

0 comments on commit 0fa250f

Please sign in to comment.