11import { isLinkWithProtocol } from '@vuepress/shared'
2- import type { SlotsType , VNode } from 'vue'
3- import { computed , defineComponent , h } from 'vue'
2+ import type { PropType , SlotsType , VNode } from 'vue'
3+ import { computed , defineComponent , h , toRef } from 'vue'
44import { useRoute } from 'vue-router'
55import { useSiteData } from '../composables/index.js'
66import { RouteLink } from './RouteLink.js'
77
8- export interface AutoLinkProps {
8+ export interface AutoLinkConfig {
99 /**
1010 * Pattern to determine if the link should be active, which has higher priority than `exact`
1111 */
@@ -51,57 +51,11 @@ export interface AutoLinkProps {
5151export const AutoLink = defineComponent ( {
5252 name : 'AutoLink' ,
5353
54- props : {
55- /**
56- * Pattern to determine if the link should be active, which has higher priority than `exact`
57- */
58- activeMatch : {
59- type : [ String , RegExp ] ,
60- default : '' ,
61- } ,
62-
63- /**
64- * The `aria-label` attribute
65- */
66- ariaLabel : {
67- type : String ,
68- default : '' ,
69- } ,
70-
71- /**
72- * Whether the link should be active only if the url is an exact match
73- */
74- exact : Boolean ,
75-
76- /**
77- * URL of the auto link
78- */
79- link : {
80- type : String ,
81- required : true ,
82- } ,
83-
84- /**
85- * The `rel` attribute
86- */
87- rel : {
88- type : String ,
89- default : '' ,
90- } ,
54+ inheritAttrs : false ,
9155
92- /**
93- * The `target` attribute
94- */
95- target : {
96- type : String ,
97- default : '' ,
98- } ,
99-
100- /**
101- * Text of the auto link
102- */
103- text : {
104- type : String ,
56+ props : {
57+ config : {
58+ type : Object as PropType < AutoLinkConfig > ,
10559 required : true ,
10660 } ,
10761 } ,
@@ -113,15 +67,16 @@ export const AutoLink = defineComponent({
11367 } > ,
11468
11569 setup ( props , { slots } ) {
70+ const config = toRef ( props , 'config' )
11671 const route = useRoute ( )
11772 const siteData = useSiteData ( )
11873
11974 // If the link has non-http protocol
120- const withProtocol = computed ( ( ) => isLinkWithProtocol ( props . link ) )
75+ const withProtocol = computed ( ( ) => isLinkWithProtocol ( config . value . link ) )
12176
12277 // Resolve the `target` attr
12378 const linkTarget = computed (
124- ( ) => props . target || ( withProtocol . value ? '_blank' : undefined ) ,
79+ ( ) => config . value . target || ( withProtocol . value ? '_blank' : undefined ) ,
12580 )
12681
12782 // If the `target` attr is "_blank"
@@ -134,57 +89,65 @@ export const AutoLink = defineComponent({
13489
13590 // Resolve the `rel` attr
13691 const linkRel = computed (
137- ( ) => props . rel || ( isBlankTarget . value ? 'noopener noreferrer' : null ) ,
92+ ( ) =>
93+ config . value . rel ||
94+ ( isBlankTarget . value ? 'noopener noreferrer' : null ) ,
13895 )
13996
14097 // Resolve the `aria-label` attr
141- const linkAriaLabel = computed ( ( ) => props . ariaLabel ?? props . text )
98+ const linkAriaLabel = computed (
99+ ( ) => config . value . ariaLabel ?? config . value . text ,
100+ )
142101
143102 // Should be active when current route is a subpath of this link
144103 const shouldBeActiveInSubpath = computed ( ( ) => {
145104 // Should not be active in `exact` mode
146- if ( props . exact ) return false
105+ if ( config . value . exact ) return false
147106
148107 const localePaths = Object . keys ( siteData . value . locales )
149108
150109 return localePaths . length
151110 ? // Check all the locales
152- localePaths . every ( ( key ) => key !== props . link )
111+ localePaths . every ( ( key ) => key !== config . value . link )
153112 : // Check root
154- props . link !== '/'
113+ config . value . link !== '/'
155114 } )
156115
157116 // If this link is active
158117 const isActive = computed ( ( ) => {
159118 if ( ! isInternal . value ) return false
160119
161- if ( props . activeMatch ) {
120+ if ( config . value . activeMatch ) {
162121 return (
163- props . activeMatch instanceof RegExp
164- ? props . activeMatch
165- : new RegExp ( props . activeMatch , 'u' )
122+ config . value . activeMatch instanceof RegExp
123+ ? config . value . activeMatch
124+ : new RegExp ( config . value . activeMatch , 'u' )
166125 ) . test ( route . path )
167126 }
168127
169128 // If this link is active in subpath
170129 if ( shouldBeActiveInSubpath . value ) {
171- return route . path . startsWith ( props . link )
130+ return route . path . startsWith ( config . value . link )
172131 }
173132
174- return route . path === props . link
133+ return route . path === config . value . link
175134 } )
176135
177136 return ( ) => {
178137 const { before, after, default : defaultSlot } = slots
179138
180- const content = defaultSlot ?.( ) || [ before ?.( ) , props . text , after ?.( ) ]
139+ const content = defaultSlot ?.( ) || [
140+ before ?.( ) ,
141+ config . value . text ,
142+ after ?.( ) ,
143+ ]
181144
182145 return isInternal . value
183146 ? h (
184147 RouteLink ,
185148 {
186149 'class' : 'auto-link' ,
187- 'to' : props . link ,
150+ 'to' : config . value . link ,
188151 'active' : isActive . value ,
189152 'aria-label' : linkAriaLabel . value ,
190153 } ,
@@ -194,7 +157,7 @@ export const AutoLink = defineComponent({
194157 'a' ,
195158 {
196159 'class' : 'auto-link external-link' ,
197- 'href' : props . link ,
160+ 'href' : config . value . link ,
198161 'aria-label' : linkAriaLabel . value ,
199162 'rel' : linkRel . value ,
200163 'target' : linkTarget . value ,
0 commit comments