使用 Lua for Pandoc 将 Markdown 警告语法转换为 HTML

2023-11-30

Markdown 警告语法基于https://python-markdown.github.io/extensions/admonition/:

!!! note Important note
    You should note that the title will be automatically capitalized.

Pandoc 文档的解释很差,写得也很糟糕。我用以下问题来训练自己:

  • Pandoc Lua:如何在标题周围添加 Markdown 块而不丢失 Markdown 语法 #
  • 使用自定义 Markdown 语法扩展 Pandoc
  • 从 Markdown 转换为 HTML 时,使用 Pandoc Lua 过滤器替换 HTML 标签
  • pandoc lua 过滤器替换 tex 宏
  • Pandoc Lua 过滤器:如何指定 Span 元素的属性
  • Pandoc过滤器pandoc.Para Lua函数中的字符转义
  • 自定义 pandoc writer 中的 PandocLuaError“所有选择失败”

我尝试用 Lua 构建:

function Para (para)
  if para.content[1].text == "!!!" and para.content[1].text == "note" then
    return pandoc.Plain(
      {pandoc.RawInline('html', '<div class="admonition note">')} ..
      {pandoc.RawInline('html', '<p class="admonition-title">')} ..
      para.content[2].text ..
      {pandoc.RawInline('html', '</p>')} ..
      para.content[3].text ..
      {pandoc.RawInline('html', '</div>')}
    )
  elseif para.content[1].text == "!!!" and para.content[1].text == "danger" then
    return pandoc.Plain(
      {pandoc.RawInline('html', '<div class="admonition danger">')} ..
      {pandoc.RawInline('html', '<p class="admonition-title">')} ..
      para.content[2].text ..
      {pandoc.RawInline('html', '</p>')} ..
      para.content[3].text ..
      {pandoc.RawInline('html', '</div>')}
    )
  end
end

我期望:

<div class="admonition note">
<p class="admonition-title">Important note</p>
<p>You should note that the title will be automatically capitalized.</p>
</div>

Update 1

它几乎成功了,我只是不喜欢para.content[number].text因为我需要将“重要说明”作为警告标题,并在该警告标题之后捕获整个句子作为段落。

function Para(para)
  if para.content[1].text == '!!!' and para.content[2].tag == 'Space' and para.content[3].text == 'note' then
    return pandoc.RawInline('html',
      '<div class="admonition note">'
        .. '\n\t' ..
        '<p class="admonition-title">' 
          .. para.content[5].text .. 
        '</p>'
        .. '\n\t' ..
        para.content[5].text ..
        '\n' .. 
      '</div>')
  elseif para.content[1].text == '!!!' and para.content[2].tag == 'Space' and para.content[3].text == 'danger' then
    return pandoc.Emph {pandoc.Str "Danger"}
  end
end

Update 2

您的答案有效,但不适用于两个代码:

  1. 当没有标题时,它看起来像:
!!! important ""

但它给出了一个输出:

<div class="admonition important ““"><p class="admonition-title">IMPORTANT</p>
admonition with no title
</div>

你可以注意到important ““"。如果我想使用""要隐藏标题,它会给出一个输出:<div class="admonition important"><p class="admonition-title no-title">IMPORTANT</p></div>.

  1. 当我想包含一个比段落,包含斜体,粗体,blockquote, code等,您的过滤器仅采用第一段,因此会忽略文本的其余部分。你可以看看参考资料:https://github.com/qjebbs/vscode-markdown-extended#admonition。它应该类似于 HTML:
<div class="admonition important"><p class="admonition-title">IMPORTANT</p>
<p> Here is the first paragraph with a <code>code</code>...</p>
<p> Here is the second paragraph with <i>italic</i> and <b>boild</b>...
<pre><code class="language-css">.css { color: black; }</code></pre>
<blockquote>
Accidit in puncto, quod non contingit in anno
</blockquote>
Julius Caesarus
</div>

Update 3

请原谅我之前未能为您提供完整的 CSS 代码。获取下面的完整代码:

@font-face {
    font-family: "Material Icons";
    font-style: normal;
    font-weight: 400;
    src: local("Material Icons"), local("MaterialIcons-Regular"), url("data:application/x-font-woff;charset=utf-8;base64,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") format("woff");
}

