towxml支持代码复制功能(支持uni-app)
<h2>uni-app中使用towxml</h2><p>步骤见: https://www.cnblogs.com/chuan2021/p/17223663.html</p>
<p> </p>
<h1>在微信小程序中的效果:</h1>
<p>展示的css可自行调整</p>
<p><img src="https://img2023.cnblogs.com/blog/1820780/202303/1820780-20230320121553145-1441964432.png"></p>
<p> </p>
<h1>支持代码复制:</h1>
<p>towxml先用mardown.js把mardown转换成html, 然后再解析html,最后渲染到towxml/decode.wxml页面中, 代码会渲染到</p>
<p>item.tag == "view" 一段中, 这里先在parse/index.js中增加一个参数, 好判断是不是代码块, 增加第18-27行, 为代码块和行内代码块增加raw_tag, 行内代码块不支持复制, 修改结果:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> arr.forEach(item =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.type === 'comment'<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 0, 255, 1)">return</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)"> 4</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)"> 5</span> let o =<span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 6</span> type: item.type === 'text' ? 'text' : isRichTextContent ? 'node'<span style="color: rgba(0, 0, 0, 1)"> : item.type
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> <span style="color: rgba(0, 0, 0, 1)"> },
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> e =<span style="color: rgba(0, 0, 0, 1)"> {},
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> attrs = o.attrs = item.attribs ||<span style="color: rgba(0, 0, 0, 1)"> {};
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.type === 'text'<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">11</span> o.text = e.text =<span style="color: rgba(0, 0, 0, 1)"> item.data;
</span><span style="color: rgba(0, 128, 128, 1)">12</span> } <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">13</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (isRichTextContent) {
</span><span style="color: rgba(0, 128, 128, 1)">14</span> o.name =<span style="color: rgba(0, 0, 0, 1)"> item.name;
</span><span style="color: rgba(0, 128, 128, 1)">15</span> } <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">16</span> o.tag = getWxmlTag(item.name); <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 转换之后的标签</span>
<span style="color: rgba(0, 128, 128, 1)">17</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> o.tag = o.tag === 'text' ? 'view' : o.tag;</span>
<span style="color: rgba(0, 128, 128, 1)">18</span> o.raw_tag =<span style="color: rgba(0, 0, 0, 1)"> item.name
</span><span style="color: rgba(0, 128, 128, 1)">19</span>
<span style="color: rgba(0, 128, 128, 1)">20</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> code block has parent element with class "h2w__pre"</span>
<span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> inline block has parent element with class "h2w__p" or "h2w__li"</span>
<span style="color: rgba(0, 128, 128, 1)">22</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> inline block no support copy</span>
<span style="color: rgba(0, 128, 128, 1)">23</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.name == "code" && item.parent && item.parent.attribs &&<span style="color: rgba(0, 0, 0, 1)"> item.parent.attribs.class) {
</span><span style="color: rgba(0, 128, 128, 1)">24</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.parent.attribs.class.indexOf('h2w__pre') === -1<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">25</span> o.raw_tag = "inline_code"
<span style="color: rgba(0, 128, 128, 1)">26</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">27</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">28</span>
<span style="color: rgba(0, 128, 128, 1)">29</span> e.tag = item.name; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 原始</span>
<span style="color: rgba(0, 128, 128, 1)">30</span> o.attrs =<span style="color: rgba(0, 0, 0, 1)"> item.attribs;
</span><span style="color: rgba(0, 128, 128, 1)">31</span> e.attrs =<span style="color: rgba(0, 0, 0, 1)"> JSON.parse(JSON.stringify(attrs));
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)">33</span> attrs.class = attrs.class ?<span style="color: rgba(0, 0, 0, 1)"> `h2w__${item.name} ${attrs.class}` : `h2w__${item.name}`;
</span><span style="color: rgba(0, 128, 128, 1)">34</span>
<span style="color: rgba(0, 128, 128, 1)">35</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 处理资源相对路径</span>
<span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (base &&<span style="color: rgba(0, 0, 0, 1)"> attrs.src) {
</span><span style="color: rgba(0, 128, 128, 1)">37</span> let src =<span style="color: rgba(0, 0, 0, 1)"> attrs.src;
</span><span style="color: rgba(0, 128, 128, 1)">38</span> <span style="color: rgba(0, 0, 255, 1)">switch</span> (src.indexOf('//'<span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 0, 255, 1)">case</span> 0<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 128, 128, 1)">40</span> attrs.src =<span style="color: rgba(0, 0, 0, 1)"> `https:${src}`;
</span><span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 0, 255, 1)">case</span> -1<span style="color: rgba(0, 0, 0, 1)">:
</span><span style="color: rgba(0, 128, 128, 1)">43</span> attrs.src =<span style="color: rgba(0, 0, 0, 1)"> `${base}${src}`;
</span><span style="color: rgba(0, 128, 128, 1)">44</span> <span style="color: rgba(0, 0, 255, 1)">break</span><span style="color: rgba(0, 0, 0, 1)">;
</span><span style="color: rgba(0, 128, 128, 1)">45</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)">46</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)">47</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)">48</span>
<span style="color: rgba(0, 128, 128, 1)">49</span> o.rely = relyList.indexOf(e.tag) > -1; <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 判断是否不能嵌套其它标签</span>
<span style="color: rgba(0, 128, 128, 1)">50</span>
<span style="color: rgba(0, 128, 128, 1)">51</span> <span style="color: rgba(0, 0, 255, 1)">if</span><span style="color: rgba(0, 0, 0, 1)"> (item.children) {
</span><span style="color: rgba(0, 128, 128, 1)">52</span> eachFn(item.children, o, e, isRichTextContent || item.name === 'rich-text'<span style="color: rgba(0, 0, 0, 1)">);
</span><span style="color: rgba(0, 128, 128, 1)">53</span> <span style="color: rgba(0, 0, 0, 1)"> };
</span><span style="color: rgba(0, 128, 128, 1)">54</span> <span style="color: rgba(0, 0, 0, 1)"> child.push(o);
</span><span style="color: rgba(0, 128, 128, 1)">55</span> <span style="color: rgba(0, 0, 0, 1)"> child_e.push(e);
</span><span style="color: rgba(0, 128, 128, 1)">56</span> });</pre>
</div>
<p>然后在decode.wxml的h2w__viewParent一段下进行判断和增加复制按钮:</p>
<p>towxml/decode.wxml</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> <block wx:<span style="color: rgba(0, 0, 255, 1)">if</span>="{{item.tag==='view'}}">
<span style="color: rgba(0, 128, 128, 1)"> 2</span> <block wx:<span style="color: rgba(0, 0, 255, 1)">if</span>="{{item.rely}}">
<span style="color: rgba(0, 128, 128, 1)"> 3</span> <view data-data="{{item}}" class="{{item.attrs.class}}" data="{{item.attrs.data}}" id="{{item.attrs.id}}" style="{{item.attrs.style}}" <span style="color: rgba(0, 0, 255, 1)">catch</span>:tap="_tap">
<span style="color: rgba(0, 128, 128, 1)"> 4</span> <decode wx:<span style="color: rgba(0, 0, 255, 1)">if</span>="{{item.children}}" nodes="{{item}}"/>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> </view>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> </block>
<span style="color: rgba(0, 128, 128, 1)"> 7</span> <block wx:<span style="color: rgba(0, 0, 255, 1)">else</span>>
<span style="color: rgba(0, 128, 128, 1)"> 8</span> <view class="h2w__viewParent">
<span style="color: rgba(0, 128, 128, 1)"> 9</span> <view data-data="{{item}}" class="{{item.attrs.class}}" data="{{item.attrs.data}}" id="{{item.attrs.id}}" style="{{item.attrs.style}}" <span style="color: rgba(0, 0, 255, 1)">catch</span>:tap="_tap">
<span style="color: rgba(0, 128, 128, 1)">10</span> <block wx:<span style="color: rgba(0, 0, 255, 1)">if</span>="{{item.raw_tag === 'code'}}">
<span style="color: rgba(0, 128, 128, 1)">11</span> <view style="float: right" <span style="color: rgba(0, 0, 255, 1)">catch</span>:tap="_copy" data-data="{{item}}" data="{{item.attrs.data}}">复制</view>
<span style="color: rgba(0, 128, 128, 1)">12</span> </block>
<span style="color: rgba(0, 128, 128, 1)">13</span> <decode wx:<span style="color: rgba(0, 0, 255, 1)">if</span>="{{item.children}}" nodes="{{item}}"/>
<span style="color: rgba(0, 128, 128, 1)">14</span> </view>
<span style="color: rgba(0, 128, 128, 1)">15</span> </view>
<span style="color: rgba(0, 128, 128, 1)">16</span> </block>
<span style="color: rgba(0, 128, 128, 1)">17</span> </block></pre>
</div>
<p>可以看到这里我们新增了一个copy函数, 专门支持复制代码块, 为了支持新event. 还需要改towxml/config.js中的events字段:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)">1</span> <span style="color: rgba(0, 0, 0, 1)"> events:[
</span><span style="color: rgba(0, 128, 128, 1)">2</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'touchstart',</span>
<span style="color: rgba(0, 128, 128, 1)">3</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'touchmove',</span>
<span style="color: rgba(0, 128, 128, 1)">4</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'touchcancel',</span>
<span style="color: rgba(0, 128, 128, 1)">5</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 'touchend',</span>
<span style="color: rgba(0, 128, 128, 1)">6</span> 'tap', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用于元素的点击事件</span>
<span style="color: rgba(0, 128, 128, 1)">7</span> 'change', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 用于todoList的change事件</span>
<span style="color: rgba(0, 128, 128, 1)">8</span> 'copy', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 代码复制事件</span>
<span style="color: rgba(0, 128, 128, 1)">9</span> ],</pre>
</div>
<p>然后就可以在uni-app中处理该点击事件:</p>
<div class="cnblogs_code">
<pre><span style="color: rgba(0, 128, 128, 1)"> 1</span> let md = <span style="color: rgba(0, 0, 255, 1)">this</span><span style="color: rgba(0, 0, 0, 1)">.$towxml(src,
</span><span style="color: rgba(0, 128, 128, 1)"> 2</span> 'markdown'<span style="color: rgba(0, 0, 0, 1)">, {
</span><span style="color: rgba(0, 128, 128, 1)"> 3</span> <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> base: 'https://xxx.com', // 相对资源的base路径</span>
<span style="color: rgba(0, 128, 128, 1)"> 4</span> theme: 'light', <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 主题,默认`light`</span>
<span style="color: rgba(0, 128, 128, 1)"> 5</span> events: { <span style="color: rgba(0, 128, 0, 1)">//</span><span style="color: rgba(0, 128, 0, 1)"> 为元素绑定的事件方法</span>
<span style="color: rgba(0, 128, 128, 1)"> 6</span> tap: (e) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)"> 7</span> console.log('tap'<span style="color: rgba(0, 0, 0, 1)">, e);
</span><span style="color: rgba(0, 128, 128, 1)"> 8</span> <span style="color: rgba(0, 0, 0, 1)"> },
</span><span style="color: rgba(0, 128, 128, 1)"> 9</span> copy: (e) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">10</span> <span style="color: rgba(0, 0, 0, 1)"> console.log(e.target.dataset.data)
</span><span style="color: rgba(0, 128, 128, 1)">11</span> let copyed_code = ""
<span style="color: rgba(0, 128, 128, 1)">12</span>
<span style="color: rgba(0, 128, 128, 1)">13</span> const extract_code = (parsed_item) =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">14</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (!<span style="color: rgba(0, 0, 0, 1)">parsed_item.children) {
</span><span style="color: rgba(0, 128, 128, 1)">15</span> <span style="color: rgba(0, 0, 255, 1)">return</span>
<span style="color: rgba(0, 128, 128, 1)">16</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">17</span> parsed_item.children.forEach(item =><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">18</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.raw_tag == "ul" || (item.attrs.class &&<span style="color: rgba(0, 0, 0, 1)"> item.attrs.class
</span><span style="color: rgba(0, 128, 128, 1)">19</span> .indexOf("h2w__lineNum") != -1<span style="color: rgba(0, 0, 0, 1)">)) {
</span><span style="color: rgba(0, 128, 128, 1)">20</span> console.log('find number'<span style="color: rgba(0, 0, 0, 1)">)
</span><span style="color: rgba(0, 128, 128, 1)">21</span> <span style="color: rgba(0, 0, 255, 1)">return</span>
<span style="color: rgba(0, 128, 128, 1)">22</span> } <span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.raw_tag == "p"<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">23</span> copyed_code = copyed_code + "\n\n"
<span style="color: rgba(0, 128, 128, 1)">24</span> } <span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.raw_tag == "br"<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">25</span> copyed_code = copyed_code + "\n"
<span style="color: rgba(0, 128, 128, 1)">26</span> } <span style="color: rgba(0, 0, 255, 1)">else</span> <span style="color: rgba(0, 0, 255, 1)">if</span> (item.type == "text"<span style="color: rgba(0, 0, 0, 1)">) {
</span><span style="color: rgba(0, 128, 128, 1)">27</span> copyed_code = copyed_code +<span style="color: rgba(0, 0, 0, 1)"> item.text
</span><span style="color: rgba(0, 128, 128, 1)">28</span> } <span style="color: rgba(0, 0, 255, 1)">else</span><span style="color: rgba(0, 0, 0, 1)"> {
</span><span style="color: rgba(0, 128, 128, 1)">29</span> <span style="color: rgba(0, 0, 0, 1)"> extract_code(item)
</span><span style="color: rgba(0, 128, 128, 1)">30</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">31</span> <span style="color: rgba(0, 0, 0, 1)"> })
</span><span style="color: rgba(0, 128, 128, 1)">32</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">33</span>
<span style="color: rgba(0, 128, 128, 1)">34</span> <span style="color: rgba(0, 0, 0, 1)"> extract_code(e.target.dataset.data)
</span><span style="color: rgba(0, 128, 128, 1)">35</span>
<span style="color: rgba(0, 128, 128, 1)">36</span> <span style="color: rgba(0, 0, 0, 1)"> uni.setClipboardData({
</span><span style="color: rgba(0, 128, 128, 1)">37</span> <span style="color: rgba(0, 0, 0, 1)"> data: copyed_code,
</span><span style="color: rgba(0, 128, 128, 1)">38</span> showToast: <span style="color: rgba(0, 0, 255, 1)">true</span><span style="color: rgba(0, 0, 0, 1)">,
</span><span style="color: rgba(0, 128, 128, 1)">39</span> <span style="color: rgba(0, 0, 0, 1)"> });
</span><span style="color: rgba(0, 128, 128, 1)">40</span> <span style="color: rgba(0, 0, 0, 1)"> },
</span><span style="color: rgba(0, 128, 128, 1)">41</span> <span style="color: rgba(0, 0, 0, 1)"> }
</span><span style="color: rgba(0, 128, 128, 1)">42</span> <span style="color: rgba(0, 0, 0, 1)"> });
</span><span style="color: rgba(0, 128, 128, 1)">43</span> <span style="color: rgba(0, 0, 255, 1)">this</span>.article = md;</pre>
</div>
<p> </p>
<p>因为事件中的dataset传过来的是解析好的数据, 这里重新组件了一下, 代码有些简陋, 可以自行修改.</p><br><br>
来源:https://www.cnblogs.com/chuan2021/p/17223727.html
頁:
[1]