UNPKG

@wordpress/block-library

Version:
8 lines (7 loc) 7.39 kB
{ "version": 3, "sources": ["../../../src/navigation-link/shared/use-link-preview.js"], "sourcesContent": ["/**\n * WordPress dependencies\n */\nimport { __ } from '@wordpress/i18n';\nimport { safeDecodeURI } from '@wordpress/url';\nimport { privateApis as blockEditorPrivateApis } from '@wordpress/block-editor';\n\n/**\n * Internal dependencies\n */\nimport { unlock } from '../../lock-unlock';\n\nconst { useRemoteUrlData } = unlock( blockEditorPrivateApis );\n\n/**\n * Capitalize the first letter of a string.\n *\n * @param {string} str - The string to capitalize\n * @return {string} Capitalized string\n */\nfunction capitalize( str ) {\n\treturn str.charAt( 0 ).toUpperCase() + str.slice( 1 );\n}\n\n/**\n * Compute display URL - strips site URL if internal, shows full URL if external.\n *\n * @param {string} url - The URL to process\n * @return {Object} Object with displayUrl and isExternal flag\n */\nfunction computeDisplayUrl( url ) {\n\tif ( ! url ) {\n\t\treturn { displayUrl: '', isExternal: false };\n\t}\n\n\tlet displayUrl = safeDecodeURI( url );\n\tlet isExternal = false;\n\n\ttry {\n\t\tconst linkUrl = new URL( url );\n\t\tconst siteUrl = window.location.origin;\n\t\tif ( linkUrl.origin === siteUrl ) {\n\t\t\t// Show only the pathname (and search/hash if present)\n\t\t\tlet path = linkUrl.pathname + linkUrl.search + linkUrl.hash;\n\t\t\t// Remove trailing slash\n\t\t\tif ( path.endsWith( '/' ) && path.length > 1 ) {\n\t\t\t\tpath = path.slice( 0, -1 );\n\t\t\t}\n\t\t\tdisplayUrl = path;\n\t\t} else {\n\t\t\tisExternal = true;\n\t\t}\n\t} catch ( e ) {\n\t\t// If URL parsing fails, use the original URL\n\t\tdisplayUrl = safeDecodeURI( url );\n\t}\n\n\treturn { displayUrl, isExternal };\n}\n\n/**\n * Compute badges for the link preview.\n *\n * @param {Object} options - Options object\n * @param {string} options.url - Link URL\n * @param {string} options.type - Entity type (page, post, etc.)\n * @param {boolean} options.isExternal - Whether link is external\n * @param {string} options.entityStatus - Entity status (publish, draft, etc.)\n * @param {boolean} options.hasBinding - Whether link has entity binding\n * @param {boolean} options.isEntityAvailable - Whether bound entity exists\n * @return {Array} Array of badge objects with label and intent\n */\nfunction computeBadges( {\n\turl,\n\ttype,\n\tisExternal,\n\tentityStatus,\n\thasBinding,\n\tisEntityAvailable,\n} ) {\n\tconst badges = [];\n\n\t// Kind badge\n\tif ( url ) {\n\t\tif ( isExternal ) {\n\t\t\tbadges.push( {\n\t\t\t\tlabel: __( 'External link' ),\n\t\t\t\tintent: 'default',\n\t\t\t} );\n\t\t} else if ( type ) {\n\t\t\tbadges.push( { label: capitalize( type ), intent: 'default' } );\n\t\t}\n\t}\n\n\t// Status badge\n\tif ( ! url ) {\n\t\tbadges.push( { label: __( 'No link selected' ), intent: 'error' } );\n\t} else if ( hasBinding && ! isEntityAvailable ) {\n\t\tbadges.push( { label: __( 'Deleted' ), intent: 'error' } );\n\t} else if ( entityStatus ) {\n\t\tconst statusMap = {\n\t\t\tpublish: { label: __( 'Published' ), intent: 'success' },\n\t\t\tfuture: { label: __( 'Scheduled' ), intent: 'warning' },\n\t\t\tdraft: { label: __( 'Draft' ), intent: 'warning' },\n\t\t\tpending: { label: __( 'Pending' ), intent: 'warning' },\n\t\t\tprivate: { label: __( 'Private' ), intent: 'default' },\n\t\t\ttrash: { label: __( 'Trash' ), intent: 'error' },\n\t\t};\n\t\tconst badge = statusMap[ entityStatus ];\n\t\tif ( badge ) {\n\t\t\tbadges.push( badge );\n\t\t}\n\t}\n\n\treturn badges;\n}\n\n/**\n * Hook to compute link preview data for display.\n *\n * This hook takes raw link data and entity information and computes\n * presentation-ready preview data including formatted title, URL, and badges.\n *\n * @param {Object} options - Options object\n * @param {string} options.url - Link URL\n * @param {string} options.title - Link title (from entity or rich data)\n * @param {string} options.image - Link image URL\n * @param {string} options.type - Entity type (page, post, etc.)\n * @param {string} options.entityStatus - Entity status (publish, draft, etc.)\n * @param {boolean} options.hasBinding - Whether link has entity binding\n * @param {boolean} options.isEntityAvailable - Whether bound entity exists\n * @return {Object} Preview data object with title, url, image, and badges\n */\nexport function useLinkPreview( {\n\turl,\n\ttitle,\n\timage,\n\ttype,\n\tentityStatus,\n\thasBinding,\n\tisEntityAvailable,\n} ) {\n\t// Fetch rich URL data if we don't have a title. Internal links should have passed a title.\n\tconst { richData } = useRemoteUrlData( title ? null : url );\n\n\t// Compute display URL and external flag\n\tconst { displayUrl, isExternal } = computeDisplayUrl( url );\n\n\t// Compute badges\n\tconst badges = computeBadges( {\n\t\turl,\n\t\ttype,\n\t\tisExternal,\n\t\tentityStatus,\n\t\thasBinding,\n\t\tisEntityAvailable,\n\t} );\n\n\t// Get display title - use provided title, fallback to rich data, or URL\n\tconst displayTitle = url\n\t\t? title || richData?.title || safeDecodeURI( url )\n\t\t: __( 'Add link' );\n\n\treturn {\n\t\ttitle: displayTitle,\n\t\turl: displayUrl,\n\t\timage,\n\t\tbadges,\n\t};\n}\n"], "mappings": "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", "names": [] }