-
Notifications
You must be signed in to change notification settings - Fork 277
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
[wip] refactor: refactor mobile site #2808
base: dev
Are you sure you want to change the base?
Conversation
WalkthroughThe pull request involves a consistent CSS styling modification across multiple Vue components in the mobile demo application. Specifically, the changes alter the Changes
Suggested Labels
Suggested Reviewers
Poem
Thank you for using CodeRabbit. We offer it for free to the OSS community and would appreciate your support in helping us grow. If you find it useful, would you consider giving us a shout-out on your favorite social media? 🪧 TipsChatThere are 3 ways to chat with CodeRabbit:
Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments. CodeRabbit Commands (Invoked using PR comments)
Other keywords and placeholders
CodeRabbit Configuration File (
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 2
🧹 Nitpick comments (2)
examples/sites/demos/mobile/app/button/event.vue (1)
39-41
: Consider mobile-specific height handling.While changing
overflow-y
toauto
improves the UI by showing scrollbars only when needed, using a fixedheight: 100%
might cause issues on mobile devices with dynamic viewport heights (e.g., when the keyboard appears).Consider using
min-height
or viewport units:.button-wrap { padding: 0 10px; overflow-y: auto; - height: 100%; + min-height: 100vh; }examples/sites/demos/mobile/app/button/size.vue (1)
46-48
: Consider grid layout for button examples.The overflow handling looks good, but with multiple button examples, consider using a responsive grid layout to improve the mobile viewing experience.
Add a grid layout for better organization:
.button-wrap { padding: 0 10px; overflow-y: auto; height: 100%; + display: grid; + grid-template-columns: repeat(auto-fill, minmax(150px, 1fr)); + gap: 16px; } .button-wrap .tiny-mobile-button { - margin-right: 16px; - margin-bottom: 16px; }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (14)
examples/sites/demos/mobile/app/button/base.vue
(1 hunks)examples/sites/demos/mobile/app/button/disabled.vue
(1 hunks)examples/sites/demos/mobile/app/button/event.vue
(1 hunks)examples/sites/demos/mobile/app/button/loading.vue
(1 hunks)examples/sites/demos/mobile/app/button/reset-time.vue
(1 hunks)examples/sites/demos/mobile/app/button/size.vue
(1 hunks)examples/sites/demos/mobile/app/input/textarea-scalable.vue
(1 hunks)examples/sites/demos/mobile/app/input/type.vue
(1 hunks)examples/sites/demos/mobile/app/list/imformation-list.vue
(1 hunks)examples/sites/demos/mobile/app/radio/base.vue
(1 hunks)examples/sites/demos/mobile/app/radio/disabled.vue
(1 hunks)examples/sites/demos/mobile/app/radio/event.vue
(1 hunks)examples/sites/demos/mobile/app/radio/label.vue
(1 hunks)examples/sites/src/views/components/components.vue
(2 hunks)
✅ Files skipped from review due to trivial changes (11)
- examples/sites/demos/mobile/app/radio/disabled.vue
- examples/sites/demos/mobile/app/radio/label.vue
- examples/sites/demos/mobile/app/radio/base.vue
- examples/sites/demos/mobile/app/button/disabled.vue
- examples/sites/demos/mobile/app/radio/event.vue
- examples/sites/demos/mobile/app/input/textarea-scalable.vue
- examples/sites/demos/mobile/app/button/reset-time.vue
- examples/sites/demos/mobile/app/input/type.vue
- examples/sites/demos/mobile/app/button/base.vue
- examples/sites/demos/mobile/app/button/loading.vue
- examples/sites/demos/mobile/app/list/imformation-list.vue
<div style="width: 300px; height: 500px"> | ||
<iframe width="100%" height="100%" :src="mobilePreviewUrl" frameborder="0"></iframe> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance the mobile preview container for better responsiveness and accessibility.
The mobile preview container needs improvements in several areas:
- Replace fixed dimensions with responsive units
- Add accessibility attributes
- Add loading and error states
- <div style="width: 300px; height: 500px">
- <iframe width="100%" height="100%" :src="mobilePreviewUrl" frameborder="0"></iframe>
+ <div class="mobile-preview-container">
+ <iframe
+ class="mobile-preview-frame"
+ :src="mobilePreviewUrl"
+ :title="i18nByKey('mobile-preview')"
+ frameborder="0"
+ @load="handleIframeLoad"
+ @error="handleIframeError"
+ ></iframe>
+ <div v-if="isIframeLoading" class="mobile-preview-loading">
+ <tiny-loading></tiny-loading>
+ </div>
+ <div v-if="iframeError" class="mobile-preview-error">
+ {{ i18nByKey('preview-error') }}
+ </div>
</div>
Add these styles to your <style>
section:
.mobile-preview-container {
width: min(300px, 100%);
height: 500px;
position: relative;
margin: 0 auto;
}
.mobile-preview-frame {
width: 100%;
height: 100%;
border: none;
}
.mobile-preview-loading,
.mobile-preview-error {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
display: flex;
align-items: center;
justify-content: center;
background: rgba(255, 255, 255, 0.9);
}
@@ -705,9 +708,11 @@ | |||
|
|||
const hasKey = (apiArr, key) => !apiArr.every((item) => item[key] === undefined) | |||
|
|||
const mobilePreviewUrl = `${import.meta.env.VITE_MOBILE_URL}?component=button&demo=base.vue` |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Make the mobile preview URL dynamic based on current component and demo.
The current implementation uses hardcoded values for component and demo parameters. This should be dynamic based on the current context.
- const mobilePreviewUrl = `${import.meta.env.VITE_MOBILE_URL}?component=button&demo=base.vue`
+ const mobilePreviewUrl = computed(() => {
+ if (!import.meta.env.VITE_MOBILE_URL) {
+ console.error('Mobile preview URL environment variable is not defined')
+ return ''
+ }
+ const component = state.cmpId
+ const demo = state.singleDemo?.demoId || ''
+ return `${import.meta.env.VITE_MOBILE_URL}?component=${component}&demo=${demo}`
+ })
Also applies to: 715-715
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🧹 Nitpick comments (3)
examples/sites/src/views/components/demo.vue (3)
56-60
: Add aria-label to improve accessibility.The mobile view button should have an aria-label for better screen reader support.
- <div class="mobile-view-btn"> - <tiny-button>{{ i18nByKey('yan-shi') }}</tiny-button> + <div class="mobile-view-btn"> + <tiny-button aria-label="Mobile preview">{{ i18nByKey('yan-shi') }}</tiny-button>
67-70
: Consider adding placeholder content or loading state.The mobile view container is empty. Consider adding a placeholder or loading state to improve user experience.
- <div class="phone-container"></div> + <div class="phone-container"> + <div class="phone-container-placeholder" aria-label="Mobile preview loading"> + <tiny-loading v-if="isLoading" /> + <div v-else class="placeholder-text">{{ i18nByKey('preview-placeholder') }}</div> + </div> + </div>
72-76
: Consider extracting repeated width logic.The width styling is duplicated from the demo content. Consider extracting it to a computed property or CSS variable for better maintainability.
+<script> export default { // ... other code ... computed: { + containerWidth() { + return this.demoConfig.isMobile ? 'width:60%' : 'width:100%' + } } } </script> <template> - <div class="demo-content" :style="demoConfig.isMobile ? 'width:60%' : 'width:100%'"> + <div class="demo-content" :style="containerWidth"> <!-- ... --> - <div class="demo-code" :style="demoConfig.isMobile ? 'width:60%' : 'width:100%'"> + <div class="demo-code" :style="containerWidth">
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
examples/sites/src/views/components/demo.vue
(3 hunks)
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (1)
examples/sites/src/views/components/demo.vue (1)
8-8
: LGTM! Clean implementation of responsive width.The conditional width styling provides a good balance between mobile and desktop layouts.
height: 600px; | ||
border: 0; | ||
position: relative; | ||
position: fixed; | ||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYsAAAMFCAYAAACFxdoKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg3MTZDNTAwMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjg3MTZDNTAxMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODcxNkM0RkUxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODcxNkM0RkYxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7YMDcrAAAcl0lEQVR42uzd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) | ||
no-repeat center top; | ||
background-size: contain; | ||
|
||
.mobile-view-container { | ||
width: 360px; | ||
height: 613px; | ||
position: absolute; | ||
left: 11px; | ||
top: 79px; | ||
transform: i18nByKeyX(0); | ||
overflow: hidden; | ||
} | ||
left: 65%; | ||
right: 10%; | ||
top: 30%; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve responsive layout handling.
The fixed positioning with percentage-based offsets might cause layout issues on different screen sizes. Consider:
- Using CSS Grid or Flexbox for more flexible positioning
- Adding media queries for better responsiveness
- Using viewport units instead of fixed percentages
.phone-container {
width: 395px;
height: 600px;
border: 0;
position: fixed;
- left: 65%;
- right: 10%;
- top: 30%;
+ position: absolute;
+ left: 50%;
+ top: 50%;
+ transform: translate(-50%, -50%);
+ max-width: 90vw;
+ max-height: 80vh;
}
+
+@media screen and (max-width: 768px) {
+ .phone-container {
+ width: 100%;
+ height: auto;
+ aspect-ratio: 395/600;
+ }
+}
Committable suggestion skipped: line range outside the PR's diff.
7445257
to
a67e83e
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (2)
examples/sites/src/views/components/components.vue
(11 hunks)examples/sites/src/views/components/demo.vue
(6 hunks)
🔇 Additional comments (9)
examples/sites/src/views/components/demo.vue (7)
11-11
: Good use of centralized state management!The transition to using
state.langKey
,state.copyTip
, andstate.copyIcon
improves reactivity and state management.Also applies to: 18-18, 21-21
Line range hint
38-38
: Well-implemented event handling for mobile preview!The
@get-iframe-demo
event handler is consistently applied in both default and single demo modes, ensuring the mobile preview functionality works uniformly.Also applies to: 42-48
56-58
: Good improvements to mobile view container!The changes enhance clarity through:
- More semantic class naming with
mobile-demo-container
- Clear user interaction with the "演示" (demo) button for mobile preview
Line range hint
84-115
: Excellent adoption of Vue 3 best practices!The changes demonstrate good practices:
- Using
<script setup>
syntax with TypeScript- Well-defined props with proper types
- Explicit emits declaration
119-139
: Well-structured component and state setup!Good practices observed:
- Component name defined for debugging
- Logically grouped state properties
- Proper use of reactive state for UI elements
372-379
: Improve responsive layout handling.The fixed positioning with percentage-based offsets might cause layout issues on different screen sizes. Consider:
- Using CSS Grid or Flexbox for more flexible positioning
- Adding media queries for better responsiveness
- Using viewport units instead of fixed percentages
Also applies to: 1105-1128
Line range hint
266-332
: Verify the demo file extension assumption.The code assumes all demo files have a .vue extension when constructing the iframe URL. This might cause issues if demos use different file extensions.
Run this script to check for non-.vue demo files:
examples/sites/src/views/components/components.vue (2)
164-171
: Enhance the mobile preview container for better responsiveness and accessibility.The mobile preview container needs improvements in several areas:
- Replace fixed dimensions with responsive units
- Add accessibility attributes
- Add loading and error states
581-586
: Make the mobile preview URL dynamic based on current component and demo.The current implementation uses hardcoded values for component and demo parameters. This should be dynamic based on the current context.
if (demoConfig.isMobile) { | ||
// 点击目录列表更新iframe显示 | ||
const hashId = data.link.slice(1) | ||
getIframeConetent(state.cmpId, hashId + '.vue') | ||
} | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation for hash IDs.
The direct use of hash IDs in URL construction without validation could lead to XSS vulnerabilities. Consider:
- Validating hash IDs against allowed patterns
- Encoding special characters in the URL
Apply this diff to add validation:
- const hashId = data.link.slice(1)
- getIframeConetent(state.cmpId, hashId + '.vue')
+ const hashId = data.link.slice(1)
+ if (!/^[a-zA-Z0-9-_]+$/.test(hashId)) {
+ console.error('Invalid hash ID')
+ return
+ }
+ const encodedHash = encodeURIComponent(hashId)
+ getIframeConetent(state.cmpId, encodedHash + '.vue')
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (demoConfig.isMobile) { | |
// 点击目录列表更新iframe显示 | |
const hashId = data.link.slice(1) | |
getIframeConetent(state.cmpId, hashId + '.vue') | |
} | |
if (demoConfig.isMobile) { | |
// 点击目录列表更新iframe显示 | |
const hashId = data.link.slice(1) | |
if (!/^[a-zA-Z0-9-_]+$/.test(hashId)) { | |
console.error('Invalid hash ID') | |
return | |
} | |
const encodedHash = encodeURIComponent(hashId) | |
getIframeConetent(state.cmpId, encodedHash + '.vue') | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 5
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
examples/sites/vite-dosearch-plugin.js
(0 hunks)examples/sites/vite.config.ts
(3 hunks)examples/sites/vite.extend.ts
(1 hunks)
💤 Files with no reviewable changes (1)
- examples/sites/vite-dosearch-plugin.js
⏰ Context from checks skipped due to timeout of 90000ms (1)
- GitHub Check: PR E2E Test (pnpm test:e2e3)
🔇 Additional comments (1)
examples/sites/vite.config.ts (1)
137-141
: Ensure 'tinyCustom.copyTarget' is properly defined after modifying the config.When adding the
viteStaticCopy
plugin, you accessnewViteConfig.tinyCustom.copyTarget
. Verify thattinyCustom.copyTarget
remains defined aftermodifyViteConfig
is called.
export const delStaticPlugin = () => { | ||
let config | ||
return { | ||
name: 'inline-plugin-del-static', | ||
apply: 'build', | ||
configResolved(_config) { | ||
config = _config | ||
}, | ||
async closeBundle() { | ||
const targetPath = path.join(config.build.outDir, '@demos') | ||
const files = await fg(['**/*.spec.js', '**/*.spec.ts'], { | ||
dot: true, | ||
cwd: targetPath | ||
}) | ||
files.forEach((filename) => { | ||
const filePath = path.join(targetPath, filename) | ||
fs.unlink(filePath) | ||
}) | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Import missing modules 'fs' and 'fast-glob' required by the plugin.
The delStaticPlugin
function uses fs.unlink
and fg
, but these modules are not imported. This will cause runtime errors when the plugin is executed.
Apply this diff to import the required modules at the top of the file:
+import fs from 'node:fs'
+import fg from 'fast-glob'
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
export const delStaticPlugin = () => { | |
let config | |
return { | |
name: 'inline-plugin-del-static', | |
apply: 'build', | |
configResolved(_config) { | |
config = _config | |
}, | |
async closeBundle() { | |
const targetPath = path.join(config.build.outDir, '@demos') | |
const files = await fg(['**/*.spec.js', '**/*.spec.ts'], { | |
dot: true, | |
cwd: targetPath | |
}) | |
files.forEach((filename) => { | |
const filePath = path.join(targetPath, filename) | |
fs.unlink(filePath) | |
}) | |
} | |
} | |
} | |
import fs from 'node:fs' | |
import fg from 'fast-glob' | |
export const delStaticPlugin = () => { | |
let config | |
return { | |
name: 'inline-plugin-del-static', | |
apply: 'build', | |
configResolved(_config) { | |
config = _config | |
}, | |
async closeBundle() { | |
const targetPath = path.join(config.build.outDir, '@demos') | |
const files = await fg(['**/*.spec.js', '**/*.spec.ts'], { | |
dot: true, | |
cwd: targetPath | |
}) | |
files.forEach((filename) => { | |
const filePath = path.join(targetPath, filename) | |
fs.unlink(filePath) | |
}) | |
} | |
} | |
} |
const demosPath = '../plusdocs/pc' | ||
const apisPath = '../plusdocs/apis' | ||
viteConfig.resolve.alias['@menu'] = path.resolve(demosPath) | ||
viteConfig.resolve.alias['@demo'] = path.resolve(demosPath) | ||
viteConfig.tinyCustom.copyTarget = [ | ||
{ | ||
src: `${demosPath}/*`, | ||
dest: '@demos' | ||
}, | ||
{ | ||
src: `${apisPath}/*`, | ||
dest: '@demos/apis' | ||
} | ||
] | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Ensure 'tinyCustom.copyTarget' and 'resolve.alias' are defined in 'plus' mode.
In the plus
function, you're assigning values to viteConfig.tinyCustom.copyTarget
and viteConfig.resolve.alias
, but these objects may not be initialized. This might cause runtime errors if they are undefined.
Initialize the properties before assignment:
+viteConfig.resolve = viteConfig.resolve || {}
+viteConfig.resolve.alias = viteConfig.resolve.alias || {}
+viteConfig.tinyCustom = viteConfig.tinyCustom || {}
+viteConfig.tinyCustom.copyTarget = viteConfig.tinyCustom.copyTarget || []
const demosPath = '../plusdocs/pc'
const apisPath = '../plusdocs/apis'
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const demosPath = '../plusdocs/pc' | |
const apisPath = '../plusdocs/apis' | |
viteConfig.resolve.alias['@menu'] = path.resolve(demosPath) | |
viteConfig.resolve.alias['@demo'] = path.resolve(demosPath) | |
viteConfig.tinyCustom.copyTarget = [ | |
{ | |
src: `${demosPath}/*`, | |
dest: '@demos' | |
}, | |
{ | |
src: `${apisPath}/*`, | |
dest: '@demos/apis' | |
} | |
] | |
} | |
viteConfig.resolve = viteConfig.resolve || {} | |
viteConfig.resolve.alias = viteConfig.resolve.alias || {} | |
viteConfig.tinyCustom = viteConfig.tinyCustom || {} | |
viteConfig.tinyCustom.copyTarget = viteConfig.tinyCustom.copyTarget || [] | |
const demosPath = '../plusdocs/pc' | |
const apisPath = '../plusdocs/apis' | |
viteConfig.resolve.alias['@menu'] = path.resolve(demosPath) | |
viteConfig.resolve.alias['@demo'] = path.resolve(demosPath) | |
viteConfig.tinyCustom.copyTarget = [ | |
{ | |
src: `${demosPath}/*`, | |
dest: '@demos' | |
}, | |
{ | |
src: `${apisPath}/*`, | |
dest: '@demos/apis' | |
} | |
] | |
} |
mobile(viteConfig) { | ||
viteConfig.build.rollupOptions.input.mobile = path.resolve(__dirname, './mobile.html') | ||
}, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initialize 'build.rollupOptions.input' before assignment in 'mobile' mode.
In the mobile
function within modeModifyMap
, viteConfig.build.rollupOptions.input
may not be initialized. Assigning a value without initialization can lead to runtime errors.
Apply this diff to ensure the nested properties are initialized:
+viteConfig.build = viteConfig.build || {}
+viteConfig.build.rollupOptions = viteConfig.build.rollupOptions || {}
+viteConfig.build.rollupOptions.input = viteConfig.build.rollupOptions.input || {}
viteConfig.build.rollupOptions.input.mobile = path.resolve(__dirname, './mobile.html')
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
mobile(viteConfig) { | |
viteConfig.build.rollupOptions.input.mobile = path.resolve(__dirname, './mobile.html') | |
}, | |
mobile(viteConfig) { | |
viteConfig.build = viteConfig.build || {} | |
viteConfig.build.rollupOptions = viteConfig.build.rollupOptions || {} | |
viteConfig.build.rollupOptions.input = viteConfig.build.rollupOptions.input || {} | |
viteConfig.build.rollupOptions.input.mobile = path.resolve(__dirname, './mobile.html') | |
}, |
} | ||
} | ||
} | ||
import { delStaticPlugin, viteDocsearchPlugin, modifyViteConfig } from './vite.extend.ts' |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Remove '.ts' extension from import path to ensure compatibility.
When importing modules, it's recommended to omit the file extension for consistency and to avoid potential issues with module resolution.
Apply this diff to correct the import statement:
-import { delStaticPlugin, viteDocsearchPlugin, modifyViteConfig } from './vite.extend.ts'
+import { delStaticPlugin, viteDocsearchPlugin, modifyViteConfig } from './vite.extend'
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
import { delStaticPlugin, viteDocsearchPlugin, modifyViteConfig } from './vite.extend.ts' | |
import { delStaticPlugin, viteDocsearchPlugin, modifyViteConfig } from './vite.extend' |
} | ||
} | ||
|
||
if (env.NODE_ENV === 'development') { | ||
viteConfig.define['process.env'] = {} | ||
} | ||
|
||
return viteConfig | ||
const newViteConfig = modifyViteConfig(viteConfig, env, { plugins: { viteStaticCopy } }) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Fix function call to 'modifyViteConfig': remove the unexpected third argument.
The function modifyViteConfig
is defined to accept two arguments (viteConfig
and env
), but it's being called with three arguments. This inconsistency may lead to unexpected behavior.
Apply this diff to correct the function call:
-const newViteConfig = modifyViteConfig(viteConfig, env, { plugins: { viteStaticCopy } })
+const newViteConfig = modifyViteConfig(viteConfig, env)
Committable suggestion skipped: line range outside the PR's diff.
…le modes on mobile devices will redirect to the first demo
…nto refactor-mobile-site
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 3
🧹 Nitpick comments (1)
examples/sites/src/views/components/components.vue (1)
1126-1134
: Improve mobile view container positioning.The mobile view container and iframe container use fixed dimensions and positioning which could cause layout issues.
Apply this diff to improve the layout:
.mobile-view-container { - width: 400px; + width: min(400px, 100%); + margin-left: auto; } .mobile-iframe-container { position: relative; - top: 10%; - left: 14%; + top: min(10%, 60px); + left: 50%; + transform: translateX(-50%); }
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (1)
examples/sites/src/views/components/components.vue
(12 hunks)
🔇 Additional comments (2)
examples/sites/src/views/components/components.vue (2)
38-38
: LGTM: Event handler consistently implemented.The
@get-iframe-demo
event handler is properly added to both single and multiple demo modes.Also applies to: 47-47
699-704
:⚠️ Potential issueAdd input validation for hash IDs.
The direct use of hash IDs in URL construction without validation could lead to XSS vulnerabilities.
Apply this diff to add validation:
if (demoConfig.isMobile) { // 点击目录列表更新iframe显示 const hashId = data.link.slice(1) + if (!/^[a-zA-Z0-9-_]+$/.test(hashId)) { + console.error('Invalid hash ID') + return + } getIframeConetent(state.cmpId, hashId + '.vue') }Likely invalid or redundant comment.
<div v-if="demoConfig.isMobile" class="mobile-view-container"> | ||
<!-- 移动端展示内容 --> | ||
<div class="phone-container"> | ||
<div style="width: 275px; height: 478px" class="mobile-iframe-container"> | ||
<iframe ref="iframeRef" width="100%" height="100%" :src="iframeUrl" frameborder="0"></iframe> | ||
</div> | ||
</div> | ||
</div> |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Enhance the mobile preview container for better accessibility and responsiveness.
The mobile preview container needs improvements:
- The iframe lacks important accessibility attributes (title, aria-label)
- Fixed dimensions (275px x 478px) may not work well on all screen sizes
Apply this diff to improve accessibility and responsiveness:
- <div style="width: 275px; height: 478px" class="mobile-iframe-container">
- <iframe ref="iframeRef" width="100%" height="100%" :src="iframeUrl" frameborder="0"></iframe>
+ <div class="mobile-iframe-container">
+ <iframe
+ ref="iframeRef"
+ :title="i18nByKey('mobile-preview')"
+ :aria-label="i18nByKey('mobile-preview')"
+ class="mobile-preview-frame"
+ :src="iframeUrl"
+ frameborder="0"
+ ></iframe>
Add these styles:
.mobile-iframe-container {
width: min(275px, 100%);
height: 478px;
position: relative;
}
.mobile-preview-frame {
width: 100%;
height: 100%;
border: none;
}
const getIframeConetent = (demoId, demoName) => { | ||
const frameWindow = iframeRef.value.contentWindow | ||
frameWindow.postMessage({ from: 'tiny-vue-site', component: state.cmpId, demo: demoName }) | ||
router.push(`#${demoId}`) | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add origin validation and error handling for postMessage communication.
The iframe communication lacks security measures and error handling:
- Missing origin validation for postMessage
- No error handling for messaging failures
Apply this diff to improve security and reliability:
const getIframeConetent = (demoId, demoName) => {
const frameWindow = iframeRef.value.contentWindow
- frameWindow.postMessage({ from: 'tiny-vue-site', component: state.cmpId, demo: demoName })
+ try {
+ const targetOrigin = import.meta.env.VITE_MOBILE_URL
+ frameWindow.postMessage(
+ { from: 'tiny-vue-site', component: state.cmpId, demo: demoName },
+ targetOrigin
+ )
+ } catch (error) {
+ console.error('Failed to send message to iframe:', error)
+ }
router.push(`#${demoId}`)
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
const getIframeConetent = (demoId, demoName) => { | |
const frameWindow = iframeRef.value.contentWindow | |
frameWindow.postMessage({ from: 'tiny-vue-site', component: state.cmpId, demo: demoName }) | |
router.push(`#${demoId}`) | |
} | |
const getIframeConetent = (demoId, demoName) => { | |
const frameWindow = iframeRef.value.contentWindow | |
try { | |
const targetOrigin = import.meta.env.VITE_MOBILE_URL | |
frameWindow.postMessage( | |
{ from: 'tiny-vue-site', component: state.cmpId, demo: demoName }, | |
targetOrigin | |
) | |
} catch (error) { | |
console.error('Failed to send message to iframe:', error) | |
} | |
router.push(`#${demoId}`) | |
} |
.phone-container { | ||
width: 395px; | ||
min-width: 395px; | ||
height: 600px; | ||
border: 0; | ||
position: fixed; | ||
left: 65%; | ||
right: 10%; | ||
top: 30%; | ||
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYsAAAMFCAYAAACFxdoKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg3MTZDNTAwMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjg3MTZDNTAxMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODcxNkM0RkUxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODcxNkM0RkYxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7YMDcrAAAcl0lEQVR42uzde4ysd1nA8ZnZmd3TU+jpKbWU0qYVgaKCRS4aISBGU6EFIQGEGA2RiEQLJBIjmBBIjAmKt2ijEDD4h2hEJVDKRRCDUKjBmtJqFRou0vQGtZz2eK47V59nzvuu0z17ztmZfWd2zsznk7yZmd2Z3dnZmd93fu878079wIEDte1oNBqPON3v94eHg8Fg43v5tXq9Pjydx/N7o6fzeC759fJ7YSWO74nD8+L0s+J8r4rjV8VyaSx7Y2n2er1Gt9utNZvN4bILBrE8PMHlzi8OH64B01Q+1uqz/sUxZg1ifBqsrKx0Yjka49nB+PKDsdwZY9o3Yrk5xrBb4/BwfK0b5+nGeQY5Jo6OncMrf2JMHB5uNZ7m8fJ7efqCCy6Y2d/Z3KV/7P5YHh9/7OXxh78gDl8UN8IVcSPujeMn/bPj68NlF9WL67yTvxdYQDF21VutVgxl9bU4uRaH+Xi/IpZnnng+PegUTxhvieXWWG6O5Wux3BNL+2z5O2cdiyfH8pS48V4ZN/A1EYB92YKsZJR3o64njdT1unskMLdOMUbVi2UtxrrHxvLiHPdWV1cPHzp06GCMdzfE6Y/G978ey3diOTrXf+OUV0NlbXP10pMyEJ1O59Xnnnvu45rNZmt9fX142fJnlMcBFnQGMjzMtSTtdjtPd2IsPBhPlG/rdrufjHHyi7HcFmdZX7bVUDkVuzaW18Qf+MxYzo8/sJ4ziDIsAgEsi/IJdo6BRQRacfzCOP6TMdt4bnz/rjj92Th9U5wtl3sWfmYR5bwqSvmW+NI1Uc595WXyvGUsrFoCqG3MFopxMTd83x/Lh2O8/Eyc/lh8v7uIM4uLIwa/EH/E6yIYT8yZxOZZhEgAnPzEuwhBPQ4viZOvj7H06jj8nlhuiOWBRZpZPD2Wt8XXXxJLzKpWN2YRAGxzUB7ZThGHR+Pwg7G8N751S5zunc0zi0viSr88Dq+LP+TKfB9ERkIoAMZXrq4v1sLke81+MZYnx9ffFYe5TePQ2TizeHpc8XfE8RdneKxiApjajOOuCMbH4vA9cfKOHINnObNoTHi5fIfcM2L5k5WVlZfFbEIoAKYoxtrLY8ZxXSxvr51Y7T/TdypPEot61O2nIg7vj0Y8r3xDHQDTk7s8yvdoNBqNV8a4+7740k/PdGYz5mqoRoTimjh8Z1zpp2YoTvWuawCmo3h16ZfjSfvvx+E/1U68A3xi+/efeY9E48ws8rzXxpV8n1AA7J58IdHa2toPx1j8OzEm/+ws3uC8rVjkS3/jyuRLYt8bV/JioQDYPTn+djq5f8LaZTEm/0ocvqJ24j0ZuxuLXq/3I+12+/qo2MVZMKEA2D3l/vSKsfj7Ixhvi8MX5B5wdzMWV8XM4l0RistszAaYrxnGcCBvNPIzgN6Y4ZhpLMqXwUa5LovlN+P083IrvB3/AcyPHKvLj3eIMfrZcfir8eXHzHRmEVfi3IhD7ufpZeW0B4C5nWHsiWD8XIzVP5+fPlr1e99OGYvcoB2/7NeazeaafwXA/Cq3X+Sn9OUG71wbVM48phqL+MU/Gr/kzVGpC70zG+DsCEaxTfnKWHKD99OmPbPIQPxSrv/KN+LZoA1w1gXjeTGOvzYOL55aLOKX/VhE4uqcUeTbywE469SLzxbKPW5U8rlFm2NxQUTiJXF4mfdSAJzVs4zHxPLSOPp9lcciApEvkX1hflqT1U8AZ69if37PieW5tcn3ML5lLPbHD/+Z6MTjvUwWYCFcmK9srZ3Y6F1NLOIHPv+cc865utlsNmyrADj7tVqtfLNeObuoJBbnx4zipb1e7xKrnwAWQ7GLpoviMPcY/oPlPqU2L9uKRa7XiuWSc88991l5ut1u17y3AmAxYpG7M4/ZxVNiXL+8GO9PWrYVi+Kdfz8e9bnctgqAxVIEIXdf/tTcjVNOBjYv243F+fkxfZ1O57zcVmFWsXsm/ScCnEoxrj8mxvmXxcTgOeXnEY0u29GMH5IfnnFF/sBi3yJu3RkHIoI9KP5pJ934OYUszuPGAsZWjh0xjlwRY8wlk47x+c6+J8QPe3Q5cDHb/2MGotfr5TI4VeHz/5K7iBcNYAdaMbt41KQXbsYA9fxY9hmEdiUUw49GLGZ09a1iXXx04nCGkS+DEwxgwhlGvufiqgjGhXHywbFjEc9YMxYtA9Bs/285k+h2u/W83U83oyu/ly9pzuMzWi211Q837YSzVD4hzQ3dMXY8LsaOR00Ui/gBl3pvxcz/cWUoxhqAc7tSRiJnGFOe8QxGY5RxKl5eN6tgLMozF4FlLuQYv7a2lo/l1aNHj+7Z7stlHxGLGIDOcVPOVtzmjUlfTFC+Yi2DUfXs4sR29uGbeOqjG9vj9w3i9w2m+WHwI9dhGNNF+D/n7WU7IHPxrCXuh7lKOx5fuTunp8Rj7KtjxyIWsZjtrCKfttcnHUVGXz1V9UiUA/VWM548nXe0CEa/MclTkjFnNfG7GovyAF1dXfXCEebJRbE8NZbPxfLQWE9+Ymm5/WYnB8JxVz9tMbuo51LlIJQRO92qsSIYjf709l2fq+YWJhRlfItnc+74zMsTmNy10+Mmmim7+SgC1NjqfR5bzDwaVQ9+Gb383fmzF+12Lfa948NhmBeNYhlMckHY9rPfaT1LXuRn3xFDjzPm5qGeKxImisVOV4mwGJrNZj83ZJ9pBrCystK3Dn6iByjsqnxFVIz3+XaJJ8Rj+MKx9w1VDgLM37P4U4l/9iCXKp+Nx88bbnQ/08+MqNSncXvkdvNi3/sLM7CW74uBeRp34rH26LhvnjNuLJreETxbOSDuZKNnObDm7j8q/r/V4+cOdz+y+Y2C5eliIJ/KM4tyYM1nP4vw4Vvl7ZVxNXtnXmKR40beL+NxNvZ2NE97ZqwY5PNVPxMNIDmgZyymMQCV+5/Kl6+W77fI3xUD3vA9FtN91exGlOpTftPhzGJR/J/c6Zmr8SeflB0/fnzsNUpisQt1LwfgfKnqmANQPlOtTevNcTlQ58/P61juXqS4ruX7O6b+DLl8w+GC/K/NKFgYYrE7zzpzUM6nnDkdPON2giIw+S7q2rTfRV1cl3oxXd24yrN8huzZOMwfL+nbxWYUH3fYLwfI0UFyZB/0uTG7Vuxuw60GmFksYzCKZ++D8g1xI69YGB7PGUi+UknYAbFY5loU2wmKUAzK18PmPphy1xoN0wlALNgcjtEdPgkFMC8MRgCIBQBiAYBYACAWAIgFAGIBgFgAgFgAIBYAiAUAYgGAWAAgFgCIBQBiAQBiAYBYACAWAIgFAGIBgFgAIBYAiAUAiAUAYgGAWAAgFgDMp+Z2zjQYDGorKyu1vXv3Dk+vr6/XWq3W8GvtdrtWr9eHpzudTq3f79fW1tZqvV5veHp1dXX4/bxMs9kcLnmZlN/rdrvD8+Zl8rL5vfIyeTx/R5WXyeP595SXaTQaw+u2+TJbmeTnlOcrz1vebnnevEx5u+X387zl7ZZ/2+bbevNlNt/WVV1mUf+nO7lMLnnd/B/n8/+YP3/0cJn+r3nd8m87fvz48HK7GouNM8cVyiuZVzgPc8k/dDhFicP8el7x8niePw/Tdi5TRmmcy5Tn28ll8mubL7PlNOwUP6e8/FY/Z/Tnbee8eZ68E4x+bTuXGb2tN1+mqv/P2f4/nfT/l+cpBx7/x/n8P262TP/X8gl9np5mLOoHDhwYbHdmcd555w2vLADzI2ckR48eHc40TjeO59qhiNAXDh8+/PoYy/+r/N6+fftsswBg58QCALEAQCwAEAsAxAIAsQBALAAQCwAQCwDEAgCxAEAsABALAMQCALEAQCwAQCwAEAsAxAIAsQBALAAQCwDEAgCxAACxAEAsABALAMQCALEAQCwAEAsAxAIAxAIAsQBALAAQCwDEAgCxAEAsABALABALAMQCALEAQCwAEAsAxAIAsQAAsQBALAAQCwDEAgCxAEAsABALAMQCAMQCALEAQCwAEAsAxAIAsQBALAAQCwAQCwDEAgCxAEAsABALAMQCALEAQCwAQCwAEAsAxAIAsQBALAAQCwDEAoAF0Ynl2GAwGOtCTbcbwHLo9/u5PDZC8ew4OWg0GvfG8Y6ZBQBD9Xq91u12a+vr61dGIK6PaLy71+u9Or6118wCgA0Rh1qEYiWicVEsL4yZxTP27NmT66M+YGYBwMbsIldFZTTyeLgoTr9hO5cVC4AllRu52+32k8UCgDMGQywAqIRYACAWAIgFAGIBgFgAIBYAiAUAYgEAYgGAWAAgFgCIBQBiAYBYACAWAIgFAIgFAGIBgFgAIBYAiAUAYgGAWAAgFgAgFgCIBQBiAYBYACAWAIgFAGIBgFgAgFgAIBYAiAUAYgGAWAAgFgCIBQBiAQBiAYBYACAWAIgFAGIBgFgAIBYAIBYAiAUAYgGAWAAgFgCIBQBiAYBYAIBYACAWAIgFAGIBgFgAIBYAiAUAYgEAYgGAWAAgFgCIBQBiAYBYACAWAIgFAIgFAGIBgFgAIBYAiAUAYgGAWAAgFgAgFgCIBQBiAYBYACAWAIgFAGIBAGIBsNwG2zlT0+0EsGR1GAxqKysrtVardTyOf1AsAHhEJJrNZkZi0O1276vX6x+KL/+BWACwIeJQazQaByMan4qZxT/2+/1PxpfvFQsANmYVa2trGYs7jx079scRjtvjy0e2e3mxAFgSEYpcDXU8QvFgLEfytFgAsGUzyrE/V0uNcyEAEAsAxAIAsQBALAAQCwDEAgCxAACxAEAsABALAMQCALEAQCwAEAsAxAIAxAIAsQBALAAQCwDEAgCxAEAsABALABALAMQCgKo13QQAy2kwGIgFAFvqxrKeoRgnFlZDASzRTCKWfXH08n6/v3ecy4oFwBKo1+u1TqdTO378+NMiFH8U0XhzfPlp+a3tXN5qKIAl0ev1huN+xOKHut3uD6yurj43IvKW+Nq/m1kAsDG7iFAMZxgxs2jG4U/E4Zu2c1mxAFgioxu1Ixxr7Xb7WrEA4EzxWBMLACohFgCIBQBiAYBYACAWAIgFAGIBgFgAgFgAIBYAiAUAYgGAWAAgFgCIBQBiAQBiAYBYACAWAIgFAGIBgFgAIBYAiAUAiAUAYgGAWAAgFgCIBQBzZjAYbOt8TTcVwPIFol6v1xqN4XzhkFgAcKpI1Fqt1pE4/TdiAcCGDMXKysrweLfbfShO3xhH3yMWAGzMKprNZgbjWL/f/0LMKj4YX/5ULPeIBQD/P+BHLGK5rdPpvDXicVt8qb/dy3o1FMCSyNVQsXRiObSystIf57JmFgDLJScJreGRRmOsCwGAWAAgFgCIBQBiAYBYACAWAIgFAIgFAGIBgFgAIBYAiAUAYgGAWAAgFgAgFgCIBQBiAYBYACAWAIgFAGIBgFgAwCM13QQAy2ffvn1mFgBUSywAEAsAxAIAsQBALAAQCwDEAgCxAACxAEAsABALAMQCALEAQCwAEAsAxAIAxAIAsQBALAAQCwDEAgCxAEAsABALABALAMQCALEAQCwAEAsAxAIAsQBALABALAAQCwDEAgCxAEAsABALAMQCALEAALEAQCwAEAsAxAIAsQBALAAQCwAQCwDEAgCxAEAsABALAMQCALEAQCwAQCwAEAsAxAIAsQBALAAQCwDEAgCxAACxAEAsABALAMQCALEAQCwAEAsAxAIAxAIAsQBALAAQCwDEAgCxAEAsABALABALAMQCALEAQCwAEAsAxAIAsQAAsQBALAAQCwDEAgCxAEAsABALAMQCAMQCALEAQCwAEAsAxAIAsQBALAAQCwAQCwDEAgCxAEAsABALAMQCALEAQCwAQCwAEAsAxAIAsQBALAAQCwDEAgCxAACxAEAsABALAMQCALEAQCwAEAsAxAIAxAIAsQBALAAQCwDEAgCxAEAsAEAsABALAMQCALEAQCwAEAsAxAIAsQAAsQBALAAQCwDEAgCxAEAsABALAMQCAMQCALEAQCwAEAsAxAIAsQBALAAQCwAQCwDEAgCxAEAsABALAMQCALEAQCwAQCwAEAsAxAIAsQBALAAQCwDEAgDEAgCxAEAsABALAMQCALEAQCwAEAsAEAsAxAIAsQBALAAQCwDEAgCxAEAsAEAsABALAMQCALEAQCwAEAsAxAIAsQAAsQBALAAQCwDEAgCxAEAsABALAMQCAMQCALEAQCwAEAsAxAIAsQBALAAQCwAQCwDEAgCxAEAsABALAMQCALEAALEAQCwAEAsAxAIAsQBALAAQCwDEAgDEAgCxAEAsABALAMQCALEAQCwAEAsAEAsAxAIAsQBALAAQCwDEAgCxAEAsAEAsABALAMQCALEAQCwAEAsAxAIAsQAAsQBALAAQCwDEAgCxAEAsABALABALAMQCALEAQCwAEAsAxAIAsQBALABALAAQCwDEAgCxAEAsABALAMQCALEAALEAQCwAEAsAxAIAsQBALAAQCwDEAgDEAgCxAEAsABALAMQCALEAQCwAEAsAEAsAxAIAsQBALAAQCwDEAgCxAEAsAEAsABALAMQCALEAQCwAEAsAxAIAxAIAsQBALAAQCwDEAgCxAEAsABALABALAMQCALEAQCwAEAsAxAIAsQBALABALAAQCwDEAgCxAEAsABALAMQCALEAALEAQCwAEAsAxAIAsQDg7NXc7hkHg0Gt3W4v8201mOAy9R1cFhj/sbZ8f3i9Phyf+/3+7seivDJHjhwZHoqFWIBYzFcwcpmLmcWsrtAca+zSZQHO6gEQALEAALEAQCwAEAsAxAIAsQBALAAQCwDEAgDEAgCxAEAsABALAMQCALEAQCwAEAsAOFnTTcA86ff7g263uzCf3ZsfQ9xqtfxjEQuYdBAdhF6vl4Goj8RiuCzsA67ZrK2srCz034hYQCWKSNTjoFbEYjQiaaH+3pgpPeJ0/s2NRmO4gFjAKWYTGYdOp5PHh2FYtDhs9XePhiMjubq6OsgZRh7Ps7h3IBZQTChyW0Qxm6hvHkSXKZi5lMEsZhgDwUAs4EQoyg3XBsXacNtMPYMR4Ri0Wq3hLCNvm2KmAWLB8oUiZhIZCivot7pxBoN6sWpquE7OdgzmlXsmU59RdDod97MzzDLa7XZj84ZwEAsWXrFevm5Gsf3bK1dBWQ2FWLBcU4oTvJlgvNtsuNEbxIKlGfdsp5hMbvRut9tmGIgFy/Ms2YA3+W0HYsHCy3col++lYLJYFG9adGMgFizyWDecVYjFDoOblvGNi4gFSyDXuZcDHZMrd41idoFYsJCzioyFWUV1swuxQCxYvFLYqF2pcl9aVkVR5ROQfPPnJPepZt4ZcxcDHuQwX5rN5nAXIB6bVCEDUcxW65NMFBrlM0Jg7h7cGQsPTiqLRer3+4dizD82dizcGWE+5Zsac5cpVkNRhdyzcdyXujG7+GbE4sGJZhYALMcEoxj3x34GIhYwx6sNyh0MQkX6xTJRLOy5DOZztUHfamKqFE88Ho7l/kkum7E45iaE+dPr9Rres0LFHojljlgeGjsWzWbzmA1oVCG3xMb9KZ8RezZcgbwtPTapaEZRa7VatbW1tXvjPvXVST6RMV9tcY+bkgqDYYCrSPHqFTcElTwu19fXc2lHKI5P8jMaMdX9fFy4404J8/VM0IZtqnzikfenbrd7fxwenuS+FZ1oZCwOigVVPYnJKW4sRrodWF1d9UooKp1ZxGPywTi8Pd9jMVEsYvlm/IBD5bMZ2Cmx2PkD2yoopqDT7/cPTzprzVdb3B1Tk28V5XFzUtXsou5lnxPHYuDJG1U++SjuT9+Kx+V9k25XzEf0w1Gbv2u1Wv+br75wB6Wi2UXd/Wl8+UqyfNUKVKV4HH43xvmPxOPy5mLmP1Es8oKfizvpXaa9VB2MXJ3CmRW7Ih+Ue5p1i1CV/IyZWP4njt4R97MjE6+GKn7QfUeOHPm3/Lm5Yc2zQaqa/uazZGPftsJaK1bdWRdMpfer/PyKXq/31RjX7yrG++Ey9s8qDvMt4DfEs8D7PBNkCsHoC8ZpH9CDeJLWt/qJacQixvQH4vDj8Rj8z3J7xUTbLEYe1J8/duzYp6NC/VzHBRXeYRuCcdrbx4yCqeh0OjmruDmOfnHH99OR4w/F1OSjMcO414OaaQQjnoTYMd7JM4qB2TxTlO+tuDEO76wyFnnnvSkq9A8RDHdgKhf3qUYMjvVc5bLs78PI2XveFsWswp2DyhXbJcpZRX+nP2/z1PdAdCIrdLf3XDClZ9PD1S6tViujMVi2aBSRsJNApi7uX9+N5YY4+o1KHrtb/IJ/iSJ9Ol8RZdsFVSteaVcvNrwNXy1VDp4LHIhc3bTxd5azdq86ZJoPtbif/WWM55+I491K7sdbfC33G/LnvV7vqvhFz847dhx30zOVaJR7DshlUZ9pj+66ww4CmfJsYvhYijH7prifvT++9O3KnvSc4hd+KX7RH8YM4/q4o1/oX8AMwrGws4v8ACOBYBahKPYumxuzfzuW/6h0hnyaX3xjxOIJ3W737VGqNf8KZhUNYLIZRTyGHoox+93xpZuq3mtx4zQP3CPxy3Kd10fKKwPA3Dre6/X+OsbqD8RyvOonX43TPcOLX3h3LO+M0/mSWsEAmMNZRYox+paYXfxZHP3uNH7Pdl4fmx+W8RtxRe4uX8ECwHyEohiXb4+T18fylWn9rm29mSKuyL+urq6+MYLxbZ97ATAfirH4K51OJzdo/3O/35/ahr9tvfwkZhb5jtsbIxT9brf73mazeXF+fZI9FwKwc8VanruLDdp/P/UwjXHeLEPuufB1McO4Y9IP0ABgZ3K7ckTiyzEWvzXG5L+dxfbkcV/YnjuC+3hc0U5cyd+Nsl1lhgEwc/n5Q+/Yv3//J2b1CyeZGuQneX0mgvHaKNtNNnoDzEbucjw/BjvG3dfFyU/N8ndPuh4p9/9xayxvihnGRyIaXW+oApie/KS7ZrP5p/Hk/Lfi5G3FODwz9QMHDmyvKpu2T5SrnuIPuCRmGi+Po9fFea7MdWf2JQWww8G5eOVp8TGouZvxd0UoPhtfP5RjbD5Bv+CCC+Z+ZjHqvrjy18fy6rjyH4pJRjv/EKumACaLxMj4eTSWv4jl12PJ7cWHdmstTpV7brst6veGWL6U69PiD3pi/t35R2cZraYCOM0z95FXmMaY2Y3lv2Pc/L342g0RkAd2ewytYjXU6B9YVvGqmGG8Jb50TbPZ3FdeJs9brqKy6xCA2iN2z58fOxzj6P2xfDjGy8/E6Y/F97vlE+7yvOXpWa6Gmso+oeOPuD3+oOvi8NqIw2siHs+MP/L89fX1/IS04RQrt+qbbQDLJse9kd2JDwORO/6LANwVT7Jzm0TuMTY/j+Keebre0/wAgYdi+atYclfnT4povDKWV+zZs+fSmG2slhtoyhtPOIBFn0GkjES73c7ZQSfGwoMxFt4WT54/GYH4Yiz5Kqf1ebz+U1kNVW7BLws6cnpfHP/eOOsvx9dfETdazqFW8nsZj/J8AIuknEnEGNdfXV09fOjQoYMx1t0QsfhofPvrcfw7cXh0ZHXUluPpbq6GmnUsyqnX/lgeHxe5PL7/gvjei+I8V8T39sY0rL7VtG30RgeYJ+VYt/nLxdKJMe7h+P4tcfzWGOdujvN/Lb52T4x77dHxVCxOjsXojbsSx/fE4Xlx+llxvlfF8dyNyKWx7I2lGbOORkRk+LGbu/TRm/kPf3iCy51fHD7s4QRTVT7WZv5sMvf0mu9LjrGtE8vRGM8OxpcfjOXOGNO+EcvNMYbdGoeH42vdOE++iTk3ZD9i7Jz3WPyfAAMAmxj+h7FTWDsAAAAASUVORK5CYII=) | ||
no-repeat center top; | ||
background-size: contain; | ||
z-index: 1; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
🛠️ Refactor suggestion
Improve responsiveness of the phone container.
The phone container uses fixed positioning and hardcoded dimensions which could cause layout issues on different screen sizes.
Apply this diff to improve responsiveness:
.phone-container {
- width: 395px;
- min-width: 395px;
+ width: min(395px, 100%);
+ min-width: min(395px, 100%);
height: 600px;
border: 0;
position: fixed;
- left: 65%;
- right: 10%;
+ right: max(10%, calc((100% - 395px) / 2));
top: 30%;
background: url(data:image/png;base64,...) no-repeat center top;
background-size: contain;
z-index: 1;
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
.phone-container { | |
width: 395px; | |
min-width: 395px; | |
height: 600px; | |
border: 0; | |
position: fixed; | |
left: 65%; | |
right: 10%; | |
top: 30%; | |
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYsAAAMFCAYAAACFxdoKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg3MTZDNTAwMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjg3MTZDNTAxMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODcxNkM0RkUxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODcxNkM0RkYxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7YMDcrAAAcl0lEQVR42uzd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) | |
no-repeat center top; | |
background-size: contain; | |
z-index: 1; | |
} | |
.phone-container { | |
width: min(395px, 100%); | |
min-width: min(395px, 100%); | |
height: 600px; | |
border: 0; | |
position: fixed; | |
right: max(10%, calc((100% - 395px) / 2)); | |
top: 30%; | |
background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAYsAAAMFCAYAAACFxdoKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuNi1jMDY3IDc5LjE1Nzc0NywgMjAxNS8wMy8zMC0yMzo0MDo0MiAgICAgICAgIj4gPHJkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENDIDIwMTUgKFdpbmRvd3MpIiB4bXBNTTpJbnN0YW5jZUlEPSJ4bXAuaWlkOjg3MTZDNTAwMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5IiB4bXBNTTpEb2N1bWVudElEPSJ4bXAuZGlkOjg3MTZDNTAxMTI1MzExRUE5Mzk1OTFBNjdDQ0JBNUQ5Ij4gPHhtcE1NOkRlcml2ZWRGcm9tIHN0UmVmOmluc3RhbmNlSUQ9InhtcC5paWQ6ODcxNkM0RkUxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiIHN0UmVmOmRvY3VtZW50SUQ9InhtcC5kaWQ6ODcxNkM0RkYxMjUzMTFFQTkzOTU5MUE2N0NDQkE1RDkiLz4gPC9yZGY6RGVzY3JpcHRpb24+IDwvcmRmOlJERj4gPC94OnhtcG1ldGE+IDw/eHBhY2tldCBlbmQ9InIiPz7YMDcrAAAcl0lEQVR42uzd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) | |
no-repeat center top; | |
background-size: contain; | |
z-index: 1; | |
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actionable comments posted: 1
🔭 Outside diff range comments (1)
examples/sites/src/views/components/demo.vue (1)
Line range hint
311-322
: Add error handling and loading states for iframe demo.The iframe demo loading lacks proper error handling and loading states:
- No loading indicator while demo loads
- No error handling if demo fails to load
- No cleanup of loading state on error
const getIframeDemo = (demo) => { + if (isIframeLoading.value) return + if (demo?.codeFiles.length > 0) { + isIframeLoading.value = true + iframeError.value = null + getIframeConetent(demo.demoId, demo.codeFiles[0]) jumpToMobileDemoAndHash(demo.demoId) state.currDemoId = demo.demoId state.currJson.demos.forEach((item) => { if (item.demoId === demo.demoId) { item.isIntersecting = true } }) + } else { + iframeError.value = i18nByKey('demo-not-found') } }
♻️ Duplicate comments (3)
examples/sites/src/views/components/components.vue (3)
164-171
: 🛠️ Refactor suggestionEnhance the mobile preview container for better accessibility and responsiveness.
The mobile preview container needs improvements:
- The iframe lacks important accessibility attributes (title, aria-label)
- Fixed dimensions (395px x 600px) may not work well on all screen sizes
<div v-if="demoConfig.isMobile" class="mobile-view-container"> <div class="phone-container"> <div class="mobile-iframe-container"> - <iframe ref="iframeRef" width="100%" height="100%" :src="iframeUrl" frameborder="0"></iframe> + <iframe + ref="iframeRef" + :title="i18nByKey('mobile-preview')" + :aria-label="i18nByKey('mobile-preview')" + class="mobile-preview-frame" + :src="iframeUrl" + frameborder="0" + ></iframe> </div> </div> </div>
701-706
:⚠️ Potential issueAdd input validation for hash IDs.
The direct use of hash IDs in URL construction without validation could lead to XSS vulnerabilities.
if (demoConfig.isMobile) { // 点击目录列表更新iframe显示 const hashId = data.link.slice(1) + if (!/^[a-zA-Z0-9-_]+$/.test(hashId)) { + console.error('Invalid hash ID') + return + } getIframeConetent(state.cmpId, hashId + '.vue') }
1113-1135
: 🛠️ Refactor suggestionImprove responsive layout handling.
The fixed positioning with percentage-based offsets might cause layout issues on different screen sizes.
.phone-container { - width: 394px; - height: 770px; + width: min(394px, 100%); + height: min(770px, 90vh); border: 0; position: fixed; - top: 280px; + top: 50%; + left: 50%; + transform: translate(-50%, -50%); background: url(...) no-repeat center top; background-size: cover; z-index: 1; } .mobile-view-container { - width: 400px; + width: min(400px, 100%); } .mobile-iframe-container { position: relative; top: 79px; left: 10px; - width: 360px; - height: 612px; + width: min(360px, 90%); + height: min(612px, 80vh); }
🧹 Nitpick comments (2)
examples/sites/mobile/App.vue (1)
71-103
: Consider using a CSS custom properties file for better maintainability.The scrollbar styling uses CSS variables but they're defined inline. Consider:
- Moving these CSS variables to a dedicated custom properties file
- Using semantic names for the variables (e.g.,
--scrollbar-width
instead of--tvm-size-scrollbar-width
)- ::-webkit-scrollbar { - width: var(--tvm-size-scrollbar-width); - height: var(--tvm-size-scrollbar-height); - } + @import '@/styles/variables.less'; + + ::-webkit-scrollbar { + width: var(--scrollbar-width); + height: var(--scrollbar-height); + }examples/sites/src/views/components/demo.vue (1)
56-60
: Add loading and error states for the mobile preview button.The mobile preview button lacks loading and error states. Consider:
- Adding a loading state while the iframe loads
- Adding error handling if the demo fails to load
<div v-else-if="demoConfig.isMobile" class="mobile-demo-container"> <div class="mobile-view-btn"> - <tiny-mobile-button type="secondary" @click="openIframe(demo)"> - {{ i18nByKey('yan-shi') }} - </tiny-mobile-button> + <tiny-mobile-button + type="secondary" + :loading="isIframeLoading" + :disabled="isIframeLoading" + @click="openIframe(demo)" + > + {{ isIframeLoading ? i18nByKey('loading') : i18nByKey('yan-shi') }} + </tiny-mobile-button> + <div v-if="iframeError" class="error-message"> + {{ i18nByKey('preview-error') }} + </div> </div> </div>
📜 Review details
Configuration used: CodeRabbit UI
Review profile: CHILL
Plan: Pro
📒 Files selected for processing (3)
examples/sites/mobile/App.vue
(2 hunks)examples/sites/src/views/components/components.vue
(12 hunks)examples/sites/src/views/components/demo.vue
(5 hunks)
🔇 Additional comments (2)
examples/sites/mobile/App.vue (1)
2-2
: LGTM! The class name aligns with the component's purpose.The addition of the "mobile-preview" class to the root div improves semantic clarity and maintainability.
examples/sites/src/views/components/demo.vue (1)
Line range hint
305-309
: Add origin validation and error handling for postMessage communication.The iframe communication lacks security measures and error handling:
- Missing origin validation for postMessage
- No error handling for messaging failures
const getIframeConetent = (demoId, demoName) => { const frameWindow = iframeRef.value.contentWindow - frameWindow.postMessage({ from: 'tiny-vue-site', component: state.cmpId, demo: demoName }) + try { + const targetOrigin = import.meta.env.VITE_MOBILE_URL + frameWindow.postMessage( + { from: 'tiny-vue-site', component: state.cmpId, demo: demoName }, + targetOrigin + ) + } catch (error) { + console.error('Failed to send message to iframe:', error) + } router.push(`#${demoId}`) }
if (demoConfig.isMobile && !hash) { | ||
// 初始化iframe,当前组件第一个demo展示 | ||
state.iframeUrl = `${import.meta.env.VITE_MOBILE_URL}?component=${state.cmpId}&demo=${ | ||
state.currJson?.demos[0].codeFiles[0] | ||
}` | ||
} else { | ||
state.iframeUrl = `${import.meta.env.VITE_MOBILE_URL}?component=${state.cmpId}&demo=${hash}.vue` | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Add input validation and error handling for iframe URL construction.
The iframe URL construction lacks validation and error handling:
- No validation of component and demo parameters
- No error handling if environment variable is missing
+const getIframeUrl = (component, demo) => {
+ if (!import.meta.env.VITE_MOBILE_URL) {
+ console.error('Mobile preview URL environment variable is not defined')
+ return ''
+ }
+ if (!component || !/^[a-zA-Z0-9-_]+$/.test(component)) {
+ console.error('Invalid component ID')
+ return ''
+ }
+ const demoFile = demo ? `${demo}.vue` : state.currJson?.demos[0]?.codeFiles[0]
+ if (!demoFile || !/^[a-zA-Z0-9-_/.]+$/.test(demoFile)) {
+ console.error('Invalid demo file')
+ return ''
+ }
+ return `${import.meta.env.VITE_MOBILE_URL}?component=${encodeURIComponent(component)}&demo=${encodeURIComponent(demoFile)}`
+}
if (demoConfig.isMobile && !hash) {
- state.iframeUrl = `${import.meta.env.VITE_MOBILE_URL}?component=${state.cmpId}&demo=${state.currJson?.demos[0].codeFiles[0]}`
+ state.iframeUrl = getIframeUrl(state.cmpId)
} else {
- state.iframeUrl = `${import.meta.env.VITE_MOBILE_URL}?component=${state.cmpId}&demo=${hash}.vue`
+ state.iframeUrl = getIframeUrl(state.cmpId, hash)
}
📝 Committable suggestion
‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.
if (demoConfig.isMobile && !hash) { | |
// 初始化iframe,当前组件第一个demo展示 | |
state.iframeUrl = `${import.meta.env.VITE_MOBILE_URL}?component=${state.cmpId}&demo=${ | |
state.currJson?.demos[0].codeFiles[0] | |
}` | |
} else { | |
state.iframeUrl = `${import.meta.env.VITE_MOBILE_URL}?component=${state.cmpId}&demo=${hash}.vue` | |
} | |
const getIframeUrl = (component, demo) => { | |
if (!import.meta.env.VITE_MOBILE_URL) { | |
console.error('Mobile preview URL environment variable is not defined') | |
return '' | |
} | |
if (!component || !/^[a-zA-Z0-9-_]+$/.test(component)) { | |
console.error('Invalid component ID') | |
return '' | |
} | |
const demoFile = demo ? `${demo}.vue` : state.currJson?.demos[0]?.codeFiles[0] | |
if (!demoFile || !/^[a-zA-Z0-9-_/.]+$/.test(demoFile)) { | |
console.error('Invalid demo file') | |
return '' | |
} | |
return `${import.meta.env.VITE_MOBILE_URL}?component=${encodeURIComponent(component)}&demo=${encodeURIComponent(demoFile)}` | |
} | |
if (demoConfig.isMobile && !hash) { | |
state.iframeUrl = getIframeUrl(state.cmpId) | |
} else { | |
state.iframeUrl = getIframeUrl(state.cmpId, hash) | |
} |
PR
PR Checklist
Please check if your PR fulfills the following requirements:
PR Type
What kind of change does this PR introduce?
What is the current behavior?
Issue Number: N/A
What is the new behavior?
Does this PR introduce a breaking change?
Other information
Summary by CodeRabbit
Style Updates
overflow-y
property fromscroll
toauto
in multiple components, improving scrollbar behavior.New Features