Repository: tlienart/Franklin.jl
Pull request #724 (2020-12-06 18:37:13)

A few bug fixes
#720 was due to a mistake in `convert_md_math`  which didn't properly disable inner  blocks (thanks @sethaxen for reporting). Now:

```
julia> s = raw"""
           \newcommand{\ip}[2]{\langle #1, #2 \rangle}
           $$\ip{\dot{a}}{\dot{b}}$$
           """ |> fd2html
"\\[\\langle  \\dot{a},  \\dot{b} \\rangle\\]\n"
```

#719 adds GitHub ci

#723 cleans up empty  folders on `optimize` 

#722 led to fixing a couple of fairly sneaky bugs with `delayed`,  `ALL_PAGE_VARS` and `FD_ENV[:source]`; thanks to @pfitzseb for reporting those 


Patch:
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
new file mode 100644
index 00000000..ecf6175b
--- /dev/null
+++ b/.github/workflows/ci.yml
@@ -0,0 +1,47 @@
+name: CI
+on:
+  pull_request:
+    branches:
+      - master
+      - dev
+  push:
+    branches:
+      - master
+      - dev
+    tags: '*'
+jobs:
+  test:
+    name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
+    runs-on: ${{ matrix.os }}
+    strategy:
+      fail-fast: false
+      matrix:
+        version:
+          - '1.3'
+          - '1'
+        os:
+          - ubuntu-latest
+        arch:
+          - x64
+    steps:
+      - uses: actions/checkout@v2
+      - uses: julia-actions/setup-julia@v1
+        with:
+          version: ${{ matrix.version }}
+          arch: ${{ matrix.arch }}
+      - uses: actions/cache@v1
+        env:
+          cache-name: cache-artifacts
+        with:
+          path: ~/.julia/artifacts
+          key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
+          restore-keys: |
+            ${{ runner.os }}-test-${{ env.cache-name }}-
+            ${{ runner.os }}-test-
+            ${{ runner.os }}-
+      - uses: julia-actions/julia-buildpkg@v1
+      - uses: julia-actions/julia-runtest@v1
+      - uses: julia-actions/julia-processcoverage@v1
+      - uses: codecov/codecov-action@v1
+        with:
+          file: lcov.info
diff --git a/.travis.yml b/.travis.yml
deleted file mode 100644
index 36e0976b..00000000
--- a/.travis.yml
+++ /dev/null
@@ -1,16 +0,0 @@
-# Documentation: http://docs.travis-ci.com/user/languages/julia/
-language: julia
-os:
-  - linux
-julia:
-  - 1.3
-  - 1.5
-  - nightly
-matrix:
-  allow_failures:
-    - julia: nightly
-notifications:
-  email: false
-after_success:
-  # push coverage results to Codecov
-  - julia -e 'using Pkg; pkg"add Coverage"; using Coverage; Codecov.submit(Codecov.process_folder())'
diff --git a/README.md b/README.md
index 92d1f59f..27dc2607 100644
--- a/README.md
+++ b/README.md
@@ -8,13 +8,9 @@
 <p align="center">
   <img src="https://img.shields.io/badge/lifecycle-maturing-blue.svg"
        alt="Lifecycle">
-  <a href="https://travis-ci.com/tlienart/Franklin.jl">
-    <img src="https://travis-ci.com/tlienart/Franklin.jl.svg?branch=master"
-         alt="Build Status (Linux)">
-  </a>
-  <a href="https://ci.appveyor.com/project/tlienart/Franklin-jl">
-    <img src="https://ci.appveyor.com/api/projects/status/github/tlienart/Franklin.jl?branch=master&svg=true"
-         alt="Build Status (Windows)">
+  <a href="https://github.com/tlienart/Franklin.jl/actions">
+    <img src="https://github.com/tlienart/Franklin.jl/workflows/CI/badge.svg"
+         alt="Build Status">
   </a>
   <a href="http://codecov.io/github/tlienart/Franklin.jl?branch=master">
     <img src="http://codecov.io/github/tlienart/Franklin.jl/coverage.svg?branch=master"
