From ed36fb30690dd564ee030daff42d65a8b93a05af Mon Sep 17 00:00:00 2001 From: Niloy Sikdar Date: Sun, 21 Aug 2022 08:41:52 +0530 Subject: [PATCH] feat(jsdoc): add JSDoc comments (#83) * docs(jsdoc): add JSDoc comments Add JSDoc comments for generateEmail utility Resolves #61 Signed-off-by: Niloy Sikdar * docs(jsdoc): add comments for generateTextEmail Add JSDoc comments for generateTextEmail utility Resolves #61 Signed-off-by: Niloy Sikdar * docs(jsdoc): add comments for generateTextEmailFromHTML Add JSDoc comments for genearteTextEmailFromHTML utility Resolves #61 Signed-off-by: Niloy Sikdar * docs(jsdoc): add comments for sx and makeStyles Add JSDoc comments for sx and makeStyles utilities re #61 Signed-off-by: Niloy Sikdar * docs(jsdoc): add comment for BaseStyleProp Add JSDoc comments for BaseStyleProp interface re #61 Signed-off-by: Niloy Sikdar * docs(jsdoc): add comments for Typography Add JSDoc comments for Typography component re #61 Signed-off-by: Niloy Sikdar * docs(jsdoc): add comments for components Add JSDoc comments for all of the components re #61 Signed-off-by: Niloy Sikdar * feat(typedoc): add typedoc generate config and scripts Add typedocOptions inside tsconfig and add build script to generate typedoc site Resolves #61 Signed-off-by: Niloy Sikdar Signed-off-by: Niloy Sikdar --- package.json | 4 +- src/components/Button/Button.tsx | 18 ++++++++ src/components/Column/Column.tsx | 14 ++++++ src/components/Divider/Divider.tsx | 22 +++++++++ src/components/Email/Email.tsx | 6 +++ src/components/Image/Image.tsx | 23 ++++++++++ src/components/Link/Link.tsx | 13 ++++++ src/components/Preheader/Preheader.tsx | 6 +++ src/components/Quote/Quote.stories.tsx | 1 - src/components/Quote/Quote.tsx | 6 +++ src/components/Section/Section.tsx | 10 ++++ src/components/Typography/Typography.tsx | 14 ++++++ src/components/types/index.ts | 6 +++ src/utils/generateEmail/generateEmail.ts | 27 +++++++++++ .../generateTextEmail/generateTextEmail.ts | 11 +++++ .../generateTextEmailFromHTML.ts | 6 +++ src/utils/makeStyles/makeStyles.ts | 6 +++ src/utils/sx/sx.ts | 6 +++ tsconfig.json | 4 ++ yarn.lock | 46 ++++++++++++++++++- 20 files changed, 246 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index e4ed3ee..3f403e7 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,8 @@ "lint-staged": "lint-staged", "release": "semantic-release --branches main", "storybook": "start-storybook -p 6006", - "build-storybook": "build-storybook -o docs-build" + "build:storybook": "build-storybook -o storybook", + "build:typedoc": "typedoc" }, "lint-staged": { "src/**": [ @@ -93,6 +94,7 @@ "react-dom": "^18.2.0", "react-test-renderer": "^18.2.0", "semantic-release": "^19.0.3", + "typedoc": "^0.23.10", "typescript": "^4.7.3" }, "husky": { diff --git a/src/components/Button/Button.tsx b/src/components/Button/Button.tsx index 3cf6f1a..fec7f87 100644 --- a/src/components/Button/Button.tsx +++ b/src/components/Button/Button.tsx @@ -5,10 +5,28 @@ import { sx } from '../../utils/sx'; type ButtonStyles = 'root' | 'primary' | 'secondary'; +/** + * Interface for PropTypes for the `Button` component. + */ export interface ButtonProps extends BaseStyleProp { + /** + * The content of the component. + */ children?: ReactNode; + /** + * Applies the theme button styles. + * @default 'primary' + */ variant?: 'primary' | 'secondary'; + /** + * The URL to link to when the button is clicked. + * An `a` element will be used as the root node. + */ href: string; + /** + * The target of the link. + * @default '_blank' + */ target?: HTMLAttributeAnchorTarget; } diff --git a/src/components/Column/Column.tsx b/src/components/Column/Column.tsx index bb0ed0f..d9f408d 100644 --- a/src/components/Column/Column.tsx +++ b/src/components/Column/Column.tsx @@ -5,9 +5,23 @@ import { BaseStyleProp } from '../types'; type ColumnStyles = 'root'; +/** + * Interface for PropTypes for the `Column` component. + */ export interface ColumnProps extends BaseStyleProp { + /** + * The content of the component. + */ children?: ReactNode; + /** + * The alignment of the children. + * @default 'center' + */ align?: 'left' | 'center' | 'right'; + /** + * The vertical alignment of the children. + * @default 'top' + */ verticalAlign?: CSSProperties['verticalAlign']; } diff --git a/src/components/Divider/Divider.tsx b/src/components/Divider/Divider.tsx index 0c44fd5..d5598de 100644 --- a/src/components/Divider/Divider.tsx +++ b/src/components/Divider/Divider.tsx @@ -5,11 +5,33 @@ import { BaseStyleProp } from '../types'; type DividerStyles = 'root'; +/** + * Interface for PropTypes for the `Divider` component. + */ export interface DividerProps extends BaseStyleProp { + /** + * The alignment of the divider. + * @default 'left' + */ align?: 'left' | 'center' | 'right'; + /** + * The color of the divider. + */ color?: CSSProperties['borderColor']; + /** + * The type of the divider. + * @default 'solid' + */ type?: CSSProperties['borderStyle']; + /** + * The thickness of the divider. + * @default '1px' + */ size?: CSSProperties['borderWidth']; + /** + * The width of the divider. + * @default '100%' + */ width?: CSSProperties['width']; } diff --git a/src/components/Email/Email.tsx b/src/components/Email/Email.tsx index 773044e..8d366e1 100644 --- a/src/components/Email/Email.tsx +++ b/src/components/Email/Email.tsx @@ -4,7 +4,13 @@ import { makeStyles } from '../../utils/makeStyles'; type EmailStyles = 'root'; +/** + * Interface for PropTypes for the `Email` component. + */ export interface EmailProps extends BaseStyleProp { + /** + * The content of the component. + */ children?: ReactNode; } diff --git a/src/components/Image/Image.tsx b/src/components/Image/Image.tsx index 1fd4636..6d072e9 100644 --- a/src/components/Image/Image.tsx +++ b/src/components/Image/Image.tsx @@ -13,12 +13,35 @@ type ImageStyles = | 'captionSection' | 'imageColumn'; +/** + * Interface for PropTypes for the `Image` component. + */ export interface ImageProps extends BaseStyleProp { + /** + * The URL or filepath of the image. + */ src: string; + /** + * The alt text for the image. + */ alt: string; + /** + * The caption for the image. + */ caption?: string; + /** + * The width of the image. + */ width: CSSProperties['width']; + /** + * The height of the image. + * @default 'auto' + */ height?: CSSProperties['height']; + /** + * The alignment of the caption. + * @default 'center' + */ captionAlign?: 'left' | 'center' | 'right'; } diff --git a/src/components/Link/Link.tsx b/src/components/Link/Link.tsx index 34fe38c..a404eeb 100644 --- a/src/components/Link/Link.tsx +++ b/src/components/Link/Link.tsx @@ -4,9 +4,22 @@ import { makeStyles } from '../../utils/makeStyles'; type LinkStyles = 'root'; +/** + * Interface for PropTypes for the `Link` component. + */ export interface LinkProps extends BaseStyleProp { + /** + * The content of the component. + */ children?: ReactNode; + /** + * The URL to link to. + */ href: string; + /** + * The target of the link. + * @default '_blank' + */ target?: HTMLAttributeAnchorTarget; } diff --git a/src/components/Preheader/Preheader.tsx b/src/components/Preheader/Preheader.tsx index a9d31ba..8a305b2 100644 --- a/src/components/Preheader/Preheader.tsx +++ b/src/components/Preheader/Preheader.tsx @@ -3,7 +3,13 @@ import { BaseStyleProp } from '../types'; type PreheaderStyles = 'root'; +/** + * Interface for PropTypes for the `Preheader` component. + */ export interface PreheaderProps extends BaseStyleProp { + /** + * The text for the preheader. + */ text: string; } diff --git a/src/components/Quote/Quote.stories.tsx b/src/components/Quote/Quote.stories.tsx index aa864b2..50a4e38 100644 --- a/src/components/Quote/Quote.stories.tsx +++ b/src/components/Quote/Quote.stories.tsx @@ -1,4 +1,3 @@ -import React from 'react'; import { ComponentStory, ComponentMeta } from '@storybook/react'; import { Quote } from './Quote'; diff --git a/src/components/Quote/Quote.tsx b/src/components/Quote/Quote.tsx index 3a30a24..ce5b1f6 100644 --- a/src/components/Quote/Quote.tsx +++ b/src/components/Quote/Quote.tsx @@ -4,7 +4,13 @@ import { BaseStyleProp } from '../types'; type QuoteStyles = 'root'; +/** + * Interface for PropTypes for the `Quote` component. + */ export interface QuoteProps extends BaseStyleProp { + /** + * The content of the component. + */ children?: ReactNode; } diff --git a/src/components/Section/Section.tsx b/src/components/Section/Section.tsx index 094d29a..a6ffbab 100644 --- a/src/components/Section/Section.tsx +++ b/src/components/Section/Section.tsx @@ -5,8 +5,18 @@ import { BaseStyleProp } from '../types'; type SectionStyles = 'root' | 'body' | 'row'; +/** + * Interface for PropTypes for the `Section` component. + */ export interface SectionProps extends BaseStyleProp { + /** + * The content of the component. + */ children?: ReactNode; + /** + * If `true`, the `section` will take up the full width of its container. + * @default true + */ fullWidth?: boolean; } diff --git a/src/components/Typography/Typography.tsx b/src/components/Typography/Typography.tsx index a9b1644..275e20e 100644 --- a/src/components/Typography/Typography.tsx +++ b/src/components/Typography/Typography.tsx @@ -5,8 +5,18 @@ import { sx } from '../../utils/sx'; type ButtonStyles = 'root'; +/** + * Interface for PropTypes for the `Typography` component. + */ export interface TypographyProps extends BaseStyleProp { + /** + * The content of the component. + */ children: ReactNode; + /** + * Applies the theme typography styles. + * @default 'body1' + */ variant?: | 'h1' | 'h2' @@ -19,6 +29,10 @@ export interface TypographyProps extends BaseStyleProp { | 'body1' | 'body2' | 'caption'; + /** + * Set the text-align on the component. + * @default 'left' + */ align?: CSSProperties['textAlign']; } diff --git a/src/components/types/index.ts b/src/components/types/index.ts index 36f7451..6f9f20e 100644 --- a/src/components/types/index.ts +++ b/src/components/types/index.ts @@ -1,6 +1,12 @@ import { CSSProperties } from 'react'; export interface BaseStyleProp { + /** + * Override or extend the styles applied to the component. + */ classes?: Partial>; + /** + * The class name to be applied to the element. + */ className?: string; } diff --git a/src/utils/generateEmail/generateEmail.ts b/src/utils/generateEmail/generateEmail.ts index 36a42b7..a5b3e7f 100644 --- a/src/utils/generateEmail/generateEmail.ts +++ b/src/utils/generateEmail/generateEmail.ts @@ -2,13 +2,40 @@ import ReactDOMServer from 'react-dom/server'; import fs from 'fs'; import { deafultHTML } from './defaultHTML'; +/** An optional configuration object for `generateEmail` */ interface GenerateEmailOptions { + /** HTML file path to override the base HTML. */ baseTemplate?: string; + /** CSS file path to override the base CSS styles. */ baseStyles?: string; + /** + * Placeholder text to replace the base CSS styles. + * @default 'EMAIL_BASE_STYLES' + */ baseStylesReplacementString?: string; + /** + * Placeholder text to replace the email body. + * @default 'EMAIL_BODY_CONTENT' + */ baseBodyReplacementString?: string; } +/** + * Function to convert React Email Layouts to HTML. + * @param {React.ReactElement} jsxElement - React email layout which needs to be converted. + * @param {Object} [options] - An optional param options for the additional configurations. + * @param {string} [options.baseTemplate] - HTML file path to override the base HTML. + * @param {string} [options.baseStyles] - CSS file path to override the base CSS styles. + * @param {string} [options.baseStylesReplacementString='EMAIL_BASE_STYLES'] - Placeholder text to replace the base CSS styles. + * @param {string} [options.baseBodyReplacementString='EMAIL_BODY_CONTENT'] - Placeholder text to replace the email body. + * @returns {string} HTML version of the email in string format. + * @example + * import { generateEmail } from '@leopardslab/react-email'; + * import { EmailLayout } from './EmailLayout'; + * const html = generateEmail(EmailLayout()); + * console.log(html); + */ + export const generateEmail = ( jsxElement: React.ReactElement, options?: GenerateEmailOptions, diff --git a/src/utils/generateTextEmail/generateTextEmail.ts b/src/utils/generateTextEmail/generateTextEmail.ts index 7dca42a..111573f 100644 --- a/src/utils/generateTextEmail/generateTextEmail.ts +++ b/src/utils/generateTextEmail/generateTextEmail.ts @@ -1,6 +1,17 @@ import { generateEmail } from '../generateEmail'; import { generateTextEmailFromHTML } from '../generateTextEmailFromHTML'; +/** + * Function to convert React Email Layouts to Text version. + * @param {JSX.Element} jsxElement - React email layout which needs to be converted. + * @returns {string} Text version of the email in string format. + * @example + * import { generateTextEmail } from '@leopardslab/react-email'; + * import { EmailLayout } from './EmailLayout'; + * const text = generateTextEmail(EmailLayout()); + * console.log(text); + */ + export const generateTextEmail = (jsxElement: JSX.Element): string => { const HTML = generateEmail(jsxElement); const plainText = generateTextEmailFromHTML(HTML); diff --git a/src/utils/generateTextEmailFromHTML/generateTextEmailFromHTML.ts b/src/utils/generateTextEmailFromHTML/generateTextEmailFromHTML.ts index 4573107..9c00309 100644 --- a/src/utils/generateTextEmailFromHTML/generateTextEmailFromHTML.ts +++ b/src/utils/generateTextEmailFromHTML/generateTextEmailFromHTML.ts @@ -15,6 +15,12 @@ const headingFormatter = builder.closeBlock({ trailingLineBreaks: formatOptions.trailingLineBreaks || 1 }); }; +/** + * Function to convert HTML Email to Text version. + * @param {string} html - HTML which needs to be converted. + * @returns {string} Text version of the email in string format. + */ + export const generateTextEmailFromHTML = (html: string): string => { const plainText = convert(html, { formatters: { diff --git a/src/utils/makeStyles/makeStyles.ts b/src/utils/makeStyles/makeStyles.ts index 1bac38e..f8050d0 100644 --- a/src/utils/makeStyles/makeStyles.ts +++ b/src/utils/makeStyles/makeStyles.ts @@ -19,6 +19,12 @@ const mergeStyles = (originalClasses: CSSClasses, overrideClasses: CSSClasses): return newClasses; }; +/** + * Function which revokes a hook to combine and merge classes. + * @param classes - The classes to be merged with the override classes + * @returns The `useStyles` hook to combine and merge classes. + */ + export const makeStyles = (classes: CSSClasses) => { return (options?: overrideOptions) => { const overrideClasses = options?.classes; diff --git a/src/utils/sx/sx.ts b/src/utils/sx/sx.ts index 54b2e3e..3250bda 100644 --- a/src/utils/sx/sx.ts +++ b/src/utils/sx/sx.ts @@ -2,6 +2,12 @@ import { CSSProperties } from 'react'; type SXProps = CSSProperties | false | undefined; +/** + * Function to merge CSSProperties. + * @param args - The CSSProperties to be merged with the override CSSProperties + * @returns The merged CSSProperties. + */ + export const sx = (...args: SXProps[]): CSSProperties => { const initialValue: CSSProperties = {}; diff --git a/tsconfig.json b/tsconfig.json index eeb4efc..7d2a8a3 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -25,6 +25,10 @@ "jsx": "react-jsx", "pretty": true }, + "typedocOptions": { + "entryPoints": ["./src/"], + "out": "typedoc" + }, "include": ["src/**/*"], "exclude": ["node_modules"] } diff --git a/yarn.lock b/yarn.lock index a50e112..a04eeca 100644 --- a/yarn.lock +++ b/yarn.lock @@ -9778,6 +9778,11 @@ json5@^2.1.2, json5@^2.1.3, json5@^2.2.1: resolved "https://registry.yarnpkg.com/json5/-/json5-2.2.1.tgz#655d50ed1e6f95ad1a3caababd2b0efda10b395c" integrity sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA== +jsonc-parser@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.1.0.tgz#73b8f0e5c940b83d03476bc2e51a20ef0932615d" + integrity sha512-DRf0QjnNeCUds3xTjKlQQ3DpJD51GvDjJfnxUVWg6PZTo2otSm+slzNAxU/35hF8/oJIKoG9slq30JYOsF2azg== + jsonfile@^4.0.0: version "4.0.0" resolved "https://registry.yarnpkg.com/jsonfile/-/jsonfile-4.0.0.tgz#8771aae0799b64076b76640fca058f9c10e33ecb" @@ -10232,6 +10237,11 @@ lru-cache@^7.4.4, lru-cache@^7.5.1, lru-cache@^7.7.1: resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-7.10.1.tgz#db577f42a94c168f676b638d15da8fb073448cab" integrity sha512-BQuhQxPuRl79J5zSXRP+uNzPOyZw2oFI9JLRQ80XswSvg21KMKNtQza9eF42rfI/3Z40RvzBdXgziEkudzjo8A== +lunr@^2.3.9: + version "2.3.9" + resolved "https://registry.yarnpkg.com/lunr/-/lunr-2.3.9.tgz#18b123142832337dd6e964df1a5a7707b25d35e1" + integrity sha512-zTU3DaZaF3Rt9rhN3uBMGQD3dD2/vFQqnvZCDv4dl5iOzq2IZQqTxu90r4E5J+nP70J3ilqVCrbho2eWaeW8Ow== + lz-string@^1.4.4: version "1.4.4" resolved "https://registry.yarnpkg.com/lz-string/-/lz-string-1.4.4.tgz#c0d8eaf36059f705796e1e344811cf4c498d3a26" @@ -10357,6 +10367,11 @@ marked@^4.0.10: resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.17.tgz#1186193d85bb7882159cdcfc57d1dfccaffb3fe9" integrity sha512-Wfk0ATOK5iPxM4ptrORkFemqroz0ZDxp5MWfYA7H/F+wO17NRWV5Ypxi6p3g2Xmw2bKeiYOl6oVnLHKxBA0VhA== +marked@^4.0.18: + version "4.0.18" + resolved "https://registry.yarnpkg.com/marked/-/marked-4.0.18.tgz#cd0ac54b2e5610cfb90e8fd46ccaa8292c9ed569" + integrity sha512-wbLDJ7Zh0sqA0Vdg6aqlbT+yPxqLblpAZh1mK2+AO2twQkPywvvqQNfEPVwSSRjZ7dZcdeVBIAgiO7MMp3Dszw== + md5.js@^1.3.4: version "1.3.5" resolved "https://registry.yarnpkg.com/md5.js/-/md5.js-1.3.5.tgz#b5d07b8e3216e3e27cd728d72f70d1e6a342005f" @@ -10608,7 +10623,7 @@ minimatch@^3.0.2, minimatch@^3.0.4, minimatch@^3.1.1, minimatch@^3.1.2: dependencies: brace-expansion "^1.1.7" -minimatch@^5.0.1: +minimatch@^5.0.1, minimatch@^5.1.0: version "5.1.0" resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-5.1.0.tgz#1717b464f4971b144f6aabe8f2d0b8e4511e09c7" integrity sha512-9TPBGGak4nHfGZsPBohm9AWg6NoT7QTCehS3BIJABslyZbzxfV78QM2Y6+i741OPZIafFAaiiEMh5OyIrJPgtg== @@ -13213,6 +13228,15 @@ shebang-regex@^3.0.0: resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== +shiki@^0.10.1: + version "0.10.1" + resolved "https://registry.yarnpkg.com/shiki/-/shiki-0.10.1.tgz#6f9a16205a823b56c072d0f1a0bcd0f2646bef14" + integrity sha512-VsY7QJVzU51j5o1+DguUd+6vmCmZ5v/6gYu4vyYAhzjuNQU6P/vmSy4uQaOhvje031qQMiW0d2BwgMH52vqMng== + dependencies: + jsonc-parser "^3.0.0" + vscode-oniguruma "^1.6.1" + vscode-textmate "5.2.0" + side-channel@^1.0.4: version "1.0.4" resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" @@ -14223,6 +14247,16 @@ typedarray@^0.0.6: resolved "https://registry.yarnpkg.com/typedarray/-/typedarray-0.0.6.tgz#867ac74e3864187b1d3d47d996a78ec5c8830777" integrity sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA== +typedoc@^0.23.10: + version "0.23.10" + resolved "https://registry.yarnpkg.com/typedoc/-/typedoc-0.23.10.tgz#285d595a5f2e35ccdf6f38eba4dfe951d5bff461" + integrity sha512-03EUiu/ZuScUBMnY6p0lY+HTH8SwhzvRE3gImoemdPDWXPXlks83UGTx++lyquWeB1MTwm9D9Ca8RIjkK3AFfQ== + dependencies: + lunr "^2.3.9" + marked "^4.0.18" + minimatch "^5.1.0" + shiki "^0.10.1" + typescript@^4.6.4, typescript@^4.7.3: version "4.7.3" resolved "https://registry.yarnpkg.com/typescript/-/typescript-4.7.3.tgz#8364b502d5257b540f9de4c40be84c98e23a129d" @@ -14573,6 +14607,16 @@ vm-browserify@^1.0.1: resolved "https://registry.yarnpkg.com/vm-browserify/-/vm-browserify-1.1.2.tgz#78641c488b8e6ca91a75f511e7a3b32a86e5dda0" integrity sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ== +vscode-oniguruma@^1.6.1: + version "1.6.2" + resolved "https://registry.yarnpkg.com/vscode-oniguruma/-/vscode-oniguruma-1.6.2.tgz#aeb9771a2f1dbfc9083c8a7fdd9cccaa3f386607" + integrity sha512-KH8+KKov5eS/9WhofZR8M8dMHWN2gTxjMsG4jd04YhpbPR91fUj7rYQ2/XjeHCJWbg7X++ApRIU9NUwM2vTvLA== + +vscode-textmate@5.2.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/vscode-textmate/-/vscode-textmate-5.2.0.tgz#01f01760a391e8222fe4f33fbccbd1ad71aed74e" + integrity sha512-Uw5ooOQxRASHgu6C7GVvUxisKXfSgW4oFlO+aa+PAkgmH89O3CXxEEzNRNtHSqtXFTl0nAC1uYj0GMSH27uwtQ== + walk-up-path@^1.0.0: version "1.0.0" resolved "https://registry.yarnpkg.com/walk-up-path/-/walk-up-path-1.0.0.tgz#d4745e893dd5fd0dbb58dd0a4c6a33d9c9fec53e"