File: include.rb

package info (click to toggle)
ruby-slim 5.2.1-1
  • links: PTS, VCS
  • area: main
  • in suites: forky, sid, trixie
  • size: 828 kB
  • sloc: ruby: 5,583; makefile: 12
file content (58 lines) | stat: -rw-r--r-- 1,823 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# frozen_string_literal: true
require 'slim'

module Slim
  # Handles inlined includes
  #
  # Slim files are compiled, non-Slim files are included as text with `#{interpolation}`
  #
  # @api private
  class Include < Slim::Filter
    define_options :file, include_dirs: [Dir.pwd, '.']

    def on_html_tag(tag, attributes, content = nil)
      return super if tag != 'include'
      name = content.to_a.flatten.select {|s| String === s }.join
      raise ArgumentError, 'Invalid include statement' unless attributes == [:html, :attrs] && !name.empty?
      unless file = find_file(name)
        name = "#{name}.slim" if name !~ /\.slim\Z/i
        file = find_file(name)
      end
      raise Temple::FilterError, "'#{name}' not found in #{options[:include_dirs].join(':')}" unless file
      content = File.read(file)
      if file =~ /\.slim\Z/i
        Thread.current[:slim_include_engine].call(content)
      else
        [:slim, :interpolate, content]
      end
    end

    protected

    def find_file(name)
      current_dir = File.dirname(File.expand_path(options[:file]))
      options[:include_dirs].map {|dir| File.expand_path(File.join(dir, name), current_dir) }.find {|file| File.file?(file) }
    end
  end

  class Engine
    after Slim::Parser, Slim::Include
    after Slim::Include, :stop do |exp|
      throw :stop, exp if Thread.current[:slim_include_level] > 1
      exp
    end

    # @api private
    alias call_without_include call

    # @api private
    def call(input)
      Thread.current[:slim_include_engine] = self
      Thread.current[:slim_include_level] ||= 0
      Thread.current[:slim_include_level] += 1
      catch(:stop) { call_without_include(input) }
    ensure
      Thread.current[:slim_include_engine] = nil if (Thread.current[:slim_include_level] -= 1) == 0
    end
  end
end