diff --git a/appveyor.yml b/appveyor.yml
deleted file mode 100644
index 19fd1c2d..00000000
--- a/appveyor.yml
+++ /dev/null
@@ -1,28 +0,0 @@
-environment:
-  matrix:
-  - julia_version: 1.3
-  - julia_version: 1.5
-  - julia_version: nightly
-
-platform:
-  - x64 # 64-bit
-
-branches:
-  only:
-    - master
-
-notifications:
-  - provider: Email
-    on_build_success: false
-    on_build_failure: false
-    on_build_status_changed: false
-
-install:
-  - ps: iex ((new-object net.webclient).DownloadString("https://raw.githubusercontent.com/JuliaCI/Appveyor.jl/version-1/bin/install.ps1"))
-
-build_script:
-  - C:\julia\bin\julia -e "%JL_BUILD_SCRIPT%"
-
-test_script:
-- echo "%JL_TEST_SCRIPT%"
-  - C:\julia\bin\julia -e "%JL_TEST_SCRIPT%"
diff --git a/src/converter/html/html.jl b/src/converter/html/html.jl
index 9a0fa2ca..ada55034 100644
--- a/src/converter/html/html.jl
+++ b/src/converter/html/html.jl
@@ -47,9 +47,9 @@ page variables. See also [`fd2html`](@ref) which only returns the html.
 """
 function fd2html_v(st::AS; internal::Bool=false,
                    dir::String="", nop::Bool=false)::Tuple{String,Dict}
-    FD_ENV[:SOURCE] = "input string"
     isempty(st) && return (st, LittleDict())
     if !internal
+        FD_ENV[:SOURCE] = "input string"
         empty!(ALL_PAGE_VARS)
         FOLDER_PATH[] = isempty(dir) ? mktempdir() : dir
         set_paths!()
diff --git a/src/converter/markdown/md.jl b/src/converter/markdown/md.jl
index e194852d..a2b6b0c4 100644
--- a/src/converter/markdown/md.jl
+++ b/src/converter/markdown/md.jl
@@ -169,11 +169,14 @@ function convert_md(mds::AbstractString,
     (:convert_md, "hstring: '$hstring'") |> logger
 
     # final var adjustment, infer title if not given
+    rpath = splitext(locvar(:fd_rpath))[1]
     if isnothing(locvar(:title)) && !isempty(PAGE_HEADERS)
         title = first(values(PAGE_HEADERS))[1]
         set_var!(LOCAL_VARS, "title", title)
-        ALL_PAGE_VARS[splitext(locvar(:fd_rpath))[1]]["title"] =
-            deepcopy(LOCAL_VARS["title"])
+    end
+    # Copy vars to allpagevars to make them more easily accessible to other pages
+    if !(isrecursive || isinternal)
+        ALL_PAGE_VARS[rpath] = deepcopy(LOCAL_VARS)
     end
 
     # Return the string
@@ -199,6 +202,9 @@ function convert_md_math(ms::AS, lxdefs::Vector{LxDef}=Vector{LxDef}(),
                          offset::Int=0)::String
     # if a substring is given, copy it as string
     ms = String(ms)
+
+    (:convert_md_math, "ms: '$ms'") |> logger
+
     #
     # Parsing of the markdown string
     # (to find latex command, latex definitions, math envs etc.)
@@ -207,14 +213,21 @@ function convert_md_math(ms::AS, lxdefs::Vector{LxDef}=Vector{LxDef}(),
     #> 1. Tokenize (with restricted set)
     tokens = find_tokens(ms, MD_TOKENS_LX, MD_1C_TOKENS_LX)
 
+    (:convert_md_math, "tokens: '$tokens'") |> logger
+
     #> 2. Find braces and drop line returns thereafter
     blocks, tokens = find_all_ocblocks(tokens, MD_OCB_ALL, inmath=true)
+    deactivate_inner_blocks!(blocks)
     braces = filter(β -> β.name == :LXB, blocks)
 
+    (:convert_md_math, "braces: '$braces'") |> logger
+
     #> 3. Find latex envs and commands (indicate we're in a math environment + offset)
     lxenvs, tokens = find_lxenvs(tokens, lxdefs, braces, offset; inmath=true)
     lxcoms, _      = find_lxcoms(tokens, lxdefs,  braces, offset; inmath=true)
 
+    (:convert_md_math, "lxcoms: '$lxcoms'") |> logger
+
     #
     # Forming of the html string
     # (see `form_inter_md`, it's similar but simplified since there are fewer
diff --git a/src/converter/markdown/mddefs.jl b/src/converter/markdown/mddefs.jl
index bea647a6..bb681e61 100644
--- a/src/converter/markdown/mddefs.jl
+++ b/src/converter/markdown/mddefs.jl
@@ -93,11 +93,7 @@ function process_mddefs(blocks::Vector{OCBlock}, isconfig::Bool,
         set_var!(LOCAL_VARS, "hasmath", math)
     end
 
-    # copy the page vars to ALL_PAGE_VARS so that they can be accessed
-    # by other pages via `pagevar`.
-    ALL_PAGE_VARS[rpath] = deepcopy(LOCAL_VARS)
-
-    (:process_mddefs, "assignments done & copy to ALL_PAGE_VARS") |> logger
+    (:process_mddefs, "assignments done") |> logger
 
     # TAGS
     tags = Set(refstring.(locvar(:tags)))
diff --git a/src/manager/dir_utils.jl b/src/manager/dir_utils.jl
index 05d91d74..82ffbdb7 100644
--- a/src/manager/dir_utils.jl
+++ b/src/manager/dir_utils.jl
@@ -34,7 +34,7 @@ function form_output_path(base::AS, file::AS, case::Symbol)
         # file is index.html or 404.html --> keep the path
         # file is page.html  --> .../page/index.html
         fname = splitext(file)[1]
-        if fname ∉ ("index", "404")
+        if fname ∉ ("index", "404") && !endswith(fname, "/index")
             file = joinpath(fname, "index.html")
         end
     end
@@ -59,8 +59,6 @@ function _out_path(base::String)::String
        # path is not a 'special folder'
        outpath = replace(base, path(:folder) => path(:site))
    end
-    # if it doesn't exist, make the path
-    !ispath(outpath) && mkpath(outpath)
     return outpath
 end
 
diff --git a/src/manager/franklin.jl b/src/manager/franklin.jl
index 89166329..5fa7b212 100644
--- a/src/manager/franklin.jl
+++ b/src/manager/franklin.jl
@@ -246,12 +246,13 @@ function fd_fullpass(watched_files::NamedTuple)::Int
         end
         s += a
     end
+
     # re-evaluate delayed pages
     if !isempty(DELAYED)
         cp_DELAYED = copy(DELAYED)
         empty!(DELAYED) # so that functions are effectively applied
         for page in cp_DELAYED
-            case = Symbol(strip(splitext(page)[2], '.'))
+            case = Symbol(strip(splitext(page)[2], '.'))  # md / html
             fpair = path(:folder) => page
             a = process_file(case, fpair, head, pg_foot, foot)
             if a < 0 && FD_ENV[:PRERENDER] && FD_ENV[:NO_FAIL_PRERENDER]
diff --git a/src/manager/post_processing.jl b/src/manager/post_processing.jl
index 79989959..7d7d4ce4 100644
--- a/src/manager/post_processing.jl
+++ b/src/manager/post_processing.jl
@@ -81,6 +81,16 @@ function optimize(; prerender::Bool=true, minify::Bool=true, sig::Bool=false,
                   "pip. The output will not be minified."
         end
     end
+
+    #
+    # Clean up empty folders if any
+    #
+    for name in readdir(path(:site))
+        p = joinpath(path(:site), name)
+        isdir(p) || continue
+        isempty(readdir(p)) && rm(p)
+    end
+
     FD_ENV[:SUPPRESS_ERR] = false
     return ifelse(sig, succ, nothing)
 end
diff --git a/src/manager/rss_generator.jl b/src/manager/rss_generator.jl
index b29b946c..46b588e9 100644
--- a/src/manager/rss_generator.jl
+++ b/src/manager/rss_generator.jl
@@ -64,7 +64,7 @@ function add_rss_item()
     link  = url_curpage()
     title = jor("rss_title", "title")
     descr = jor("rss", "rss_description")
-
+    
     descr = fd2html(descr; internal=true) |> remove_html_ps
 
     author    = locvar(:rss_author)
diff --git a/src/parser/latex/blocks.jl b/src/parser/latex/blocks.jl
index 99c423b3..55774641 100644
--- a/src/parser/latex/blocks.jl
+++ b/src/parser/latex/blocks.jl
@@ -238,6 +238,10 @@ function find_lxcoms(tokens::Vector{Token}, lxdefs::Vector{LxDef},
         # 1. look for the definition given the command name
         lxname = τ.ss
         lxdefref, utils = get_lxdef_ref(lxname, lxdefs, inmath, offset)
+
+        (:find_lxcoms, "lxname: '$lxname'") |> logger
+        (:find_lxcoms, "utils: '$utils'") |> logger
+
         if utils
             # custom command defined in utils, take a single bracket
             lxnarg = 1
@@ -248,6 +252,9 @@ function find_lxcoms(tokens::Vector{Token}, lxdefs::Vector{LxDef},
             lxnarg = getindex(lxdefref).narg
         end
 
+        (:find_lxcoms, "lxnarg: '$lxnarg'") |> logger
+        (:find_lxcoms, "braces: '$(content.(braces))'") |> logger
+
         # 2. explore with # arguments
         # >> no arguments
         if lxnarg == 0
diff --git a/src/utils/vars.jl b/src/utils/vars.jl
index a23c326a..afbfecd6 100644
--- a/src/utils/vars.jl
+++ b/src/utils/vars.jl
@@ -193,7 +193,7 @@ Dict to keep track of all pages and their vars. Each key is a relative path
 to a page, values are PageVars.
 The keys don't have the file extension so `"blog/pg1" => PageVars`.
 """