.admonition {
    box-shadow: 0 2px 2px 0 rgba(0, 0, 0, .14), 0 1px 5px 0 rgba(0, 0, 0, .12), 0 3px 1px -2px rgba(0, 0, 0, .2);
    position: relative;
    margin: 1.5625em 0;
    padding: 0 1.2rem;
    border-left: .4rem solid rgba(68, 138, 255, .8);
    border-radius: .2rem;
    background-color: rgba(255, 255, 255, 0.05);
    overflow: auto;
}

.admonition>p {
    margin-top: .8rem;
}

.admonition>.admonition-title {
    margin: 0 -1.2rem;
    padding: .8rem 1.2rem .8rem 3.6rem;
    border-bottom: 1px solid rgba(68, 138, 255, .2);
    background-color: rgba(68, 138, 255, .1);
    font-weight: 700;
}

.admonition>.admonition-title:before {
    position: absolute;
    left: 1.2rem;
    font-size: 1.5rem;
    color: rgba(68, 138, 255, .8);
    content: "\E3C9";
}

.admonition>.admonition-title:before {
    font-family: Material Icons;
    font-style: normal;
    font-variant: normal;
    font-weight: 400;
    line-height: 2rem;
    text-transform: none;
    white-space: nowrap;
    speak: none;
    word-wrap: normal;
    direction: ltr;
}

.admonition.summary,
.admonition.abstract,
.admonition.tldr {
    border-left-color: rgba(0, 176, 255, .8);
}

.admonition.summary>.admonition-title,
.admonition.abstract>.admonition-title,
.admonition.tldr>.admonition-title {
    background-color: rgba(0, 176, 255, .1);
    border-bottom-color: rgba(0, 176, 255, .2);
}

.admonition.summary>.admonition-title:before,
.admonition.abstract>.admonition-title:before,
.admonition.tldr>.admonition-title:before {
    color: rgba(0, 176, 255, 1);
    ;
    content: "\E8D2";
}

.admonition.hint,
.admonition.tip {
    border-left-color: rgba(0, 191, 165, .8);
}

.admonition.hint>.admonition-title,
.admonition.tip>.admonition-title {
    background-color: rgba(0, 191, 165, .1);
    border-bottom-color: rgba(0, 191, 165, .2);
}

.admonition.hint>.admonition-title:before,
.admonition.tip>.admonition-title:before {
    color: rgba(0, 191, 165, 1);
    content: "\E80E";
}

.admonition.info,
.admonition.todo {
    border-left-color: rgba(0, 184, 212, .8);
}

.admonition.info>.admonition-title,
.admonition.todo>.admonition-title {
    background-color: rgba(0, 184, 212, .1);
    border-bottom-color: rgba(0, 184, 212, .2);
}

.admonition.info>.admonition-title:before,
.admonition.todo>.admonition-title:before {
    color: rgba(0, 184, 212, 1);
    ;
    content: "\E88E";
}

.admonition.success,
.admonition.check,
.admonition.done {
    border-left-color: rgba(0, 200, 83, .8);
}

.admonition.success>.admonition-title,
.admonition.check>.admonition-title,
.admonition.done>.admonition-title {
    background-color: rgba(0, 200, 83, .1);
    border-bottom-color: rgba(0, 200, 83, .2);
}

.admonition.success>.admonition-title:before,
.admonition.check>.admonition-title:before,
.admonition.done>.admonition-title:before {
    color: rgba(0, 200, 83, 1);
    ;
    content: "\E876";
}

.admonition.question,
.admonition.help,
.admonition.faq {
    border-left-color: rgba(100, 221, 23, .8);
}

.admonition.question>.admonition-title,
.admonition.help>.admonition-title,
.admonition.faq>.admonition-title {
    background-color: rgba(100, 221, 23, .1);
    border-bottom-color: rgba(100, 221, 23, .2);
}

.admonition.question>.admonition-title:before,
.admonition.help>.admonition-title:before,
.admonition.faq>.admonition-title:before {
    color: rgba(100, 221, 23, 1);
    ;
    content: "\E887";
}

.admonition.warning,
.admonition.attention,
.admonition.caution {
    border-left-color: rgba(255, 145, 0, .8);
}

.admonition.warning>.admonition-title,
.admonition.attention>.admonition-title,
.admonition.caution>.admonition-title {
    background-color: rgba(255, 145, 0, .1);
    border-bottom-color: rgba(255, 145, 0, .2);
}

