当前位置: 首页 > news >正文

php网站多语言翻译怎么做工作组赴平凉事故现场

php网站多语言翻译怎么做,工作组赴平凉事故现场,私域流量营销,福步外贸论坛登录1 引言 在上一篇文章《解决Vditor加载Markdown网页很慢的问题(ViteJSVditor)》中#xff0c;我们通过设置域内CDN的方式解决Vditor加载Markdown网页很慢的问题。而在这篇文章中#xff0c;笔者将会开发实现一个前端中很常见的需求#xff1a;给基于Markdown渲染的文档网页增…1 引言 在上一篇文章《解决Vditor加载Markdown网页很慢的问题(ViteJSVditor)》中我们通过设置域内CDN的方式解决Vditor加载Markdown网页很慢的问题。而在这篇文章中笔者将会开发实现一个前端中很常见的需求给基于Markdown渲染的文档网页增加一个目录组件。 需要说明的是原生的Markdown标准并没有规定生成目录的写法但是国内的博文网站似乎都支持一个拓展来实现目录的生成 [toc]但是这样生成的目录是通常是位于文章页面的最上方这样就失去了目录的意义。比较好的实现是像CSDN或者掘金一样额外生成一个目录组件并且固定在侧栏上方。这样可以在浏览文章的时候随时定位所在的目录同时还可以使用目录来导航。 阅读本文可能需要的前置文章 《通过JS模板引擎实现动态模块组件(ViteJSHandlebars)》《使用Vditor将Markdown文档渲染成网页(ViteJSVditor)》 2 详叙 2.1 整体结构 将渲染Markdown文档的部分封装成单独的组件post-article.js、post-article.handlebars和post-article.css增加一个文章目录组件post-toc.js、post-toc.handlebars、post-toc.css。另外post-data.json是我们提前准备的博客文章里面除了保存有Markdown格式的文档字符串还有一些文章的相关数据1.png和2.png则是文章中图片。项目组织结构如下 my-native-js-app/ ├── public/ │ ├── 1.png │ ├── 2.png │ └── post-data.json ├── src/ │ ├── components/ │ │ ├── post-article.css │ │ ├── post-article.handlebars │ │ ├── post-article.js │ │ ├── post-toc.css │ │ ├── post-toc.handlebars │ │ └── post-toc.js │ ├── main.js │ └── style.css ├── index.html └── package.json 还是按照代码的执行顺序来介绍这个功能的实现。首先还是index.html !DOCTYPE html html langenheadmeta charsetUTF-8 /link relicon typeimage/svgxml href/vite.svg /meta nameviewport contentwidthdevice-width, initial-scale1.0 /titleVite App/title /headbodydiv idappdiv idpost-article-placeholder/divdiv idarticle-toc-placeholder/div/divscript typemodule src/src/main.js/script /body/html主要就是增加了post-article-placeholder和article-toc-placeholder这两个元素分别作为Markdown博文和博文目录的容器。其实这里面还有个页面布局的问题不过这个问题我们下一篇文章再说。这里还是先看main.js import ./style.css; import ./components/post-article.js;2.2 博文内容组件 引用了post-article.js也就是Markdown博文内容组件。那么就进入post-article.js import ./post-article.css; import { CreateTocPanel } from ./post-toc.js; import Handlebars from handlebars; import templateSource from ./post-article.handlebars?raw;import vditor/dist/index.css; import Vditor from vditor;// 初始化文章标签面板 async function InitializePostArticlePanel() {try { const response await fetch(/post-data.json);if (!response.ok) {throw new Error(网络无响应);}const blogData await response.json();// 编译模板const template Handlebars.compile(templateSource);// 渲染模板const renderedHtml template({blogMeta: blogData.blogMeta,});// 将渲染好的HTML插入到页面中document.getElementById(post-article-placeholder).innerHTML renderedHtml;// 显示内容Vditor.preview(document.getElementById(post-content), blogData.content, {cdn: window.location.origin,markdown: {toc: false,mark: true, //高亮显示footnotes: true, //脚注autoSpace: true, //自动空格适合中英文混合排版},math: {engine: KaTeX, //支持latex公式inlineDigit: true, //内联公式可以接数字},hljs: {style: github, //代码段样式lineNumber: true, //是否显示行号},anchor: 2, // 为标题添加锚点 0不渲染1渲染于标题前2渲染于标题后lang: zh_CN, //中文theme: {current: light, //light,dark,light,wechat},lazyLoadImage:https://cdn.jsdelivr.net/npm/vditor/dist/images/img-loading.svg,transform: (html) {// 使用正则表达式替换图片路径并添加居中样式及题注return html.replace(/img\s[^]*src\.\/([^])\.([a-zA-Z0-9])\s*alt([^]*)[^]*/g,(match, p1, p2, altText) {// const newSrc ${backendUrl}/blogs/resources/images/${postId}/${p1}.${p2};const newSrc ${p1}.${p2};const imgWithCaption div styletext-align: center;img src${newSrc} classcenter-image alt${altText}p classcaption${altText}/p/div;return imgWithCaption;});},after() {CreateTocPanel();},});} catch (error) {console.error(获取博客失败:, error);} }document.addEventListener(DOMContentLoaded, InitializePostArticlePanel);post-article.js中的内容改进自《通过JS模板引擎实现动态模块组件(ViteJSHandlebars)》中的案例不过略有不同。首先是获取博文数据 const response await fetch(/post-data.json); if (!response.ok) {throw new Error(网络无响应); } const blogData await response.json();// 编译模板 const template Handlebars.compile(templateSource);// 渲染模板 const renderedHtml template({blogMeta: blogData.blogMeta, });// 将渲染好的HTML插入到页面中 document.getElementById(post-article-placeholder).innerHTML renderedHtml;在实际项目开发中应该是从远端API获取数据这里进行了简化将数据提前准备好了放置在域内。然后将这个数据与编译的Handlebars模板一起渲染成HTML元素。从下面的post-article.handlebars中可以看到博文组件中内容不仅包含Markdown博文内容元素还有诸如时间、统计信息、标签等元素 div idmain-contenth1 idpost-title{{blogMeta.title}}/h1div classpost-statsspan class post-statspan/spanspan class text已于/span{{blogMeta.createdTime}}span class text修改/span/spanspan class post-statspan️/span{{blogMeta.postStats.viewCount}}span class text阅读/span/spanspan class post-statspan/span{{blogMeta.postStats.likeCount}}span class text点赞/span/spanspan class post-statspan/span{{blogMeta.postStats.commentCount}}span class text评论/span/span/divdiv classpost-tagsspan class tags-titlespan/spanspan class text文章标签/span/span{{#each blogMeta.tagNames}}span class post-tag{{this}}/span{{/each}}/divdiv classpost-categories专栏{{#each blogMeta.categoryNames}}span {{this}} /span{{/each}}收录该内容/divdiv idpost-content/div /divMarkdown博文内容元素是使用Vditor来渲染初始化的这一点与之前的案例一样。不同的是增加了一个after配置 import { CreateTocPanel } from ./post-toc.js;//...after() {CreateTocPanel(); },这个after配置的意思是当Vditor渲染完成以后就立刻执行CreateTocPanel()函数这个函数来自于博文目录组件post-toc.js表示要开始创建博文目录了。 2.2 博文目录组件 post-toc.js中的代码如下所示 import ./post-toc.css;import Handlebars from handlebars; import templateSource from ./post-toc.handlebars?raw;export function CreateTocPanel() {const headings document.querySelectorAll(#post-content h1, #post-content h2, #post-content h3);const tocContent [];headings.forEach((heading, index) {const content {};content[id] heading.id;content[title] heading.textContent;const marginLeft heading.tagName H2 ? 20 : heading.tagName H3 ? 40 : 0;content[marginLeft] marginLeft;tocContent.push(content);});// 编译模板const template Handlebars.compile(templateSource);// 渲染模板const renderedHtml template({tocContent,});// 将渲染好的HTML插入到页面中const articleTocPlaceholder document.getElementById(article-toc-placeholder);articleTocPlaceholder.innerHTML renderedHtml;// 联动滚动时同步激活目录项window.addEventListener(scroll, () {let activeHeading;headings.forEach((heading) {const rect heading.getBoundingClientRect();if (rect.top 0 rect.top window.innerHeight / 2) {activeHeading heading;}});if (activeHeading) {document.querySelectorAll(.toc-sidebar .toc a).forEach((link) link.classList.remove(active)); const escapedId CSS.escape(activeHeading.id); //安全地转义选择器中的特殊字符const activeLink document.querySelector(.toc-sidebar .toc a[href#${escapedId}]);if (activeLink) activeLink.classList.add(active);}}); }这段代码是实现博文目录功能的关键代码。首先搜索查询渲染成HTML形式的博文内容中的标题元素h1、h2和h3 const headings document.querySelectorAll(#post-content h1, #post-content h2, #post-content h3);然后提取出关键数据 const tocContent [];headings.forEach((heading, index) {const content {};content[id] heading.id;content[title] heading.textContent;const marginLeft heading.tagName H2 ? 20 : heading.tagName H3 ? 40 : 0;content[marginLeft] marginLeft;tocContent.push(content);});将其传入Handlebars模板进行渲染 // 编译模板const template Handlebars.compile(templateSource);// 渲染模板const renderedHtml template({tocContent,});// 将渲染好的HTML插入到页面中const articleTocPlaceholder document.getElementById(article-toc-placeholder);articleTocPlaceholder.innerHTML renderedHtml;模板post-toc.handlebars中的内容非常简单 div classtoc-sidebardiv classtoch3文章目录/h3ul{{#each tocContent}}li stylemargin-left: {{marginLeft}}px;a href#{{id}} class{{title}}/a/li{{/each}}/ul/div /div可以看到这里能够获取一级、二级还有三级标题通过样式的缩进margin-left来体现标题的不同。另外href属性的设置也保证了能通过点击来实现跳转。 最后实现联动通过文章标题元素范围的判定来高亮目录中标题元素的样式让用户直到浏览到博文中的哪一段了 // 联动滚动时同步激活目录项window.addEventListener(scroll, () {let activeHeading;headings.forEach((heading) {const rect heading.getBoundingClientRect();if (rect.top 0 rect.top window.innerHeight / 2) {activeHeading heading;}});if (activeHeading) {document.querySelectorAll(.toc-sidebar .toc a).forEach((link) link.classList.remove(active)); const escapedId CSS.escape(activeHeading.id); //安全地转义选择器中的特殊字符const activeLink document.querySelector(.toc-sidebar .toc a[href#${escapedId}]);if (activeLink) activeLink.classList.add(active);}});3 结语 最终实现的效果如下图所示 虽然功能大致实现了不过还有一些问题没有说清楚比如在浏览文章的过程中博文目录是如何始终保证黏在页面的右上角的这个问题就放在下篇中继续论述了。 实现代码
http://www.w-s-a.com/news/946001/