-const ALL_PAGE_VARS = Dict{String,PageVars}()
+const ALL_PAGE_VARS = LittleDict{String,PageVars}()
 
 """
     pagevar(rpath, name)


Test patch:
diff --git a/test/latex/newcommand.jl b/test/latex/newcommand.jl
index 32dc504f..a3786da5 100644
--- a/test/latex/newcommand.jl
+++ b/test/latex/newcommand.jl
@@ -214,3 +214,11 @@ end
         \[\begin{array}{rcl} \sin^2(x)+\cos^2(x) &=& 1\end{array}\]
         """)
 end
+
+@testset "issue #720" begin
+    s = raw"""
+        \newcommand{\ip}[2]{\langle #1, #2 \rangle}
+        $$\ip{\dot{a}}{\dot{b}}$$
+        """ |> fd2html
+    @test isapproxstr(s, raw"\[\langle \dot{a}, \dot{b} \rangle\]")
+end
diff --git a/test/utils/warnings.jl b/test/utils/warnings.jl
index 561cce02..3c3796b5 100644
--- a/test/utils/warnings.jl
+++ b/test/utils/warnings.jl
@@ -26,7 +26,7 @@ end
     set_curpath("hey/ho.md")
     F.set_var!(F.LOCAL_VARS, "rss_title", "")
     s = @capture_out F.add_rss_item()
-    @test occursin("Warning: in <input string>", s)
+    @test occursin("Warning: in <unknown>", s)
     @test occursin("An RSS description was found but without title", s)
     @test occursin("for page '/hey/ho/index.html'.", s)
 end