scribo 1.0.38
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.md +93 -0
- data/Rakefile +40 -0
- data/app/assets/config/scribo_manifest.js +2 -0
- data/app/assets/javascripts/scribo/scribo.js +1 -0
- data/app/assets/stylesheets/scribo/scribo.css +1 -0
- data/app/controllers/concerns/maintenance_standards.rb +24 -0
- data/app/controllers/scribo/admin/sites/contents_controller.rb +86 -0
- data/app/controllers/scribo/admin/sites_controller.rb +61 -0
- data/app/controllers/scribo/api/sites_controller.rb +23 -0
- data/app/controllers/scribo/application_admin_controller.rb +11 -0
- data/app/controllers/scribo/application_controller.rb +6 -0
- data/app/controllers/scribo/contents_controller.rb +20 -0
- data/app/drops/scribo/action_dispatch/request_drop.rb +15 -0
- data/app/drops/scribo/active_model/errors_drop.rb +16 -0
- data/app/drops/scribo/application_drop.rb +9 -0
- data/app/drops/scribo/array_drop.rb +13 -0
- data/app/drops/scribo/content_drop.rb +73 -0
- data/app/drops/scribo/data_drop.rb +35 -0
- data/app/drops/scribo/form_drop.rb +26 -0
- data/app/drops/scribo/include_drop.rb +13 -0
- data/app/drops/scribo/paginator_drop.rb +73 -0
- data/app/drops/scribo/site_drop.rb +83 -0
- data/app/helpers/scribo/application_helper.rb +13 -0
- data/app/jobs/scribo/application_job.rb +6 -0
- data/app/models/scribo/application_record.rb +11 -0
- data/app/models/scribo/content.rb +378 -0
- data/app/models/scribo/site.rb +161 -0
- data/app/services/scribo/application_service.rb +9 -0
- data/app/services/scribo/content_find_service.rb +69 -0
- data/app/services/scribo/content_render_service.rb +127 -0
- data/app/services/scribo/site_export_service.rb +41 -0
- data/app/services/scribo/site_find_service.rb +26 -0
- data/app/services/scribo/site_import_service.rb +96 -0
- data/app/views/layouts/scribo.html.slim +1 -0
- data/app/views/scribo/admin/sites/_create_sites.html.slim +22 -0
- data/app/views/scribo/admin/sites/_sites.html.slim +18 -0
- data/app/views/scribo/admin/sites/contents/_form.html.slim +17 -0
- data/app/views/scribo/admin/sites/contents/create.json.jbuilder +11 -0
- data/app/views/scribo/admin/sites/contents/edit.html.slim +2 -0
- data/app/views/scribo/admin/sites/contents/edit.json.jbuilder +9 -0
- data/app/views/scribo/admin/sites/contents/index.html.slim +1 -0
- data/app/views/scribo/admin/sites/contents/move.json.jbuilder +9 -0
- data/app/views/scribo/admin/sites/contents/rename.json.jbuilder +9 -0
- data/app/views/scribo/admin/sites/contents/upload.json.jbuilder +9 -0
- data/app/views/scribo/admin/sites/import.json.jbuilder +4 -0
- data/app/views/scribo/admin/sites/index.html.slim +7 -0
- data/app/views/scribo/shared/_entry.html.slim +17 -0
- data/app/views/scribo/shared/_ide.html.slim +14 -0
- data/app/views/scribo/shared/_tree-view.html.slim +32 -0
- data/config/locales/en.yml +39 -0
- data/config/routes.rb +35 -0
- data/db/migrate/20200123095630_initial_scribo.rb +34 -0
- data/db/migrate/20220919124119_add_ancestry_to_scribo_contents.rb +13 -0
- data/db/migrate/20220919124749_remove_parent_id_from_scribo_contents.rb +8 -0
- data/lib/scribo/action_controller_helpers.rb +51 -0
- data/lib/scribo/action_controller_renderers.rb +71 -0
- data/lib/scribo/action_view_helpers.rb +17 -0
- data/lib/scribo/active_record_helpers.rb +11 -0
- data/lib/scribo/configuration.rb +97 -0
- data/lib/scribo/engine.rb +24 -0
- data/lib/scribo/i18n_store.rb +100 -0
- data/lib/scribo/liquid/filters/jekyll_filters.rb +94 -0
- data/lib/scribo/liquid/filters/markdownify.rb +11 -0
- data/lib/scribo/liquid/filters/url_filters.rb +76 -0
- data/lib/scribo/liquid/parser.rb +32 -0
- data/lib/scribo/liquid/tags/application_assets_tag.rb +14 -0
- data/lib/scribo/liquid/tags/application_js_tag.rb +16 -0
- data/lib/scribo/liquid/tags/asset_tag.rb +56 -0
- data/lib/scribo/liquid/tags/button_tag.rb +24 -0
- data/lib/scribo/liquid/tags/check_box_tag.rb +31 -0
- data/lib/scribo/liquid/tags/csrf_meta_tags_tag.rb +16 -0
- data/lib/scribo/liquid/tags/date_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/editable_url_tag.rb +19 -0
- data/lib/scribo/liquid/tags/email_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/feed_meta_tag.rb +22 -0
- data/lib/scribo/liquid/tags/field_error_tag.rb +26 -0
- data/lib/scribo/liquid/tags/fields_for_tag.rb +82 -0
- data/lib/scribo/liquid/tags/form_tag.rb +57 -0
- data/lib/scribo/liquid/tags/google_analytics_javascript_tag.rb +30 -0
- data/lib/scribo/liquid/tags/google_tag_manager_javascript_tag.rb +28 -0
- data/lib/scribo/liquid/tags/hidden_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/highlight_tag.rb +106 -0
- data/lib/scribo/liquid/tags/include_tag.rb +28 -0
- data/lib/scribo/liquid/tags/label_tag.rb +24 -0
- data/lib/scribo/liquid/tags/number_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/options_for_select.rb +36 -0
- data/lib/scribo/liquid/tags/password_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/search_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/search_tag.rb +29 -0
- data/lib/scribo/liquid/tags/select_tag.rb +22 -0
- data/lib/scribo/liquid/tags/seo_tag.rb +35 -0
- data/lib/scribo/liquid/tags/set_session.rb +19 -0
- data/lib/scribo/liquid/tags/telephone_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/text_field_tag.rb +35 -0
- data/lib/scribo/liquid/tags/textarea_tag.rb +28 -0
- data/lib/scribo/liquid/tags/time_field_tag.rb +23 -0
- data/lib/scribo/liquid/tags/url_field_tag.rb +23 -0
- data/lib/scribo/preamble.rb +89 -0
- data/lib/scribo/sassc/importer.rb +72 -0
- data/lib/scribo/utility.rb +94 -0
- data/lib/scribo/version.rb +5 -0
- data/lib/scribo.rb +59 -0
- data/lib/tasks/scribo_tasks.rake +28 -0
- metadata +498 -0
@@ -0,0 +1,106 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class HighlightBlock < Liquid::Block
|
4
|
+
include Liquid::StandardFilters
|
5
|
+
|
6
|
+
# The regular expression syntax checker. Start with the language specifier.
|
7
|
+
# Follow that by zero or more space separated options that take one of three
|
8
|
+
# forms: name, name=value, or name="<quoted list>"
|
9
|
+
#
|
10
|
+
# <quoted list> is a space-separated list of numbers
|
11
|
+
SYNTAX = /^([a-zA-Z0-9.+#_-]+)((\s+\w+(=(\w+|"([0-9]+\s)*[0-9]+"))?)*)$/.freeze
|
12
|
+
|
13
|
+
def initialize(tag_name, markup, tokens)
|
14
|
+
super
|
15
|
+
if markup.strip =~ SYNTAX
|
16
|
+
@lang = Regexp.last_match(1).downcase
|
17
|
+
@highlight_options = parse_options(Regexp.last_match(2))
|
18
|
+
else
|
19
|
+
raise SyntaxError, <<~MSG
|
20
|
+
Syntax Error in tag 'highlight' while parsing the following markup:
|
21
|
+
|
22
|
+
#{markup}
|
23
|
+
|
24
|
+
Valid syntax: highlight <lang> [linenos]
|
25
|
+
MSG
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
LEADING_OR_TRAILING_LINE_TERMINATORS = /\A(\n|\r)+|(\n|\r)+\z/.freeze
|
30
|
+
|
31
|
+
def render(context)
|
32
|
+
prefix = context['highlighter_prefix'] || ''
|
33
|
+
suffix = context['highlighter_suffix'] || ''
|
34
|
+
code = super.to_s.gsub(LEADING_OR_TRAILING_LINE_TERMINATORS, '')
|
35
|
+
|
36
|
+
output =
|
37
|
+
case context.registers[:site]&.highlighter
|
38
|
+
when 'rouge'
|
39
|
+
render_rouge(code)
|
40
|
+
when 'pygments'
|
41
|
+
render_pygments(code, context)
|
42
|
+
else
|
43
|
+
render_codehighlighter(code)
|
44
|
+
end
|
45
|
+
|
46
|
+
rendered_output = add_code_tag(output)
|
47
|
+
prefix + rendered_output + suffix
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
OPTIONS_REGEX = /(?:\w="[^"]*"|\w=\w|\w)+/.freeze
|
53
|
+
|
54
|
+
def parse_options(input)
|
55
|
+
options = {}
|
56
|
+
return options if input.empty?
|
57
|
+
|
58
|
+
# Split along 3 possible forms -- key="<quoted list>", key=value, or key
|
59
|
+
input.scan(OPTIONS_REGEX) do |opt|
|
60
|
+
key, value = opt.split('=')
|
61
|
+
# If a quoted list, convert to array
|
62
|
+
if value&.include?('"')
|
63
|
+
value.delete!('"')
|
64
|
+
value = value.split
|
65
|
+
end
|
66
|
+
options[key.to_sym] = value || true
|
67
|
+
end
|
68
|
+
|
69
|
+
options[:linenos] = 'inline' if options[:linenos] == true
|
70
|
+
options
|
71
|
+
end
|
72
|
+
|
73
|
+
def render_pygments(code, _context)
|
74
|
+
Scribo.logger.warn 'Warning: Highlight Tag no longer supports rendering with Pygments. Using the default highlighter, Rouge, instead.'
|
75
|
+
render_rouge(code)
|
76
|
+
end
|
77
|
+
|
78
|
+
def render_rouge(code)
|
79
|
+
require 'rouge'
|
80
|
+
formatter = ::Rouge::Formatters::HTMLLegacy.new(
|
81
|
+
line_numbers: @highlight_options[:linenos],
|
82
|
+
wrap: false,
|
83
|
+
css_class: 'highlight',
|
84
|
+
gutter_class: 'gutter',
|
85
|
+
code_class: 'code'
|
86
|
+
)
|
87
|
+
lexer = ::Rouge::Lexer.find_fancy(@lang, code) || Rouge::Lexers::PlainText
|
88
|
+
formatter.format(lexer.lex(code))
|
89
|
+
end
|
90
|
+
|
91
|
+
def render_codehighlighter(code)
|
92
|
+
Scribo.logger.warn 'Warning: Highlight Tag no longer supports rendering with Pygments. Using the default highlighter, Rouge, instead.'
|
93
|
+
render_rouge(code)
|
94
|
+
end
|
95
|
+
|
96
|
+
def add_code_tag(code)
|
97
|
+
code_attributes = [
|
98
|
+
"class=\"language-#{@lang.to_s.tr('+', '-')}\"",
|
99
|
+
"data-lang=\"#{@lang}\""
|
100
|
+
].join(' ')
|
101
|
+
"<figure class=\"highlight\"><pre><code #{code_attributes}>"\
|
102
|
+
"#{code.chomp}</code></pre></figure>"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
Liquid::Template.register_tag('highlight', HighlightBlock)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Include other published content
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%include 'navigation'}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%include 'navigation' title:"Menu"}
|
10
|
+
#
|
11
|
+
# This allows you pass variables to the included content, which will only available there
|
12
|
+
#
|
13
|
+
class IncludeTag < LiquidumTag
|
14
|
+
def render(context)
|
15
|
+
super
|
16
|
+
|
17
|
+
content = context.registers['file_system'].read_template_file(argv1)
|
18
|
+
|
19
|
+
result = ''
|
20
|
+
context.stack do
|
21
|
+
context['include'] = Scribo::IncludeDrop.new(attr_args.deep_stringify_keys)
|
22
|
+
result += Liquidum.render(content, context: context, registers: context.registers)
|
23
|
+
end
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Liquid::Template.register_tag('include', IncludeTag)
|
@@ -0,0 +1,24 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a text_field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%label for:"name"%}Name:{%endlabel%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%label name%}Name:{%endlabel%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
class LabelTag < LiquidumBlock
|
14
|
+
def render(context)
|
15
|
+
super
|
16
|
+
|
17
|
+
@form_model = lookup(context, 'form.model')
|
18
|
+
@form_class_name = lookup(context, 'form.class_name')
|
19
|
+
|
20
|
+
%[<label] + attr_str(:for, arg(:for), input(:id, argv1)) + %[>] + render_body + %[</label>]
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
Liquid::Template.register_tag('label', LabelTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a number-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%number_field name:"name" value:"1"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%number_field name%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
|
14
|
+
require_relative './text_field_tag'
|
15
|
+
|
16
|
+
class NumberFieldTag < TextFieldTag
|
17
|
+
def initialize(tag, args, tokens)
|
18
|
+
super
|
19
|
+
@field_type = 'number'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('number_field', NumberFieldTag)
|
@@ -0,0 +1,36 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a text-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%assign airports = "Eindhoven, Schiphol" | split: ', '%}
|
7
|
+
# {%options_for_select airports%}
|
8
|
+
#
|
9
|
+
# == Advanced usage:
|
10
|
+
# {%assign airports = "Eindhoven, Schiphol" | split: ', '%}
|
11
|
+
# {%options_for_select airports selected:"Schiphol" disabled:"Eindhoven"%}
|
12
|
+
#
|
13
|
+
# == Advanced usage:
|
14
|
+
# {%options_for_select airports name value selected:"Schiphol" disabled:"Eindhoven"%}
|
15
|
+
#
|
16
|
+
# This last usage requires a model on the form
|
17
|
+
#
|
18
|
+
class OptionsForSelectTag < LiquidumTag
|
19
|
+
def render(context)
|
20
|
+
super
|
21
|
+
|
22
|
+
options = argv1.map(&:to_liquid)
|
23
|
+
|
24
|
+
if sargs.present?
|
25
|
+
options = options.map do |option|
|
26
|
+
result = sargs.map { |a| option[a.to_s] }
|
27
|
+
result = result.first if result.length == 1
|
28
|
+
result
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
context.registers['controller'].helpers.options_for_select(options, attr_args).to_s
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
Liquid::Template.register_tag('options_for_select', OptionsForSelectTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a password-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%password_field name:"name" value:"1"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%password_field name%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
|
14
|
+
require_relative './text_field_tag'
|
15
|
+
|
16
|
+
class PasswordFieldTag < TextFieldTag
|
17
|
+
def initialize(tag, args, tokens)
|
18
|
+
super
|
19
|
+
@field_type = 'password'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('password_field', PasswordFieldTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a search-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%search_field name:"name" value:"1"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%search_field name%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
|
14
|
+
require_relative './text_field_tag'
|
15
|
+
|
16
|
+
class SearchFieldTag < TextFieldTag
|
17
|
+
def initialize(tag, args, tokens)
|
18
|
+
super
|
19
|
+
@field_type = 'search'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('search_field', SearchFieldTag)
|
@@ -0,0 +1,29 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Full-text searches content, in both content and properties
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%search q%}
|
7
|
+
# {{search|size}} results
|
8
|
+
# {%endsearch%}
|
9
|
+
#
|
10
|
+
# Note: It will only look at published content
|
11
|
+
class SearchTag < LiquidumBlock
|
12
|
+
def render(context)
|
13
|
+
super
|
14
|
+
|
15
|
+
current_content = context.registers['content']
|
16
|
+
request = context.registers['controller'].request
|
17
|
+
|
18
|
+
contents = current_content.site.contents.published.search(request.params[argv1])
|
19
|
+
|
20
|
+
result = ''
|
21
|
+
context.stack do
|
22
|
+
context['results'] = contents.map { |content| Scribo::ContentDrop.new(content) }
|
23
|
+
result += render_body
|
24
|
+
end
|
25
|
+
result
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
Liquid::Template.register_tag('search', SearchTag)
|
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Adds a (by default submit) button
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%select name:'group'%}{%endselect%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%select group%}{%endselect%}
|
10
|
+
#
|
11
|
+
class SelectTag < LiquidumBlock
|
12
|
+
def render(context)
|
13
|
+
super
|
14
|
+
|
15
|
+
%[<select] + attr_str(:name, arg(:name), input(:name, argv1)) +
|
16
|
+
attr_str(:id, arg(:id), input(:id, argv1)) +
|
17
|
+
attrs_str(reject: %[name id]) +
|
18
|
+
%[>] + render_body + %[</select>]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
Liquid::Template.register_tag('select', SelectTag)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Adds SEO tags
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%seo%}
|
7
|
+
#
|
8
|
+
class SeoTag < LiquidumTag
|
9
|
+
def render(context)
|
10
|
+
super
|
11
|
+
|
12
|
+
content = context.registers['content']
|
13
|
+
site = content.site
|
14
|
+
request = context.registers['controller'].request
|
15
|
+
|
16
|
+
%[
|
17
|
+
<!-- Begin Scribo SEO tag #{Scribo::VERSION} -->
|
18
|
+
<title>#{site.properties['title']}</title>
|
19
|
+
<meta name="generator" content="Scribo #{Scribo::VERSION}" />
|
20
|
+
<meta property="og:title" content="#{content.site.title}" />
|
21
|
+
<meta name="author" content="#{site.properties['author'].is_a?(String) ? site.properties['author'] : ''}" />
|
22
|
+
<meta property="og:locale" content="en_US" />
|
23
|
+
<meta name="description" content="#{site.properties['description']}" />
|
24
|
+
<meta property="og:description" content="#{site.properties['description']}" />
|
25
|
+
<link rel="canonical" href="#{request.protocol + request.host}" />
|
26
|
+
<meta property="og:url" content="#{request.protocol + request.host}" />
|
27
|
+
<meta property="og:site_name" content="#{content.site.title}" />
|
28
|
+
<script type="application/ld+json">
|
29
|
+
{"url":"#{request.protocol + request.host}","headline":"#{site.properties['title']}","name":"#{site.properties['title']}","author":{"@type":"Person","name":"#{site.properties['author']}"},"description":"#{site.properties['description']}","@type":"WebSite","@context":"https://schema.org"}</script>
|
30
|
+
<!-- End Scribo SEO tag -->
|
31
|
+
]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Liquid::Template.register_tag('seo', SeoTag)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Sets the value in the session
|
4
|
+
#
|
5
|
+
# {%set_session name value%}
|
6
|
+
# {%set_session locale 'nl'%}
|
7
|
+
# {%set_session locale request.query_parameters['lang']%}
|
8
|
+
# {%set_session locale request.query_parameters['lang']%}
|
9
|
+
# {%set_session coupon_code 'beyou'%}
|
10
|
+
class SetSessionTag < LiquidumTag
|
11
|
+
def render(context)
|
12
|
+
super
|
13
|
+
|
14
|
+
context.registers['controller'].session[argv1] = sargs.first
|
15
|
+
''
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
Liquid::Template.register_tag('set_session', SetSessionTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a telephone-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%telephone_field name:"phone" value:"1"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%telephone_field phone%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
|
14
|
+
require_relative './text_field_tag'
|
15
|
+
|
16
|
+
class TelephoneFieldTag < TextFieldTag
|
17
|
+
def initialize(tag, args, tokens)
|
18
|
+
super
|
19
|
+
@field_type = 'tel'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('telephone_field', TelephoneFieldTag)
|
@@ -0,0 +1,35 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a text-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%text_field name:"name" value:"Pencil"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%text_field name%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
class TextFieldTag < LiquidumTag
|
14
|
+
attr_accessor :field_type
|
15
|
+
|
16
|
+
def initialize(tag, args, tokens)
|
17
|
+
super
|
18
|
+
@field_type = 'text'
|
19
|
+
end
|
20
|
+
|
21
|
+
def render(context)
|
22
|
+
super
|
23
|
+
|
24
|
+
result = %[<input] +
|
25
|
+
attr_str(:name, arg(:name), input(:name, argv1)) +
|
26
|
+
attr_str(:id, arg(:id), input(:id, argv1)) +
|
27
|
+
attr_str(:value, arg(:value), input(:value, argv1))
|
28
|
+
|
29
|
+
result += attrs_str(reject: %[name value id])
|
30
|
+
result += %[ type="#{field_type}"/>]
|
31
|
+
result
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Liquid::Template.register_tag('text_field', TextFieldTag)
|
@@ -0,0 +1,28 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a text-area, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%textarea name:"name"%}{%endtextarea%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%textarea name%}{%endtextarea%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
class TextareaTag < LiquidumBlock
|
14
|
+
def render(context)
|
15
|
+
super
|
16
|
+
|
17
|
+
result = %[<textarea] +
|
18
|
+
attr_str(:name, arg(:name), input(:name, argv1)) +
|
19
|
+
attr_str(:id, arg(:id), input(:id, argv1))
|
20
|
+
|
21
|
+
result += attrs_str(reject: %[name id])
|
22
|
+
result += %[>] + render_body + %[</textarea>]
|
23
|
+
|
24
|
+
result
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
Liquid::Template.register_tag('textarea', TextareaTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a time-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%time_field name:"name" value:"1"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%time_field name%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
|
14
|
+
require_relative './text_field_tag'
|
15
|
+
|
16
|
+
class TimeFieldTag < TextFieldTag
|
17
|
+
def initialize(tag, args, tokens)
|
18
|
+
super
|
19
|
+
@field_type = 'time'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('time_field', TimeFieldTag)
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
# Add a url-field, either specifying everything manually or using a model object on the form
|
4
|
+
#
|
5
|
+
# == Basic usage:
|
6
|
+
# {%url_field name:"homepage" value:"1"%}
|
7
|
+
#
|
8
|
+
# == Advanced usage:
|
9
|
+
# {%url_field homepage%}
|
10
|
+
#
|
11
|
+
# This last usage requires a model on the form
|
12
|
+
#
|
13
|
+
|
14
|
+
require_relative './text_field_tag'
|
15
|
+
|
16
|
+
class UrlFieldTag < TextFieldTag
|
17
|
+
def initialize(tag, args, tokens)
|
18
|
+
super
|
19
|
+
@field_type = 'url'
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
Liquid::Template.register_tag('url_field', UrlFieldTag)
|
@@ -0,0 +1,89 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scribo
|
4
|
+
class Preamble
|
5
|
+
DEFAULTS = {
|
6
|
+
external_encoding: Encoding.default_external
|
7
|
+
}.freeze
|
8
|
+
|
9
|
+
attr_accessor :metadata, :content
|
10
|
+
|
11
|
+
def initialize(metadata, content)
|
12
|
+
@metadata = metadata
|
13
|
+
@content = content
|
14
|
+
end
|
15
|
+
|
16
|
+
def metadata_with_content
|
17
|
+
@metadata.to_yaml + "---\n" + @content
|
18
|
+
end
|
19
|
+
|
20
|
+
def dump
|
21
|
+
metadata_with_content
|
22
|
+
end
|
23
|
+
|
24
|
+
def save(path, options = {})
|
25
|
+
options = DEFAULTS.merge(options)
|
26
|
+
|
27
|
+
File.open(path, "w:#{options[:external_encoding]}") do |f|
|
28
|
+
f.write metadata_with_content
|
29
|
+
end
|
30
|
+
end
|
31
|
+
|
32
|
+
def self.parse(data)
|
33
|
+
preamble_lines = +''
|
34
|
+
content_lines = +''
|
35
|
+
|
36
|
+
state = :before_preamble
|
37
|
+
|
38
|
+
f = StringIO.new(data)
|
39
|
+
f.each do |line|
|
40
|
+
stripped = line.strip
|
41
|
+
|
42
|
+
case state
|
43
|
+
when :before_preamble
|
44
|
+
|
45
|
+
new_state = case stripped
|
46
|
+
when '---'
|
47
|
+
:preamble
|
48
|
+
when ''
|
49
|
+
:before_preamble
|
50
|
+
else
|
51
|
+
content_lines << line
|
52
|
+
:after_preamble
|
53
|
+
end
|
54
|
+
|
55
|
+
when :preamble
|
56
|
+
|
57
|
+
new_state = case stripped
|
58
|
+
when '---'
|
59
|
+
:after_preamble
|
60
|
+
else
|
61
|
+
preamble_lines << line
|
62
|
+
:preamble
|
63
|
+
end
|
64
|
+
|
65
|
+
when :after_preamble
|
66
|
+
new_state = :after_preamble
|
67
|
+
content_lines << line
|
68
|
+
|
69
|
+
else
|
70
|
+
raise "Invalid State: #{state}"
|
71
|
+
end
|
72
|
+
|
73
|
+
state = new_state
|
74
|
+
end
|
75
|
+
|
76
|
+
new(Scribo::Utility.yaml_safe_parse(preamble_lines), content_lines)
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.load(path, options = {})
|
80
|
+
f = File.open(path, "r:#{options[:external_encoding]}")
|
81
|
+
parse(f.read)
|
82
|
+
end
|
83
|
+
|
84
|
+
def self.load_multiple(*paths)
|
85
|
+
options = paths.last.is_a?(Hash) ? paths.pop : {}
|
86
|
+
paths.map { |path| Preamble.load(path, options) }
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Scribo
|
4
|
+
module SassC
|
5
|
+
class Importer < ::SassC::Importer
|
6
|
+
def imports(path, parent_path)
|
7
|
+
content = options[:content]
|
8
|
+
|
9
|
+
import_path = ''
|
10
|
+
if path.start_with?('/')
|
11
|
+
import_path += path
|
12
|
+
else
|
13
|
+
import_path += content.site.sass_dir
|
14
|
+
import_path += '/' unless import_path.end_with?('/')
|
15
|
+
|
16
|
+
import_path += path
|
17
|
+
import_path += File.extname(content.path)
|
18
|
+
import_path = File.expand_path(import_path, content.site.sass_dir)
|
19
|
+
unless import_path.start_with?(content.site.sass_dir)
|
20
|
+
# import_path always starts with /
|
21
|
+
import_path = content.site.sass_dir + import_path[1..-1]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
include_content = content.site.contents.where(kind: 'text').located(import_path, restricted: false)
|
26
|
+
unless include_content.present?
|
27
|
+
# Look for /_file.ext alternative
|
28
|
+
import_path = File.dirname(import_path) + '/_' + File.basename(import_path)
|
29
|
+
include_content = content.site.contents.where(kind: 'text').located(import_path, restricted: false)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Look in parent's folder
|
33
|
+
if include_content.blank? && File.dirname(parent_path) != '.'
|
34
|
+
import_path = content.site.sass_dir + File.dirname(parent_path) + '/' + File.basename(import_path)
|
35
|
+
include_content = content.site.contents.where(kind: 'text').located(import_path, restricted: false)
|
36
|
+
end
|
37
|
+
|
38
|
+
if include_content.empty? && content.site.properties.value_at_keypath('sass.sass_dir')
|
39
|
+
alternate_path = content.site.properties.value_at_keypath('sass.sass_dir')
|
40
|
+
# alternate_path += '/' unless alternate_path.end_with?('/')
|
41
|
+
alternate_path = '/' + alternate_path unless alternate_path.start_with?('/')
|
42
|
+
|
43
|
+
import_path = File.expand_path(path, alternate_path)
|
44
|
+
import_path += File.extname(content.path)
|
45
|
+
|
46
|
+
include_content = content.site.contents.where(kind: 'text').located(import_path, restricted: false)
|
47
|
+
|
48
|
+
unless include_content.present?
|
49
|
+
# Look for /_file.ext alternative
|
50
|
+
import_path = File.dirname(import_path) + '/_' + File.basename(import_path)
|
51
|
+
include_content = content.site.contents.located(import_path, restricted: false)
|
52
|
+
end
|
53
|
+
|
54
|
+
end
|
55
|
+
|
56
|
+
Scribo.config.logger.warn "SassC::Importer: No import found: #{import_path}" unless include_content.first
|
57
|
+
# FIXME: Add context
|
58
|
+
# Here we don't use a filter
|
59
|
+
source = ContentRenderService.new(include_content.first, {}, filter: nil).call || ''
|
60
|
+
::SassC::Importer::Import.new(path, source: source)
|
61
|
+
end
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
|
66
|
+
module Tilt
|
67
|
+
class Template
|
68
|
+
def eval_file
|
69
|
+
options[:full_path] || file || '(__TEMPLATE__)'
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|