.admonition.attention>.admonition-title:before {
    color: rgba(255, 145, 0, 1);
    content: "\E417";
}

.admonition.warning>.admonition-title:before,
.admonition.caution>.admonition-title:before {
    color: rgba(255, 145, 0, 1);
    content: "\E002";
}

.admonition.failure,
.admonition.fail,
.admonition.missing {
    border-left-color: rgba(255, 82, 82, .8);
}

.admonition.failure>.admonition-title,
.admonition.fail>.admonition-title,
.admonition.missing>.admonition-title {
    background-color: rgba(255, 82, 82, .1);
    border-bottom-color: rgba(255, 82, 82, .2);
}

.admonition.failure>.admonition-title:before,
.admonition.fail>.admonition-title:before,
.admonition.missing>.admonition-title:before {
    color: rgba(255, 82, 82, 1);
    ;
    content: "\E14C";
}

.admonition.danger,
.admonition.error,
.admonition.bug {
    border-left-color: rgba(255, 23, 68, .8);
}

.admonition.danger>.admonition-title,
.admonition.error>.admonition-title,
.admonition.bug>.admonition-title {
    background-color: rgba(255, 23, 68, .1);
    border-bottom-color: rgba(255, 23, 68, .2);
}

.admonition.danger>.admonition-title:before {
    color: rgba(255, 23, 68, 1);
    content: "\E3E7";
}

.admonition.error>.admonition-title:before {
    color: rgba(255, 23, 68, 1);
    content: "\E14C";
}

.admonition.bug>.admonition-title:before {
    color: rgba(255, 23, 68, 1);
    content: "\E868";
}

.admonition.example,
.admonition.snippet {
    border-left-color: rgba(0, 184, 212, .8);
}

.admonition.example>.admonition-title,
.admonition.snippet>.admonition-title {
    background-color: rgba(0, 184, 212, .1);
    border-bottom-color: rgba(0, 184, 212, .2);
}

.admonition.example>.admonition-title:before,
.admonition.snippet>.admonition-title:before {
    color: rgba(0, 184, 212, 1);
    ;
    content: "\E242";
}

.admonition.quote,
.admonition.cite {
    border-left-color: rgba(158, 158, 158, .8);
}

.admonition.quote>.admonition-title,
.admonition.cite>.admonition-title {
    background-color: rgba(158, 158, 158, .1);
    border-bottom-color: rgba(158, 158, 158, .2);
}

.admonition.quote>.admonition-title:before,
.admonition.cite>.admonition-title:before {
    color: rgba(158, 158, 158, 1);
    ;
    content: "\E244";
}

.no-title
{
    display: none;
}

我已经承认 Pandoc 的新 Markdown 语法定义,但使用它是一个坏主意dl, dt and dd用于警告,因为它们是为定义、词典和术语表而设计的。但无论如何,我也测试了使用和不使用 Markdown 语法的情况:这不是我所期望的。

使用更新后的 Lua 代码,结果如下(单击图像放大):

result

在第二个警告中,您的过滤器没有删除标题。

预期的:

expected

您可以比较图像并轻松理解。

我为你准备了 Markdown 和 HTML 代码。

这是 Markdown 代码:

<!-- With title -->
!!! note "Pay attention!"
    Title for notes

    some code and text
    
    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    Title for denger
    
    some code and text

    ```python
    print
    ```

    It is not a good

<!-- Without title -->
!!! note ""
    Title for notes

    some code and text

    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    Title for denger
    
    some code and text

    ```python
    print
    ```

    It is not a good

以及 HTML 代码:

  <!-- With title -->

  <div class="admonition note">
    <p class="admonition-title">Pay attention!</p>

    <p>Title for notes</p>
    <p>some code and text</p>
    <div class="sourceCode" id="cb1">
      <pre class="sourceCode C"><code class="sourceCode c"><span id="cb1-1"><a href="#cb1-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(){</span></span>
