mirror of
https://github.com/tuna/mirror-web.git
synced 2025-12-25 20:32:46 +00:00
Basic vite rendering config
This commit is contained in:
parent
d20e32c01f
commit
e014df8126
|
|
@ -14,3 +14,5 @@
|
|||
/vendor/
|
||||
.vscode/
|
||||
.DS_Store
|
||||
/node_modules/
|
||||
/.jekyll-cache/
|
||||
|
|
|
|||
2
Gemfile
2
Gemfile
|
|
@ -19,3 +19,5 @@ group :jekyll_plugins do
|
|||
gem 'jekyll-fontawesome-svg', '~> 0.4.0'
|
||||
gem 'jekyll-minifier', '~> 0.1.10'
|
||||
end
|
||||
|
||||
gem 'vite_ruby', '~> 3.2'
|
||||
|
|
|
|||
18
_config.yml
18
_config.yml
|
|
@ -48,6 +48,10 @@ kramdown:
|
|||
sass:
|
||||
sass_dir: static/css
|
||||
|
||||
vite:
|
||||
config_path: _src/vite.json
|
||||
viteConfig: _vite.config.mjs
|
||||
|
||||
plugins:
|
||||
- jekyll-relative-links
|
||||
- jekyll-babel
|
||||
|
|
@ -57,7 +61,19 @@ plugins:
|
|||
|
||||
babel_js_extensions: 'es6'
|
||||
|
||||
exclude: [Gemfile, Gemfile.lock, README.md, gen_robot.sh, vendor, geninfo/, gen_desc.py, Dockerfile*]
|
||||
jekyll-minifier:
|
||||
exclude: [ 'assets/**' ]
|
||||
|
||||
exclude: [gen_robot.sh, geninfo/, gen_desc.py]
|
||||
addition_exclude:
|
||||
- package.json
|
||||
- package-lock.json
|
||||
- node_modules
|
||||
- Gemfile
|
||||
- Gemfile.lock
|
||||
- README.md
|
||||
- vendor/
|
||||
- Dockerfile*
|
||||
|
||||
sponsors:
|
||||
megvii:
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
{% raw %}
|
||||
<div v-if="false" id="upgrade-mask" style="position: fixed; background: white; width: 100%; height: 100%; z-index: 2000; padding-top: 40px; overflow: scroll;" data-bs-theme="light" class="container mw-100">
|
||||
<div id="upgrade-mask">
|
||||
<div style="position: fixed; background: white; width: 100%; height: 100%; z-index: 2000; padding-top: 40px; overflow: scroll;" data-bs-theme="light" class="container mw-100">
|
||||
<div class="card"><div class="card-body">
|
||||
<p>尊敬的访问者,</p>
|
||||
<p>Dear visitor, </p>
|
||||
|
|
@ -17,4 +18,5 @@
|
|||
<p>お使いのブラウザは当サイトとの互換性はありません。ブラウザを更新しJavaScriptを有効にするか、或いはこちらの<a href="/legacy_index">代用ページ</a>をご利用ください。</p>
|
||||
</div>
|
||||
</div></div>
|
||||
</div>
|
||||
{% endraw %}
|
||||
|
|
|
|||
|
|
@ -221,6 +221,9 @@
|
|||
{% endraw %}
|
||||
{% unless page.legacy or site.issue %}
|
||||
<script src="/static/js/index.js?{{ site.data['hash'] }}"></script>
|
||||
{% vite_javascript_tag app %}
|
||||
<script src="{% vite_asset_path /vite/legacy-polyfills-legacy %}" defer nomodule></script>
|
||||
<script src="{% vite_asset_path app-legacy.js %}" defer nomodule></script>
|
||||
{% endunless %}
|
||||
</html>
|
||||
<!--
|
||||
|
|
|
|||
|
|
@ -0,0 +1,3 @@
|
|||
Jekyll::Hooks.register(:site, :after_init) do |site|
|
||||
site.config['exclude'].push(*(site.config['addition_exclude'] || []))
|
||||
end
|
||||
|
|
@ -0,0 +1,263 @@
|
|||
require 'vite_ruby'
|
||||
require "jekyll/filters"
|
||||
require "ostruct"
|
||||
|
||||
module Jekyll::Vite
|
||||
end
|
||||
|
||||
class Jekyll::Vite::Generator < Jekyll::Generator
|
||||
safe true
|
||||
priority :highest
|
||||
|
||||
class ViteAssetFile < Jekyll::StaticFile
|
||||
# Override (4.2): Copy to the configured public_output_dir
|
||||
if method_defined?(:cleaned_relative_path)
|
||||
def cleaned_relative_path
|
||||
replace_build_path(super)
|
||||
end
|
||||
end
|
||||
|
||||
# Override: Copy to the configured public_output_dir
|
||||
def destination_rel_dir
|
||||
replace_build_path(super)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def replace_build_path(src)
|
||||
src.sub(
|
||||
@site.vite_ruby_instance.config.build_output_dir.relative_path_from(@site.source).to_s,
|
||||
@site.vite_ruby_instance.config.public_output_dir,
|
||||
)
|
||||
end
|
||||
end
|
||||
|
||||
# Internal: Set the mode based on which command was run.
|
||||
# Builds assets with Vite only if `jekyll build` was run.
|
||||
def generate(site)
|
||||
cache_dir = site.config['cache_dir'] || '.jekyll-cache'
|
||||
vr = ViteRuby.new(
|
||||
mode: Jekyll.env,
|
||||
public_dir: cache_dir,
|
||||
build_cache_dir: File.join(cache_dir, 'vite-build'),
|
||||
**(site.config['vite'].transform_keys(&:to_sym) || {})
|
||||
)
|
||||
site.reader.read_data
|
||||
vr.env['site_config'] = Jekyll_Filters.new.jsonify(site.config)
|
||||
vr.env['site_data'] = Jekyll_Filters.new.jsonify(site.data)
|
||||
vr.env['site_categories'] = Jekyll_Filters.new.jsonify(site.categories)
|
||||
vr.logger = Jekyll.logger
|
||||
|
||||
class << site
|
||||
def vite_ruby_instance
|
||||
@__vite_ruby_instance
|
||||
end
|
||||
def vite_ruby_instance=(vr)
|
||||
@__vite_ruby_instance = vr
|
||||
end
|
||||
end
|
||||
site.vite_ruby_instance = vr
|
||||
if Jekyll.env == 'production'
|
||||
vr.commands.clobber
|
||||
end
|
||||
generate_vite_build(site)
|
||||
end
|
||||
|
||||
class Jekyll_Filters
|
||||
include Jekyll::Filters
|
||||
end
|
||||
|
||||
# Internal: Build all assets with Vite and add them to the site's static files.
|
||||
def generate_vite_build(site)
|
||||
args = []
|
||||
viteConfig = site.config['vite']&.fetch('viteConfig', "")
|
||||
if viteConfig != ""
|
||||
args += ["--config", viteConfig]
|
||||
end
|
||||
site.vite_ruby_instance.commands.build(*args) || raise("Vite build failed")
|
||||
add_static_files(site, site.vite_ruby_instance.config.build_output_dir)
|
||||
end
|
||||
|
||||
# Internal: Add generated assets to the site's static files.
|
||||
def add_static_files(site, assets_dir)
|
||||
relative_assets_dir = assets_dir.relative_path_from(site.source).to_s
|
||||
vite_static_files = Dir.chdir(assets_dir.to_s) {
|
||||
Dir.glob('**/*').select { |f| File.file?(f) }
|
||||
}.map { |file|
|
||||
ViteAssetFile.new(site, site.source, relative_assets_dir, file)
|
||||
}
|
||||
site.static_files.concat(vite_static_files)
|
||||
end
|
||||
end
|
||||
|
||||
class Jekyll::Vite::Tag < Jekyll::Tags::IncludeTag
|
||||
include Jekyll::Filters::URLFilters
|
||||
|
||||
# Override: Set the context to make the site available in the URLFilters.
|
||||
def render(context)
|
||||
@context = context
|
||||
@params = @params.is_a?(String) ? parse_params(context).transform_keys(&:to_sym) : @params || {}
|
||||
if @file = render_variable(@file)
|
||||
validate_file_name(@file)
|
||||
track_file_dependency(@file)
|
||||
end
|
||||
block_given? ? yield : raise(NotImplementedError, "Implement render in #{ self.class.name }")
|
||||
end
|
||||
|
||||
# Override: Modified version that can resolve recursive references.
|
||||
def render_variable(variable)
|
||||
variable = Liquid::Template.parse(variable).render!(@context) while VARIABLE_SYNTAX =~ variable
|
||||
variable
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
# Internal: Resolves the path for the specified Vite asset.
|
||||
def vite_asset_path(name, **options)
|
||||
vite_manifest.path_for(name, **options)
|
||||
end
|
||||
|
||||
# Internal: Returns the current manifest loaded by Vite Ruby.
|
||||
def vite_manifest
|
||||
vite_ruby_instance.manifest
|
||||
end
|
||||
|
||||
def site
|
||||
@context.registers[:site]
|
||||
end
|
||||
|
||||
def vite_ruby_instance
|
||||
site.vite_ruby_instance
|
||||
end
|
||||
|
||||
# Internal: Renders HTML attributes inside a tag.
|
||||
def stringify_attrs(**attrs)
|
||||
attrs.map { |key, value| %(#{ key }="#{ value }") }.join(' ')
|
||||
end
|
||||
|
||||
# Internal: Renders an HTML tag of the specified type.
|
||||
def tag(type, **attrs)
|
||||
self_closing = type != :script
|
||||
%i[href src].each { |key| attrs[key] = relative_url(attrs[key]) if attrs.key?(key) }
|
||||
["<#{ type } ", stringify_attrs(**attrs), self_closing ? '/>' : "></#{ type }>"].join
|
||||
end
|
||||
|
||||
# Internal: Renders HTML link tags.
|
||||
def link_tags(sources, **attrs)
|
||||
sources.map { |href| tag(:link, href: href, **attrs) }.join("\n")
|
||||
end
|
||||
|
||||
# Internal: Renders HTML script tags.
|
||||
def script_tags(sources, **attrs)
|
||||
sources.map { |src| tag(:script, src: src, **attrs) }.join("\n")
|
||||
end
|
||||
|
||||
# Internal: Adds entrypoint files managed by Vite as a dependency in the
|
||||
# renegerator in order to support --incremental mode.
|
||||
def track_file_dependency(name)
|
||||
path = site.in_source_dir(File.join(vite_ruby_instance.config.source_code_dir, vite_ruby_instance.config.entrypoints_dir, name))
|
||||
|
||||
['', '.css', '.js', '.ts'].each do |ext|
|
||||
if File.file?(asset_path = "#{ path }#{ ext }")
|
||||
return [asset_path, last_build_metadata_path].each do |filename|
|
||||
add_include_to_dependency(site, filename.to_s, @context)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
# Internal: Adding the last build metadata file as a dependency ensures
|
||||
# all pages using Vite assets are regenerated if a Vite build is triggered.
|
||||
def last_build_metadata_path
|
||||
vite_ruby_instance.builder.send(:last_build_path, ssr: false)
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Renders a path to a Vite asset.
|
||||
class Jekyll::Vite::AssetPathTag < Jekyll::Vite::Tag
|
||||
def render(context)
|
||||
super { vite_asset_path(@file, **@params) }
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Renders the @vite/client script tag.
|
||||
class Jekyll::Vite::ClientTag < Jekyll::Vite::Tag
|
||||
def render(context)
|
||||
@context = context
|
||||
return unless src = vite_manifest.vite_client_src
|
||||
|
||||
super {
|
||||
tag :script, src: src, type: 'module'
|
||||
}
|
||||
end
|
||||
|
||||
def syntax_example
|
||||
"{% #{ @tag_name } %}"
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Renders a script tag to enable HMR with React Refresh.
|
||||
class Jekyll::Vite::ReactRefreshTag < Jekyll::Vite::Tag
|
||||
def render(_context)
|
||||
vite_manifest.react_refresh_preamble&.html_safe
|
||||
end
|
||||
|
||||
def syntax_example
|
||||
"{% #{ @tag_name } %}"
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Renders a <link> tag for the specified stylesheet.
|
||||
class Jekyll::Vite::StylesheetTag < Jekyll::Vite::Tag
|
||||
def render(context)
|
||||
super {
|
||||
tag :link, **{
|
||||
rel: 'stylesheet',
|
||||
href: vite_asset_path(@file, type: :stylesheet),
|
||||
media: 'screen',
|
||||
}.merge(@params)
|
||||
}
|
||||
end
|
||||
|
||||
def syntax_example
|
||||
"{% #{ @tag_name } application.scss media='screen, projection' %}"
|
||||
end
|
||||
end
|
||||
|
||||
# Public: Renders a <script> tag for the specified file.
|
||||
class Jekyll::Vite::JavascriptTag < Jekyll::Vite::Tag
|
||||
def render(context)
|
||||
super {
|
||||
media = @params.delete(:media) || 'screen'
|
||||
crossorigin = @params.delete(:crossorigin) || 'anonymous'
|
||||
type = @params.delete(:type) || 'module'
|
||||
asset_type = @tag_name == 'vite_typescript_tag' ? :typescript : :javascript
|
||||
|
||||
entries = vite_manifest.resolve_entries(@file, type: asset_type)
|
||||
|
||||
[
|
||||
script_tags(entries.fetch(:scripts), crossorigin: crossorigin, type: type, **@params),
|
||||
link_tags(entries.fetch(:imports), rel: 'modulepreload', as: 'script', crossorigin: crossorigin, **@params),
|
||||
link_tags(entries.fetch(:stylesheets), rel: 'stylesheet', media: media, crossorigin: crossorigin, **@params),
|
||||
].join("\n")
|
||||
}
|
||||
end
|
||||
|
||||
def syntax_example
|
||||
"{% #{ @tag_name } application %}"
|
||||
end
|
||||
end
|
||||
|
||||
# Recreating tag helpers in Jekyll requires considerably more code than in web
|
||||
# frameworks, since Liquid does not provide HTML helpers and parsing parameters
|
||||
# is more complex than a Ruby method invocation.
|
||||
{
|
||||
'vite_asset_path' => Jekyll::Vite::AssetPathTag,
|
||||
'vite_client_tag' => Jekyll::Vite::ClientTag,
|
||||
'vite_javascript_tag' => Jekyll::Vite::JavascriptTag,
|
||||
'vite_typescript_tag' => Jekyll::Vite::JavascriptTag,
|
||||
'vite_stylesheet_tag' => Jekyll::Vite::StylesheetTag,
|
||||
'vite_react_refresh_tag' => Jekyll::Vite::ReactRefreshTag,
|
||||
}.each do |name, tag|
|
||||
Liquid::Template.register_tag(name, tag)
|
||||
end
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
<script setup>
|
||||
</script>
|
||||
|
||||
<template>
|
||||
</template>
|
||||
|
|
@ -0,0 +1,5 @@
|
|||
import Empty from '../components/Empty.vue'
|
||||
import { createApp } from 'vue';
|
||||
|
||||
const empty = createApp(Empty);
|
||||
empty.mount("#upgrade-mask");
|
||||
|
|
@ -0,0 +1,12 @@
|
|||
{
|
||||
"all": {
|
||||
"sourceCodeDir": "_src",
|
||||
"watchAdditionalPaths": ["index.html", "_includes/**/*", "_layouts/**/*", "_config.yml", "vite.config.mjs"],
|
||||
"publicOutputDir": "",
|
||||
"assetsDir": "assets"
|
||||
},
|
||||
"development": {
|
||||
"autoBuild": true,
|
||||
"publicOutputDir": "vite-dev"
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,47 @@
|
|||
import { resolve } from 'path'
|
||||
import { defineConfig } from 'vite'
|
||||
import vue from '@vitejs/plugin-vue'
|
||||
import ruby from 'vite-plugin-ruby'
|
||||
import components from 'unplugin-vue-components/vite'
|
||||
import legacy from '@vitejs/plugin-legacy'
|
||||
|
||||
export default defineConfig(({mode})=>({
|
||||
build: {
|
||||
emptyOutDir: true,
|
||||
sourcemap: mode === 'production' ? false : true,
|
||||
minify: mode === 'production',
|
||||
},
|
||||
plugins: [
|
||||
(()=>{
|
||||
const exposedData = ['config', 'data', 'categories'];
|
||||
const jekyllData = Object.fromEntries(exposedData.map((key) => [key, JSON.parse(process.env[`site_${key}`] || '{}')]));
|
||||
const importNamePrefix = 'virtual:jekyll-';
|
||||
const loadNamePrefix = '\0' + importNamePrefix;
|
||||
|
||||
return {
|
||||
name: 'jekyll',
|
||||
resolveId(id) {
|
||||
if (id.startsWith(importNamePrefix)) {
|
||||
return loadNamePrefix + id.slice(importNamePrefix.length);
|
||||
}
|
||||
},
|
||||
load(id) {
|
||||
if (id.startsWith(loadNamePrefix)) {
|
||||
const key = id.slice(loadNamePrefix.length);
|
||||
return Object.entries(jekyllData[key]).map(([key, value]) => `export const ${key} = ${JSON.stringify(value)};`).join('\n');
|
||||
}
|
||||
},
|
||||
};
|
||||
})(),
|
||||
vue(),
|
||||
ruby(),
|
||||
components({
|
||||
dirs: [resolve(__dirname, '_src/components')],
|
||||
resolvers:[
|
||||
],
|
||||
}),
|
||||
legacy({
|
||||
targets: [],
|
||||
}),
|
||||
],
|
||||
}))
|
||||
File diff suppressed because it is too large
Load Diff
|
|
@ -0,0 +1,11 @@
|
|||
{
|
||||
"devDependencies": {
|
||||
"@vitejs/plugin-legacy": "^5.3.2",
|
||||
"@vitejs/plugin-vue": "^5.0.4",
|
||||
"sass": "^1.74.1",
|
||||
"terser": "^5.30.3",
|
||||
"unplugin-vue-components": "^0.26.0",
|
||||
"vite": "^5.2.8",
|
||||
"vite-plugin-ruby": "^5.0.0"
|
||||
}
|
||||
}
|
||||
|
|
@ -14,10 +14,6 @@ global_options.options.force_redirect_help_mirrors.forEach((m) => options[m] = {
|
|||
var descriptions = {};
|
||||
global_options.options.mirror_desc.forEach((m) => descriptions[m.name] = m.desc);
|
||||
|
||||
new Vue({
|
||||
el: "#upgrade-mask",
|
||||
});
|
||||
|
||||
const vmMirList = new Vue({
|
||||
el: "#mirror-list",
|
||||
data: {
|
||||
|
|
|
|||
Loading…
Reference in New Issue