### Access Site, Theme, Page, and Frontmatter Data with useData() in Vue Source: https://github.com/perfreeblog/perfree-blog-docs/blob/main/api-examples.md This example demonstrates using the useData() hook within a Vue ` ## Results ### Theme Data
{{ theme }}
### Page Data
{{ page }}
### Page Frontmatter
{{ frontmatter }}
``` -------------------------------- ### VitePress Configuration - Site Setup Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Details the VitePress configuration for the PerfreeBlog documentation website, including API proxy settings, theme configuration, navigation, and sidebar setup. ```APIDOC ## VitePress Configuration (`vite.config.js` or similar) ### Description This configuration outlines the setup for the VitePress documentation site, including Vite server proxy settings to route API requests to the official PerfreeBlog backend, site metadata, theme customization, navigation, and sidebar structure. ### Method N/A (Configuration file) ### Endpoint N/A (Configuration file) ### Parameters N/A ### Request Example ```javascript import { defineConfig } from 'vitepress'; export default defineConfig({ vite: { server: { proxy: { // This proxy configuration routes requests starting with '/api' to the // official PerfreeBlog API endpoint. '/api': { target: 'https://www.yinpengfei.com/api', // The actual API base URL changeOrigin: true, // Allows the server to change the origin of the request rewrite: (path) => path.replace(/^/api/, '') // Rewrites the path to remove the '/api' prefix } } } }, // Site metadata title: "PerfreeBlog - Java Blog/CMS System", description: "PerfreeBlog Documentation", lang: 'zh-CN', // Markdown configuration markdown: { lineNumbers: true, // Enable line numbers for code blocks image: { lazyLoading: true } // Enable lazy loading for images }, // Theme configuration themeConfig: { siteTitle: 'PerfreeBlog', logo: { src: '/logo.png', width: 24, height: 24 }, nav: [ { text: '🏠 Home', link: '/' }, { text: '📖 User Docs', link: '/useDocs' }, { text: '🎨 Theme Store', link: '/theme' }, { text: '🔌 Plugin Store', link: '/plugin' } ], search: { provider: 'local' }, // Use local search sidebar: { '/useDocs': [ { text: '🕹 Installation', items: [ { text: 'Quick Start', link: '/useDocs/' }, { text: 'JAR Installation', link: '/useDocs/jar' }, { text: 'Docker Installation', link: '/useDocs/docker' } ] } ] } } }); ``` ### Response N/A (This is a configuration file, not an API endpoint.) ``` -------------------------------- ### Axios HTTP Client Configuration Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Demonstrates the configuration and usage of a pre-configured Axios instance for making HTTP requests to the PerfreeBlog backend. Includes examples for GET and POST requests. ```APIDOC ## Axios Instance Usage ### Description Shows how to use a pre-configured Axios instance, which includes base URL, timeout, and interceptors for API communication with the PerfreeBlog backend. ### Method GET, POST (examples shown) ### Endpoint Configured via proxy in VitePress (`/api` prefix) ### Parameters N/A (Parameters are part of the request body or query for specific endpoints) ### Request Example ```javascript import axios from './core/axios/axios.js'; // Example GET request to fetch a specific item (e.g., from appstore) axios.get('/api/official/appstore/get?id=123') .then(data => { console.log('GET Response data:', data); }) .catch(error => { console.error('GET Request failed:', error); }); // Example POST request to fetch a paginated list (e.g., appstore page) axios.post('/api/official/appstore/page', { pageNo: 1, pageSize: 10, type: 1 // 1 for plugins, 2 for themes }).then(data => { console.log('POST Response data:', data); }).catch(error => { console.error('POST Request failed:', error); }); ``` ### Response #### Success Response (200) - The response format depends on the specific API endpoint called. Typically includes `code`, `msg`, and `data` fields. #### Response Example ```json // Example response for a successful POST request to /api/official/appstore/page { "code": 200, "msg": "Success", "data": { "list": [ // ... items ... ], "total": 50 } } ``` ``` -------------------------------- ### Syntax Highlighting with Line Highlighting in VitePress Source: https://github.com/perfreeblog/perfree-blog-docs/blob/main/markdown-examples.md VitePress uses Shiki for syntax highlighting with support for line-level highlighting. The {4} notation highlights specific lines in code blocks. This example shows a Vue.js component with line 4 highlighted to emphasize the return value. ```javascript export default { data () { return { msg: 'Highlighted!' } } } ``` -------------------------------- ### Access Site, Theme, and Page Data with useData() in Markdown Source: https://github.com/perfreeblog/perfree-blog-docs/blob/main/api-examples.md This example shows how to import and use the useData() hook within a Markdown file to access theme, page, and frontmatter data. It then displays this data using Vue template syntax. No external dependencies are required beyond VitePress itself. ```markdown ## Results ### Theme Data
{{ theme }}
### Page Data
{{ page }}
### Page Frontmatter
{{ frontmatter }}
``` -------------------------------- ### Custom Container Blocks in Markdown Source: https://github.com/perfreeblog/perfree-blog-docs/blob/main/markdown-examples.md VitePress supports custom container syntax for creating styled content blocks. Five container types are available: info, tip, warning, danger, and details. Each container uses the ::: syntax and automatically renders with appropriate styling and icons. ```markdown ::: info This is an info box. ::: ::: tip This is a tip. ::: ::: warning This is a warning. ::: ::: danger This is a dangerous warning. ::: ::: details This is a details block. ::: ``` -------------------------------- ### Axios HTTP Client Configuration and Usage (JavaScript) Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Configures a pre-set Axios instance for communicating with the PerfreeBlog backend. It includes request/response interceptors, base URL, timeout, and automatic data extraction. Demonstrates GET and POST requests. ```javascript import axios from './core/axios/axios.js'; // The axios instance is pre-configured with: // - Base URL: '/' // - Timeout: 5000ms // - Automatic response data extraction // - Error logging // Example GET request axios.get('/api/official/appstore/get?id=123') .then(data => { console.log('Response data:', data); }) .catch(error => { console.error('Request failed:', error); }); // Example POST request axios.post('/api/official/appstore/page', { pageNo: 1, pageSize: 10, type: 1 }).then(data => { console.log('Page data:', data); }).catch(error => { console.error('Request failed:', error); }); ``` -------------------------------- ### Application Store API - Get Plugin Details by ID Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Retrieves detailed information for a specific plugin or theme using its unique ID. This is useful for displaying detailed views of individual store items. ```APIDOC ## GET /api/official/appstore/get ### Description Retrieves detailed information for a specific plugin or theme from the application store using its ID. ### Method GET ### Endpoint /api/official/appstore/get ### Query Parameters - **id** (string) - Required - The unique identifier of the plugin or theme. ### Request Example ```javascript // This is a client-side JavaScript example using the appstoreGetByIdApi function. // The actual API endpoint is typically called via an HTTP client like Axios. // Example using the provided JS function: import { appstoreGetByIdApi } from './core/api/appstore.js'; const pluginId = 'perfree-plugin-demo'; appstoreGetByIdApi(pluginId).then(res => { if(res.code === 200) { const plugin = res.data; console.log('Plugin name:', plugin.appName); console.log('Author:', plugin.appAuthor); console.log('Description:', plugin.description); console.log('Download URL:', plugin.downloadUrl); } else { console.error('Error fetching plugin:', res.msg); } }).catch(error => { console.error('Request failed:', error); }); ``` ### Response #### Success Response (200) - **code** (integer) - The status code of the response. - **msg** (string) - A message indicating the result of the operation. - **data** (object) - Contains the detailed information of the plugin or theme. - **appName** (string) - The name of the application (plugin/theme). - **appAuthor** (string) - The author of the application. - **description** (string) - A detailed description of the application. - **downloadUrl** (string) - The URL to download the application. - **version** (string) - The current version of the application. #### Response Example ```json { "code": 200, "msg": "Success", "data": { "appName": "Example Plugin", "appAuthor": "Perfree", "description": "This is a sample plugin for demonstration purposes.", "downloadUrl": "http://example.com/plugins/example-plugin-1.0.0.zip", "version": "1.0.0" } } ``` ``` -------------------------------- ### Handle Plugin Lifecycle Events in Java Service Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Spring service class implementing BasePluginEvent interface to handle plugin lifecycle events including installation, startup, updates, and uninstallation. Provides hooks for resource initialization, cleanup, data migration, and configuration management at each lifecycle stage. ```Java package com.official; import com.perfree.plugin.BasePluginEvent; import org.springframework.stereotype.Service; @Service public class PluginEventService implements BasePluginEvent { @Override public void onStart() { // Execute when plugin is started/enabled System.out.println("Plugin started"); // Initialize resources, register services, etc. } @Override public void onStop() { // Execute when plugin is stopped/disabled System.out.println("Plugin stopped"); // Clean up resources, unregister services, etc. } @Override public void onUpdate() { // Execute when plugin is updated System.out.println("Plugin updated"); // Migrate data, update configurations, etc. } @Override public void onInstall() { // Execute when plugin is first installed System.out.println("Plugin installed"); // Create initial data, setup defaults, etc. } @Override public void onUnInstall() { // Execute when plugin is uninstalled System.out.println("Plugin uninstalled"); // Remove all plugin data, cleanup database, etc. } } ``` -------------------------------- ### Get Plugin Details by ID from App Store API (JavaScript) Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Retrieves detailed information for a specific plugin or theme using its ID from the application store. It takes a plugin ID as input and returns detailed plugin data or an error message. ```javascript import { appstoreGetByIdApi } from './core/api/appstore.js'; // Fetch plugin details by ID const pluginId = 'perfree-plugin-demo'; appstoreGetByIdApi(pluginId).then(res => { if(res.code === 200) { const plugin = res.data; console.log('Plugin name:', plugin.appName); console.log('Author:', plugin.appAuthor); console.log('Description:', plugin.description); console.log('Download URL:', plugin.downloadUrl); } else { console.error('Error fetching plugin:', res.msg); } }).catch(error => { console.error('Request failed:', error); }); ``` -------------------------------- ### Application Store API - Paginated Plugin Listing Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Fetches a paginated list of plugins or themes from the PerfreeBlog application store. This API is used to populate the plugin and theme repository interfaces. ```APIDOC ## GET /api/official/appstore/page ### Description Fetches paginated plugin or theme data from the PerfreeBlog official application store. ### Method GET ### Endpoint /api/official/appstore/page ### Query Parameters - **pageNo** (integer) - Required - The page number to retrieve. - **pageSize** (integer) - Required - The number of items per page. - **type** (integer) - Required - The type of item to fetch (1 for plugins, 2 for themes). ### Request Example ```javascript // This is a client-side JavaScript example using the appstorePageApi function. // The actual API endpoint is typically called via an HTTP client like Axios. // Example using the provided JS function: import { appstorePageApi } from './core/api/appstore.js'; const searchParam = { pageNo: 1, pageSize: 8, type: 1 // 1 for plugins, 2 for themes }; appstorePageApi(searchParam).then(res => { if(res.code === 200) { console.log('Plugin list:', res.data.list); console.log('Total plugins:', res.data.total); } else { console.error('Error:', res.msg); } }).catch(error => { console.error('Request failed:', error); }); ``` ### Response #### Success Response (200) - **code** (integer) - The status code of the response. - **msg** (string) - A message indicating the result of the operation. - **data** (object) - Contains the list of items and total count. - **list** (array) - An array of plugin/theme objects. - **total** (integer) - The total number of available items. #### Response Example ```json { "code": 200, "msg": "Success", "data": { "list": [ { "appName": "Example Plugin", "appAuthor": "Perfree", "description": "A demo plugin.", "downloadUrl": "http://example.com/plugins/example.zip", "version": "1.0.0" } // ... other plugins/themes ], "total": 15 } } ``` ``` -------------------------------- ### VitePress Site Configuration (JavaScript) Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Configures the VitePress static site generator for the PerfreeBlog documentation. Includes site metadata, theme configuration, navigation, sidebar structure, search, and Vite server proxy settings for API requests. ```javascript import { defineConfig } from 'vitepress'; export default defineConfig({ vite: { server: { proxy: { '/api': { target: 'https://www.yinpengfei.com/api', changeOrigin: true, rewrite: (path) => path.replace(/^/api/, '') } } } }, title: "PerfreeBlog - Java Blog/CMS System", description: "PerfreeBlog Documentation", lang: 'zh-CN', markdown: { lineNumbers: true, image: { lazyLoading: true } }, themeConfig: { siteTitle: 'PerfreeBlog', logo: { src: '/logo.png', width: 24, height: 24 }, nav: [ { text: '🏠 Home', link: '/' }, { text: '📖 User Docs', link: '/useDocs' }, { text: '🎨 Theme Store', link: '/theme' }, { text: '🔌 Plugin Store', link: '/plugin' } ], search: { provider: 'local' }, sidebar: { '/useDocs': [ { text: '🕹 Installation', items: [ { text: 'Quick Start', link: '/useDocs/' }, { text: 'JAR Installation', link: '/useDocs/jar' }, { text: 'Docker Installation', link: '/useDocs/docker' } ] } ] } } }); ``` -------------------------------- ### Docker Compose Deployment Configuration Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt A Docker Compose configuration file for deploying PerfreeBlog and its MySQL database. It sets up two services: `mysql-container` and `perfree-blog-container`, defining their images, environment variables, volumes, and network dependencies. ```yaml version: '3.8' services: mysql-container: image: registry.cn-hangzhou.aliyuncs.com/perfree/perfree_mysql:8.0 restart: always environment: MYSQL_ROOT_PASSWORD: perfree666 TZ: Asia/Shanghai MYSQL_DATABASE: perfree MYSQL_CHARSET: utf8mb4 MYSQL_COLLATION: utf8mb4_unicode_ci volumes: - ./perfree/mysql/data:/var/lib/mysql healthcheck: test: ["CMD", "mysqladmin", "ping", "-h", "localhost"] interval: 10s timeout: 10s retries: 3 start_period: 40s perfree-blog-container: image: registry.cn-hangzhou.aliyuncs.com/perfree/perfree_blog:latest restart: always ports: - 8080:8080 environment: SPRING_DATASOURCE_URL: jdbc:mysql://mysql-container:3306/perfree?useSSL=false&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&nullCatalogMeansCurrent=true SPRING_DATASOURCE_USERNAME: root SPRING_DATASOURCE_PASSWORD: perfree666 depends_on: mysql-container: condition: service_healthy volumes: - ./perfree/resources:/perfree-server/resources ``` -------------------------------- ### Plugin YAML Configuration Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Configuration file for PerfreeBlog plugins written in YAML. It defines essential plugin metadata such as ID, name, version, description, and development settings including update URLs and frontend development server addresses. ```yaml plugin: # Unique plugin identifier id: perfree-plugin-test # Plugin display name name: Test Plugin # Mapper XML file location (optional) mapperLocation: mapper/*.xml # Plugin description description: Test plugin for demonstration # Minimum PerfreeBlog version required minimalVersion: 4.0.0 # Plugin version version: 1.0.0 # Static resource path staticLocations: /ui/ # Development mode flag isDev: true # Frontend development server address (for hot reload) frontDevAddress: http://127.0.0.1:4202 # Plugin update check URL updateUrl: https://example.com/updates author: # Author name name: perfree # Author email email: perfree@126.com # Author website webSite: https://yinpengfei.com ``` -------------------------------- ### Create WebSocket Server Endpoint for Real-Time Communication Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Jakarta WebSocket server endpoint implementation for handling real-time bidirectional communication in plugins. Manages client connections with session tracking, message reception, and error handling using SLF4J logging and atomic counters for thread-safe connection counting. ```Java package com.demo.websocket; import jakarta.websocket.*; import jakarta.websocket.server.ServerEndpoint; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.stereotype.Component; import java.util.concurrent.atomic.AtomicInteger; @ServerEndpoint("/webSocket/test") @Component public class WebSocketTest { private static final Logger LOGGER = LoggerFactory.getLogger(WebSocketTest.class); private static final AtomicInteger onlineCount = new AtomicInteger(0); @OnOpen public void onOpen(Session session) { onlineCount.incrementAndGet(); LOGGER.info("New WebSocket connection, online count: {}", onlineCount.get()); } @OnClose public void onClose(Session session) { onlineCount.decrementAndGet(); LOGGER.info("WebSocket connection closed, online count: {}", onlineCount.get()); } @OnMessage public void onMessage(String message, Session session) { LOGGER.info("Received message from client: {}", message); this.sendMessage("Hello, " + message, session); } @OnError public void onError(Session session, Throwable error) { LOGGER.error("WebSocket error: {}", error.getMessage(), error); } private void sendMessage(String message, Session toSession) { try { LOGGER.info("Sending message to client: {}", message); toSession.getBasicRemote().sendText(message); } catch (Exception e) { LOGGER.error("Failed to send message: {}", e.getMessage(), e); } } } ``` -------------------------------- ### Fetch Paginated Plugin List from App Store API (JavaScript) Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Fetches a paginated list of plugins from the PerfreeBlog official application store. It requires a search parameter object with page number, page size, and type. Returns plugin data or an error message. ```javascript import { appstorePageApi } from './core/api/appstore.js'; // Fetch paginated plugin list const searchParam = { pageNo: 1, pageSize: 8, total: 0, type: 1 // 1 for plugins, 2 for themes }; appstorePageApi(searchParam).then(res => { if(res.code === 200) { console.log('Plugin list:', res.data.list); console.log('Total plugins:', res.data.total); } else { console.error('Error:', res.msg); } }).catch(error => { console.error('Request failed:', error); }); ``` -------------------------------- ### Plugin Store Vue Component Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt An interactive Vue.js component for displaying and browsing plugins. It includes features for pagination and filtering, fetching data from the `appstorePageApi`. Dependencies include Vue.js and the Element Plus UI library. ```vue ``` -------------------------------- ### Plugin HTML Render Proxy - Java Implementation Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Java Spring component that extends HtmlRenderProxy to manipulate rendered HTML documents before delivery. Provides two hooks: editFrontDocument for frontend pages (applies grayscale filter for memorial days) and editAdminDocument for admin panel modifications. Uses JSoup for DOM manipulation. ```java package com.demo.proxy; import com.perfree.commons.proxy.HtmlRenderProxy; import org.jsoup.nodes.Document; import org.springframework.stereotype.Component; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; @Component public class WebGray extends HtmlRenderProxy { @Override public Document editFrontDocument(Document document, HttpServletResponse response, HttpServletRequest request) { // Apply grayscale filter to entire page (e.g., for memorial days) document.head().append(""); return document; } @Override public Document editAdminDocument(Document document, HttpServletResponse response, HttpServletRequest request) { // Modify admin panel HTML (executed only for /admin/* URLs) return document; } } ``` -------------------------------- ### Implement Custom Java Template Directive for PerfreeBlog Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt This Java code implements a custom template directive named 'pluginDemo' for PerfreeBlog themes. It extends BaseDirective and uses annotations to register itself. The directive can accept parameters, process them, and generate HTML output to be embedded in the theme template. It relies on PerfreeBlog's directive system and Spring framework for component management. ```java package com.demo.directive; import com.jfinal.template.Env; import com.jfinal.template.io.Writer; import com.jfinal.template.stat.Scope; import com.perfree.commons.directive.BaseDirective; import com.perfree.commons.directive.TemplateDirective; import org.springframework.stereotype.Component; @TemplateDirective("pluginDemo") @Component public class PluginDemoDirective extends BaseDirective { @Override public void exec(Env env, Scope scope, Writer writer) { // Access directive parameters String param = getParam("param", scope, null); // Generate output StringBuilder output = new StringBuilder(); output.append("
"); output.append("This is a custom directive from plugin"); if (param != null) { output.append("