<span id="cb1-2"><a href="#cb1-2" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;Hello World!&quot;</span><span class="op">);</span></span>
<span id="cb1-3"><a href="#cb1-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre>
    </div>
    <p>It is a good code.</p>
    <div class="admonition danger">
      <p class="admonition-title">Be careful!</p>

      <p>Title for denger</p>
      <p>some code and text</p>
      <div class="sourceCode" id="cb2">
        <pre
          class="sourceCode python"><code class="sourceCode python"><span id="cb2-1"><a href="#cb2-1" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">&quot;!!!&quot;</span>)</span></code></pre>
      </div>
      <p>It is not a good code.</p>
    </div>

  </div>

  <!-- Without title -->

  <div class="admonition note">
    <p class="admonition-title no-title">Pay attention!</p>

    <p>Title for notes</p>
    <p>some code and text</p>
    <div class="sourceCode" id="cb3">
      <pre class="sourceCode C"><code class="sourceCode c"><span id="cb3-1"><a href="#cb3-1" aria-hidden="true" tabindex="-1"></a><span class="dt">int</span> main<span class="op">(){</span></span>
<span id="cb3-2"><a href="#cb3-2" aria-hidden="true" tabindex="-1"></a>    puts<span class="op">(</span><span class="st">&quot;Hello World!&quot;</span><span class="op">);</span></span>
<span id="cb3-3"><a href="#cb3-3" aria-hidden="true" tabindex="-1"></a><span class="op">}</span></span></code></pre>
    </div>
    <p>It is a good code.</p>
    <div class="admonition danger">
      <p class="admonition-title">Be careful!</p>

      <p>Title for denger</p>
      <p>some code and text</p>
      <div class="sourceCode" id="cb4">
        <pre
          class="sourceCode python"><code class="sourceCode python"><span id="cb4-1"><a href="#cb4-1" aria-hidden="true" tabindex="-1"></a><span class="bu">print</span>(<span class="st">&quot;!!!&quot;</span>)</span></code></pre>
      </div>
      <p>It is not a good code.</p>
    </div>

  </div>

这是一个类似Python-Markdown的Admonition扩展语法的lua过滤器。

您可以使用许多标签(CSS类名称)和引用的标题""

这个过滤器的不同之处在于你不能使用缩进,因为 pandoc 不认为!!!应该有缩进,所以如果使用缩进,pandoc 会渲染得很糟糕。

!!! danger notes "title"
You should note that the title will be automatically capitalized.
```haskell
--code will be rendered
main::IO ()
main = main
```

*Emph string* and **strong string**

!!! important ""
admonition with no title

lua过滤器

function Para(para)
  if para.content[1] and para.content[1].text == '!!!' and 
    para.content[2] and para.content[2].tag == 'Space' and 
    para.content[3] and para.content[3].tag == 'Str' then
    local text = para.content[3].text -- default title is tag
    tags = text
    title = string.upper(text)
    i = 4
    -- parse tags
    while para.content[i] and para.content[i].tag ~= 'SoftBreak'
    do
      -- tags can only be string or spaces
      if para.content[i].tag == 'Str' then
        tags = tags .. para.content[i].text
      elseif para.content[i].tag == 'Space' then
        tags = tags .. ' '
      -- Quoted is title
      elseif para.content[i].tag == 'Quoted' then
        title = pandoc.utils.stringify(para.content[i].content)
      end
      i = i + 1
    end
    if para.content[i] and para.content[i].tag == 'SoftBreak' then
      body = pandoc.List({table.unpack(para.content, i+1)})
    else
      body = '' -- no body
    end
    return pandoc.Blocks( -- merge into blocks
      {
        pandoc.RawInline(
          'html','<div class="admonition ' .. tags .. '">' ..
          '<p class="admonition-title">' .. title .. '</p>'
        ),
        pandoc.Plain(body),
        pandoc.RawInline('html', '</div>')
      }
    )
  end
end

预览输出(第一段)

$ pandoc test.md --lua-filter f.lua
<div class="admonition danger notes "><p class="admonition-title">title</p>
You should note that the title will be automatically capitalized.
</div>

您可以添加样式表,例如H.html

<style>
div.note {
    background-color: #24502426;
}
div.danger {
    background-color: #8c24047a;
}
p.admonition-title {
    font-family: cursive;
}
</style>

then run

$ pandoc test.md --lua-filter f.lua -s -o main.html -H H.html

Update 2

更新空标题

@Gustavo Reis pandoc 在过滤器处理文本之前读取了错误的缩进,所以我的过滤器不能嵌套。如果你想改变这个,你可以尝试定义列表可以嵌套