相关文章:

  • c2c网站设计店面logo设计制作
  • 网站建设任务执行书重庆今天新闻事件
  • 怎样发布自己的网站南宁制作网站公司
  • wordpress装多站点百度查一下
  • 怎么优化一个网站搭建网站免费空间
  • 山东建设和城乡建设厅注册中心网站首页wordpress安装教材
  • 个人风采网站制作毕节网站开发公司电话
  • 网络网站销售设计主题和设计理念
  • 做网站一般用什么服务器承德专业做网站
  • 松北区建设局网站网站建设分为几种
  • 网站建设的合同 体会智联招聘网站建设情况
  • 记的网站域名wordpress地方信息主题
  • 淄博好的建网站公司网站建设 海口
  • 有人做网站花了10几万2017做啥网站能致富
  • 做网站有什么软件cod建站平台
  • 合肥学校网站建设怎么做免费的产品图片网站
  • 营养早餐网站的设计与制作建设通网站怎么查项目经理在建
  • 浑南区建设局网站永州网站建设公司推荐
  • 做外贸都得有网站吗绵阳网站建设制作
  • 功能性的网站建设北京餐饮品牌设计公司
  • php做网站优势视频直播软件
  • 怎么安装php网站哪个网站是专门为建设方服务的
  • 重慶网站开发sina app engine wordpress
  • wampserver网站开发步骤中冠工程管理咨询有限公司
  • 自己做网站商城需要营业执照吗老外做牛排的视频网站
  • 网站推广效果的评估指标主要包括公司广告推广
  • 昆明网站建设那家好哪个网站学做凉皮
  • hype做网站动效哪里有给网站做
  • 打扑克网站推广软件设计类专业哪个最好
  • 网站设计首页网站建设意向书