Parameter: ").append(param).append("

"); } output.append("
"); // Write output to template write(writer, output.toString()); } } // Usage in theme template: // #pluginDemo(param="example value") ``` -------------------------------- ### Implement HTTP Request Interceptor for Custom Processing Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Spring HandlerInterceptor implementation for intercepting and processing HTTP requests/responses at specified paths. Provides preHandle and postHandle hooks for custom logic before/after request execution, with logging for debugging and request URI tracking. ```Java package com.demo.interceptor; import org.springframework.stereotype.Component; import org.springframework.web.servlet.HandlerInterceptor; import org.springframework.web.servlet.ModelAndView; import jakarta.servlet.http.HttpServletRequest; import jakarta.servlet.http.HttpServletResponse; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @Component @InterceptPath("/**") // Intercept all paths public class InterceptorDemo implements HandlerInterceptor { private static final Logger LOGGER = LoggerFactory.getLogger(InterceptorDemo.class); @Override public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler) throws Exception { LOGGER.info("Plugin interceptor preHandle: {}", request.getRequestURI()); // Return true to continue request processing // Return false to stop request processing return HandlerInterceptor.super.preHandle(request, response, handler); } @Override public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler, ModelAndView modelAndView) throws Exception { LOGGER.info("Plugin interceptor postHandle: {}", request.getRequestURI()); HandlerInterceptor.super.postHandle(request, response, handler, modelAndView); } } ``` -------------------------------- ### Theme Template Directive - Category Listing and Hot Categories Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Template directives for displaying categories in paginated grid format with article counts, and a separate hot categories display. The categoriesPage directive handles pagination while hotCategories shows top categories as badges. Both include conditional navigation and empty state handling. ```html #categoriesPage(pageSize=20)
#for(category: categoriesPage.data)

#(category.name)

#(category.description)

#(category.articleCount) articles
#else

No categories found

#end
#if(categoriesPage.pageTotal > 1) #end #end #hotCategories(count=4)
#for(category: categories) #(category.name) (#(category.articleCount)) #end
#end ``` -------------------------------- ### Theme Template Directive - Article Pagination Source: https://context7.com/perfreeblog/perfree-blog-docs/llms.txt Template directive that renders a paginated list of articles with metadata (author, date, views) and navigation controls. Uses the articlePage object to display article data and pagination links. Handles empty states with conditional rendering. ```html #articlePage(pageSize=10) #for(article: articlePage.data)

#(article.title)

Author: #(article.author) Date: #(article.createTime) Views: #(article.viewCount)
#(article.summary)
#else

No articles found

#end #if(articlePage.pageTotal > 1) #end #end ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.