function Para(para)
  if para.content[1] and para.content[1].text == '!!!' and 
    para.content[2] and para.content[2].tag == 'Space' and 
    para.content[3] and para.content[3].tag == 'Str' then
    local text = para.content[3].text -- default title is tag
    tags = text
    title = string.upper(text)
    i = 4
    -- parse tags
    while para.content[i] and para.content[i].tag ~= 'SoftBreak'
    do
      -- tags can only be string or spaces
      if para.content[i].tag == 'Str' then
        if para.content[i].text == '“”' then
          title = nil
        else
          tags = tags .. para.content[i].text
        end
      elseif para.content[i].tag == 'Space' then
        tags = tags .. ' '
      -- Quoted is title
      elseif para.content[i].tag == 'Quoted' then
        title = pandoc.utils.stringify(para.content[i].content)
      end
      i = i + 1
    end
    if para.content[i] and para.content[i].tag == 'SoftBreak' then
      body = pandoc.List({table.unpack(para.content, i+1)})
    else
      body = '' -- no body
    end
    if title==nil then
      title_html = '<p class="admonition-title no-title"/>'
    else
      title_html = '<p class="admonition-title">' .. title .. '</p>'
    end
    return pandoc.Blocks( -- merge into blocks
      {
        pandoc.RawInline(
          'html','<div class="admonition ' .. tags .. '">' .. title_html
        ),
        pandoc.Plain(body),
        pandoc.RawInline('html', '</div>')
      }
    )
  end
end

定义列表示例

definition list example

notes

:   title for notes

    some code and text
    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    denger
    :   title for denger
    
        some code and text
        ```python
        print('!!!!')
        ```

Update 3

在此更新中,我在 markdown 中使用定义列表(带有!!!语法)并将 lua 过滤器替换为 javascript 代码。

window.onload = function(){
    document.querySelectorAll('dl').forEach(n => n.classList.add('admonition'))
    let dts = document.querySelectorAll('dt');
    for(let dt of dts){
        let text = dt.innerText;
        let default_title = false;
        if (text.slice(0, 4)=='!!! '){
            let i = text.lastIndexOf('“');
            dt.classList.add('admonition-title');
            if (i == -1) {
                i = text.length;
                default_title = true;
            }
            let tags = text.slice(4, i).split(' ').filter((x)=>x.length);
            for (var j = tags.length - 1; j >= 0; j--) {
                dt.parentNode.classList.add(tags[j]);
            }
            if (default_title) {
                dt.innerText = tags[0] || "";
            }else{
                let end = text.lastIndexOf('”');
                if (end == -1) {
                    end = text.length;
                }
                dt.innerText = text.slice(i+1, end);
                if (dt.innerText == '') {
                    dt.classList.add('no-title');
                }
            }
        }         
    }
}

降价代码

<!-- With title -->
!!! note "Pay attention!"
:   Title for notes

    some code and text
    
    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    :   Title for denger
    
        some code and text
    
        ```python
        print
        ```
    
        It is not a good

<!-- Without title -->
!!! note ""
:   Title for notes

    some code and text

    ```C
    int main(){
        puts("Hello World!");
    }
    ```

    It is a good code.

    !!! danger "Be careful!"
    :   Title for denger
        
        some code and text
    
        ```python
        print
        ```
    
       It is not a good

这个 CSS 代码没有改变

下面是截图

看来使用的效果dt, dl, dd类似于使用div

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

