@@ -6,8 +6,10 @@ definePageMeta({
66 name: ' compare' ,
77})
88
9+ const { locale } = useI18n ()
910const router = useRouter ()
1011const canGoBack = useCanGoBack ()
12+ const { copied, copy } = useClipboard ({ copiedDuring: 2000 })
1113
1214// Sync packages with URL query param (stable ref - doesn't change on other query changes)
1315const packagesParam = useRouteQuery <string >(' packages' , ' ' , { mode: ' replace' })
@@ -79,6 +81,57 @@ const gridHeaders = computed(() =>
7981 gridColumns .value .map (col => (col .version ? ` ${col .name }@${col .version } ` : col .name )),
8082)
8183
84+ /*
85+ * Convert the comparison grid data to a Markdown table.
86+ */
87+ function exportComparisonDataAsMarkdown() {
88+ const mdData: Array <Array <string >> = []
89+ const headers = [
90+ ' ' ,
91+ ... gridHeaders .value ,
92+ ... (showNoDependency .value ? [$t (' compare.no_dependency.label' )] : []),
93+ ]
94+ mdData .push (headers )
95+ const maxLengths = headers .map (item => item .length )
96+
97+ selectedFacets .value .forEach ((facet , index ) => {
98+ const label = facet .label
99+ const data = getFacetValues (facet .id )
100+ mdData .push ([
101+ label ,
102+ ... data .map (item =>
103+ item ?.type === ' date'
104+ ? new Date (item .display ).toLocaleDateString (locale .value , {
105+ year: ' numeric' ,
106+ month: ' short' ,
107+ day: ' numeric' ,
108+ })
109+ : item ?.display || ' ' ,
110+ ),
111+ ])
112+ mdData ?.[index + 1 ]?.forEach ((item , itemIndex ) => {
113+ if (item .length > (maxLengths ?.[itemIndex ] || 0 )) {
114+ maxLengths [itemIndex ] = item .length
115+ }
116+ })
117+ })
118+
119+ const markdown = mdData .reduce ((result , row , index ) => {
120+ // replacing pipe `|` with `ǀ` (U+01C0 Latin Letter Dental Click) to avoid breaking tables
121+ result += ` | ${row
122+ .map ((el , ind ) => el .padEnd (maxLengths [ind ] || 0 , ' ' ).replace (/ \| / g , ' ǀ' ))
123+ .join (' | ' )} | `
124+ if (index === 0 ) {
125+ result += ` \n |`
126+ maxLengths .forEach (len => (result += ` ${' -' .padEnd (len , ' -' )} | ` ))
127+ }
128+ result += ` \n `
129+ return result
130+ }, ' ' )
131+
132+ copy (markdown )
133+ }
134+
82135useSeoMeta ({
83136 title : () =>
84137 packages .value .length > 0
@@ -193,7 +246,24 @@ useSeoMeta({
193246
194247 <!-- Comparison grid -->
195248 <section v-if =" canCompare" class =" mt-10" aria-labelledby =" comparison-heading" >
196- <h2 id =" comparison-heading" class =" text-xs text-fg-subtle uppercase tracking-wider mb-4" >
249+ <CopyToClipboardButton
250+ v-if =" packagesData && packagesData.some(p => p !== null)"
251+ :copied =" copied"
252+ :copy-text =" $t('compare.packages.copy_as_markdown')"
253+ class =" mb-4"
254+ :button-attrs =" { class: 'hidden md:inline-flex' }"
255+ @click =" exportComparisonDataAsMarkdown"
256+ >
257+ <h2 id =" comparison-heading" class =" text-xs text-fg-subtle uppercase tracking-wider" >
258+ {{ $t('compare.packages.section_comparison') }}
259+ </h2 >
260+ </CopyToClipboardButton >
261+
262+ <h2
263+ v-else
264+ id =" comparison-heading"
265+ class =" text-xs text-fg-subtle uppercase tracking-wider mb-4"
266+ >
197267 {{ $t('compare.packages.section_comparison') }}
198268 </h2 >
199269
@@ -241,7 +311,7 @@ useSeoMeta({
241311 </div >
242312
243313 <h2
244- id =" comparison-heading"
314+ id =" trends- comparison-heading"
245315 class =" text-xs text-fg-subtle uppercase tracking-wider mb-4 mt-10"
246316 >
247317 {{ $t('compare.facets.trends.title') }}
0 commit comments