使用 Lua for Pandoc 将 Markdown 警告语法转换为 HTML 的相关文章

  • HTML 解析 - 从 div 内的表格获取数据?

    我对 HTML 解析 抓取的整个想法还比较陌生 我希望我能来这里获得我需要的帮助 基本上我想要做的 我认为 是指定我希望从中获取数据的页面的 url 在这种情况下 http www epgpweb com guild us Caelestr
  • .addClass 仅添加到无序列表中单击的项目符号

    我有一个简短的无序列表 其中有两个项目符号 我添加了一些 Javascript 这样当我单击项目符号时 它会向其中添加一个类 问题是 它将该类添加到所有现有的 li 中 而不仅仅是我单击的那个 这是 JSFiddle http jsfidd
  • 如何在 django 表单中设置自定义 HTML 属性?

    我有一个 Django 表单 它是页面的一部分 假设我有一个字段 search input forms CharField u Search word required False 我只能通过模板访问它 form search input
  • Div 上的倾斜边框

    我正在尝试倾斜一个 div 类似于 使用 css 倾斜 div 的顶部而不倾斜文本 https stackoverflow com questions 13591584 slant the top of a div using css wi
  • 将 SVG 元素放置在图像上

    是否可以拥有以下元素并设置它们的样式 以便 SVG 对象出现在图像上 即像图像的一部分 目前它们显示在其下方的新行中 我知道我可以将图像设置为父 div 的背景图像 但不幸的是我还需要能够在父级内旋转它 所以我认为这不是一个选项 div s
  • 如何使用FileSystem API的window.requestFileSystem?

    我用 JavaScript 编写了以下代码 JavaScript 代码 var fs null function initFS window requestFileSystem window requestFileSystem window
  • HTML 和 CSS 的基本编码标准 [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我想知道它们是否是像 PSR 01 这样的 HTML 和 CSS 基本编码标准 我尝试谷歌搜索和搜索 但没有找到 我建议看看类似的东西
  • 从 Google Chrome 打印时的页码

    我看过这个答案 page bottom left content counter page counter pages 很多次 但它从来没有为我输出任何内容到页面 即使它应该工作 我尝试过 创造性 的方法来在底部获取页码 但我永远无法让它可
  • HTML5
    标签的正确使用

    我正在为一家公司编写一个新网页 并且我心中有 HTML5 W3C 建议 的合理子集 读完语义后 hr 我想知道这是否是一个使用它的好地方 section h2 2002 h2 p Dolorem ipsum dolor sit amet i
  • 更改特定元素的滚动速度[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 好吧 我不知道如何编写脚本 但是在
  • 当鼠标悬停在上面时制作一个 React Bootstrap NavDropdown 下拉菜单

    我试图让 React Bootstrap 中的下拉菜单栏在您显示选项时hover超过它 我到处查看 所有解决方案似乎都已过时并且不起作用 如果您能够解决此问题 请告诉我 这是我尝试将更改应用到的下拉菜单
  • 在 Chrome 上使用 display:none 重置 GIF 动画的正确方法

    标题是不言自明的 但我将提供对此事的逐步看法 希望我不是第一个注意到 Webkit Chrome 上这个 显然 错误的人 我想重置 GIF 动画 到目前为止我看到的所有例子要么简单地设置src图像本身或将其设置为空字符串 后跟原始图像src
  • 如何使用滚动条图像?

    如何使用 HTML CSS 替换滚动条的图像 I have scrollbar base color 00acee scrollbar dark shadow color 00acee scrollbar track color fffff
  • 将移动设备重定向到我网站的备用版本

    我们已经为移动设备准备了网站的替代版本 我们提供的内容不同 而且效果很好 检测要提供哪个版本的最佳方法是什么 我们没有所有移动设备的列表 因此使用用户代理标头很棘手 因为我们可能会错过一些东西 我们考虑过使用设备屏幕宽度 但如果移动设备不支
  • 使用 HTML5 FileSystem API 将文件写入桌面

    我正在玩一下文件系统API http www html5rocks com en tutorials file filesystem 我发现了很多生成下载链接并让用户以 浏览器方式 下载文件的示例 我想知道两件事 有没有办法将fiddle中
  • 从 HTML 表单发送数据到 Node.js 服务器

    我正在学习 Node js 我的服务器中有这个 var http require http var url require url http createServer function request response response w
  • 清理 CSS 抖动

    我已经构建了这些圆圈 当鼠标悬停时它们会扩展边框 我现在遇到的唯一问题是有时圆圈会抖动 摇晃 当我设置transition all 1s ease in out 超过 0 2 秒 有解决这个问题的方法吗 还是事情就是这样 这是其中的代码Js
  • Bootstrap 3 - 使用垂直滚动条水平拖动元素,overflow-y:滚动

    在我的失败之后上一篇文章 https stackoverflow com questions 23586926 bootstrap grid with scrollable affixed column noredirect 1 comme
  • 表单提交不起作用

    我有一张桌子 可以打印出所有可用的相机 它使用表单来更改这些设置 问题在于该表单仅更新条目中的最后一个摄像机 换句话说 如果我更改表单并为列表中的最后一个摄像机点击 应用 它将起作用 如果我更改此列表中任何其他摄像机的表单 它会将其更改为与
  • 在 HTML5 画布上创建颜色选择器

    如何在 HTML5 画布上绘制颜色选择器 一个基本的例子是使用getImageData http jsfiddle net eGjak 60 http jsfiddle net eGjak 60 var ctx cv get 0 getCo

随机推荐