quby-compiler 0.5.15 → 0.5.17
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +23 -1
- data/lib/quby/compiler/dsl/merge(values(:v_1, :v_2), values(v_4).rb +16 -0
- data/lib/quby/compiler/dsl/questionnaire_builder.rb +11 -0
- data/lib/quby/compiler/dsl/questions/base.rb +1 -0
- data/lib/quby/compiler/dsl/questions/integer_question_builder.rb +10 -0
- data/lib/quby/compiler/dsl/sexp_variable_builder.rb +57 -0
- data/lib/quby/compiler/entities/question.rb +8 -0
- data/lib/quby/compiler/entities/question_option.rb +3 -0
- data/lib/quby/compiler/entities/questionnaire.rb +8 -0
- data/lib/quby/compiler/entities/questions/concerns/split_to_units.rb +58 -0
- data/lib/quby/compiler/entities/questions/integer_question.rb +2 -0
- data/lib/quby/compiler/entities/sexp_variable.rb +50 -0
- data/lib/quby/compiler/entities/sexp_variables.rb +41 -0
- data/lib/quby/compiler/outputs/quby_frontend_v1_serializer.rb +1 -1
- data/lib/quby/compiler/outputs/quby_frontend_v2_serializer.rb +26 -7
- data/lib/quby/compiler/services/definition_validator.rb +7 -0
- data/lib/quby/compiler/version.rb +1 -1
- metadata +7 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 4be07e6f3fabe1a0b02fbc36ea63c5ccd964519aedb08d0adaf9b6196f4f9830
|
4
|
+
data.tar.gz: 382ea4dc3bd640a7d2e92b9bb27ad1bd5b1176129eb93e84fc71ad954bb691f9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1e699567c3318dcc2b4cf9d7b2b44e7c05cacab8783f17e5631bfcee12d1de690aba8ab8ae3e9da93bab07be680a26f4fe9ca735af8c27ea7bbd72b79146aad9
|
7
|
+
data.tar.gz: 8ffbc7c1374528de5edefd0e35cab356c07e98b0e2f6436b0291510be9d0751971261846c7b98300290fc12689dd6a961816de16b1cebf0ff90bf6f0bce70d29
|
data/CHANGELOG.md
CHANGED
@@ -1,7 +1,29 @@
|
|
1
|
+
# 0.5.17
|
2
|
+
|
3
|
+
* Add option#label.
|
4
|
+
* quby.json
|
5
|
+
* Add option#label to option#description just in case.
|
6
|
+
* quby2.json:
|
7
|
+
* Pass options#hidden.
|
8
|
+
* Allow hr tags in prose.
|
9
|
+
* Allow all prose tags in question#description, except headers.
|
10
|
+
* Allow css_vars to be defined on questionnaire and question level.
|
11
|
+
* Add option#label
|
12
|
+
* quby2.json: Add option#label (without fallback for now, until quby2 0.9.7 is deployed everywhere).
|
13
|
+
|
14
|
+
# 0.5.16
|
15
|
+
|
16
|
+
* add integer as split_to_units option, with units and conversions as attributes
|
17
|
+
* add sexp_variables to do calculations using s expressions, for now in quby2, but later in the backend.
|
18
|
+
* test that select/radio options are always numeric
|
19
|
+
* quby2.json
|
20
|
+
* add split_to_units question, that saves a integer.
|
21
|
+
* Calculate sexpr variables and allow strings to interpolate them {{calculation.some_var}}
|
22
|
+
|
1
23
|
# 0.5.15
|
2
24
|
|
3
25
|
* Add context_description to questions, to have a text item that is hidden together with the question.
|
4
|
-
*
|
26
|
+
* quby2.json
|
5
27
|
* Moved quby2 serialization to the serializer, compact everything, no markdown for v2 title/descriptions.
|
6
28
|
* Sanitize Quby2 html in v2.
|
7
29
|
* Add contextDescription to questions.
|
@@ -0,0 +1,16 @@
|
|
1
|
+
merge(values(:v_1, :v_2), values(v_4).recode(1 => 3)).sum
|
2
|
+
|
3
|
+
|
4
|
+
|
5
|
+
divide(value(:v_2), multiply(value(:v_1), value(:v_1)))
|
6
|
+
|
7
|
+
w / l * l
|
8
|
+
|
9
|
+
|
10
|
+
sexp_variable :key1 do
|
11
|
+
foo = values(:v_1, :v_2)
|
12
|
+
bar = recode(foo, 1 => 3)
|
13
|
+
bla = merge(foo, bar)
|
14
|
+
sum(bla)
|
15
|
+
|
16
|
+
end
|
@@ -8,6 +8,7 @@ require 'quby/compiler/dsl/charting/line_chart_builder'
|
|
8
8
|
require 'quby/compiler/dsl/charting/radar_chart_builder'
|
9
9
|
require 'quby/compiler/dsl/charting/bar_chart_builder'
|
10
10
|
require 'quby/compiler/dsl/charting/overview_chart_builder'
|
11
|
+
require 'quby/compiler/dsl/sexp_variable_builder'
|
11
12
|
|
12
13
|
require_relative 'standardized_panel_generators'
|
13
14
|
|
@@ -139,6 +140,12 @@ module Quby
|
|
139
140
|
@questionnaire.extra_css += value
|
140
141
|
end
|
141
142
|
|
143
|
+
# css_vars("option-gap-y" => 1)
|
144
|
+
def css_vars(value)
|
145
|
+
@questionnaire.css_vars ||= {}
|
146
|
+
@questionnaire.css_vars.merge!(value)
|
147
|
+
end
|
148
|
+
|
142
149
|
def allow_switch_to_bulk(value=true)
|
143
150
|
@questionnaire.allow_switch_to_bulk = value
|
144
151
|
end
|
@@ -200,6 +207,10 @@ module Quby
|
|
200
207
|
end
|
201
208
|
end
|
202
209
|
|
210
|
+
def sexp_variable(key, &block)
|
211
|
+
@questionnaire.add_sexp_variable(key, SexpVariableBuilder.new(key, &block).build)
|
212
|
+
end
|
213
|
+
|
203
214
|
# variable :totaal do
|
204
215
|
# # Plain old Ruby code here, executed in the scope of the answer
|
205
216
|
# # variables are private to the score calculation
|
@@ -14,6 +14,16 @@ module Quby
|
|
14
14
|
super
|
15
15
|
@question = Entities::Questions::IntegerQuestion.new(key, options)
|
16
16
|
end
|
17
|
+
|
18
|
+
# as split_to_units
|
19
|
+
def units(*values)
|
20
|
+
@question.units = values
|
21
|
+
end
|
22
|
+
|
23
|
+
# as split_to_units
|
24
|
+
def conversions(value)
|
25
|
+
@question.conversions = value
|
26
|
+
end
|
17
27
|
end
|
18
28
|
end
|
19
29
|
end
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'quby/compiler/entities/sexp_variable'
|
4
|
+
module Quby::Compiler
|
5
|
+
module DSL
|
6
|
+
# sexp_variable :myvar do
|
7
|
+
# sum(number_values(:v_1, :v_2))
|
8
|
+
# end
|
9
|
+
class ::SexpVariableBuilder
|
10
|
+
attr_reader :calculation, :key
|
11
|
+
|
12
|
+
def initialize(key, &block)
|
13
|
+
@key = key
|
14
|
+
@calculation = instance_eval(&block)
|
15
|
+
end
|
16
|
+
|
17
|
+
def string_value(key)
|
18
|
+
Entities::SexpVariables::StringValue.new(op: :string_value, key: key)
|
19
|
+
end
|
20
|
+
|
21
|
+
def number_value(key)
|
22
|
+
Entities::SexpVariables::NumberValue.new(op: :number_value, key: key)
|
23
|
+
end
|
24
|
+
|
25
|
+
def number_values(*keys)
|
26
|
+
keys.map { |key| number_value(key) }
|
27
|
+
end
|
28
|
+
|
29
|
+
%i[sum subtract multiply divide].each do |op|
|
30
|
+
define_method(op) do |*values|
|
31
|
+
Entities::SexpVariables::NumberReducer.new(op:, values: wrap_and_flatten(values))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def round(value)
|
36
|
+
Entities::SexpVariables::NumberMethod.new(op: :round, value: value)
|
37
|
+
end
|
38
|
+
|
39
|
+
def build
|
40
|
+
Entities::SexpVariable.new(key:, calculation:)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def wrap_and_flatten(values)
|
46
|
+
values.flat_map { |value|
|
47
|
+
case value
|
48
|
+
when Numeric
|
49
|
+
Entities::SexpVariables::Number.new(op: :number, value: value)
|
50
|
+
else
|
51
|
+
value
|
52
|
+
end
|
53
|
+
}
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -30,6 +30,9 @@ module Quby
|
|
30
30
|
# How should we display this question
|
31
31
|
attr_accessor :as
|
32
32
|
|
33
|
+
# extra styling options
|
34
|
+
attr_accessor :css_vars
|
35
|
+
|
33
36
|
# To hide old questions
|
34
37
|
attr_accessor :hidden
|
35
38
|
validates :hidden, inclusion: {in: [true, false, nil], message: "must be boolean"}
|
@@ -164,6 +167,7 @@ module Quby
|
|
164
167
|
@cols = options[:cols] || 40
|
165
168
|
@default_invisible = options[:default_invisible] || false
|
166
169
|
@labels ||= []
|
170
|
+
@css_vars = options[:css_vars]
|
167
171
|
|
168
172
|
@col_span = options[:col_span] || 1
|
169
173
|
@row_span = options[:row_span] || 1
|
@@ -208,6 +212,10 @@ module Quby
|
|
208
212
|
end
|
209
213
|
# rubocop:enable CyclomaticComplexity, Metrics/MethodLength
|
210
214
|
|
215
|
+
# called after DSL has instance_evalled everything within the question block.
|
216
|
+
def after_build
|
217
|
+
end
|
218
|
+
|
211
219
|
def context_free_title_or_title
|
212
220
|
context_free_title || title
|
213
221
|
end
|
@@ -11,6 +11,8 @@ module Quby
|
|
11
11
|
|
12
12
|
attr_reader :key
|
13
13
|
attr_reader :value
|
14
|
+
validates :value, numericality: {allow_nil: true} # nil for checkbox questions.
|
15
|
+
attr_reader :label
|
14
16
|
attr_reader :description, :context_free_description
|
15
17
|
attr_reader :questions
|
16
18
|
# for scale/radio/checbox questions, piece of of html that is rendered between the options
|
@@ -31,6 +33,7 @@ module Quby
|
|
31
33
|
@key = key
|
32
34
|
@question = question
|
33
35
|
@value = options[:value]
|
36
|
+
@label = options[:label]
|
34
37
|
@description = options[:description]
|
35
38
|
@context_free_description = options[:context_free_description]
|
36
39
|
@questions = []
|
@@ -40,6 +40,7 @@ module Quby
|
|
40
40
|
@license = :unknown
|
41
41
|
@layout_version = nil
|
42
42
|
@extra_css = ""
|
43
|
+
@css_vars = nil
|
43
44
|
@allow_switch_to_bulk = false
|
44
45
|
@panels = []
|
45
46
|
@flags = {}.with_indifferent_access
|
@@ -53,6 +54,7 @@ module Quby
|
|
53
54
|
@outcome_tables = []
|
54
55
|
@check_score_keys_consistency = true
|
55
56
|
@lookup_tables = {}
|
57
|
+
@sexp_variables = {}
|
56
58
|
@versions = []
|
57
59
|
@seeds_patch = {}
|
58
60
|
@anonymous_conditions = Entities::AnonymousConditions.new
|
@@ -76,6 +78,7 @@ module Quby
|
|
76
78
|
attr_writer :leave_page_alert
|
77
79
|
attr_reader :fields
|
78
80
|
attr_accessor :extra_css
|
81
|
+
attr_accessor :css_vars
|
79
82
|
attr_accessor :allow_switch_to_bulk
|
80
83
|
attr_reader :license
|
81
84
|
attr_accessor :licensor
|
@@ -102,6 +105,7 @@ module Quby
|
|
102
105
|
|
103
106
|
attr_accessor :outcome_tables
|
104
107
|
attr_accessor :score_schemas
|
108
|
+
attr_accessor :sexp_variables
|
105
109
|
attr_accessor :lookup_tables
|
106
110
|
attr_accessor :anonymous_conditions
|
107
111
|
|
@@ -362,6 +366,10 @@ module Quby
|
|
362
366
|
end
|
363
367
|
end
|
364
368
|
|
369
|
+
def add_sexp_variable(key, sexp_variable)
|
370
|
+
sexp_variables[key] = sexp_variable
|
371
|
+
end
|
372
|
+
|
365
373
|
def add_outcome_table(outcome_table_options)
|
366
374
|
outcome_tables << OutcomeTable.new(**outcome_table_options, questionnaire: self)
|
367
375
|
end
|
@@ -0,0 +1,58 @@
|
|
1
|
+
module Quby::Compiler::Entities::Questions::Concerns
|
2
|
+
module SplitToUnits
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
DEFAULT_SPLIT_TO_UNIT_CONVERSIONS = {
|
5
|
+
minutes: {
|
6
|
+
hours: 60,
|
7
|
+
days: 1440,
|
8
|
+
weeks: 10080
|
9
|
+
},
|
10
|
+
seconds: {
|
11
|
+
minutes: 60,
|
12
|
+
hours: 3600,
|
13
|
+
days: 86400
|
14
|
+
},
|
15
|
+
m: {
|
16
|
+
km: 1000
|
17
|
+
},
|
18
|
+
cm: {
|
19
|
+
m: 100
|
20
|
+
},
|
21
|
+
mm: {
|
22
|
+
cm: 10,
|
23
|
+
m: 1000
|
24
|
+
},
|
25
|
+
g: {
|
26
|
+
kg: 1000
|
27
|
+
}
|
28
|
+
}.freeze
|
29
|
+
|
30
|
+
included do
|
31
|
+
attr_accessor :units, :conversions
|
32
|
+
|
33
|
+
validates :units, :conversions, presence: true, if: -> { as == :split_to_units }
|
34
|
+
validate :validate_split_to_units, if: -> { as == :split_to_units }
|
35
|
+
end
|
36
|
+
|
37
|
+
def after_build
|
38
|
+
super
|
39
|
+
return unless as == :split_to_units
|
40
|
+
@unit = units&.last
|
41
|
+
(@conversions ||= {}).reverse_merge!(default_split_to_units_conversions)
|
42
|
+
end
|
43
|
+
|
44
|
+
def default_split_to_units_conversions
|
45
|
+
(DEFAULT_SPLIT_TO_UNIT_CONVERSIONS[unit] || {}).slice(*units)
|
46
|
+
end
|
47
|
+
|
48
|
+
def validate_split_to_units
|
49
|
+
return unless units.present? && conversions.present?
|
50
|
+
|
51
|
+
(units - [unit]).each do |unit_to_convert|
|
52
|
+
if conversions[unit_to_convert].nil?
|
53
|
+
errors.add(:conversions, "should contain a conversion for unit #{unit_to_convert}")
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
58
|
+
end
|
@@ -1,6 +1,7 @@
|
|
1
1
|
# frozen_string_literal: true
|
2
2
|
|
3
3
|
require_relative 'concerns/slider'
|
4
|
+
require_relative 'concerns/split_to_units'
|
4
5
|
|
5
6
|
module Quby
|
6
7
|
module Compiler
|
@@ -8,6 +9,7 @@ module Quby
|
|
8
9
|
module Questions
|
9
10
|
class IntegerQuestion < Question
|
10
11
|
include Concerns::Slider
|
12
|
+
include Concerns::SplitToUnits
|
11
13
|
|
12
14
|
def size
|
13
15
|
@size || 30
|
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'quby/compiler/entities/sexp_variables'
|
2
|
+
|
3
|
+
module Quby::Compiler::Entities
|
4
|
+
class SexpVariable
|
5
|
+
attr_reader :calculation, :key
|
6
|
+
|
7
|
+
def initialize(key:, calculation:)
|
8
|
+
@key = key
|
9
|
+
@calculation = calculation
|
10
|
+
end
|
11
|
+
|
12
|
+
# Called by DefinitionValidator.
|
13
|
+
def validate(questionnaire)
|
14
|
+
case calculation
|
15
|
+
when SexpVariables::NumberValue
|
16
|
+
validate_question_exist(questionnaire, calculation)
|
17
|
+
validate_value_is_number(questionnaire, calculation)
|
18
|
+
when SexpVariables::StringValue
|
19
|
+
validate_question_exist(questionnaire, calculation)
|
20
|
+
validate_value_is_string(questionnaire, calculation)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
def validate_question_exist(questionnaire, sexp)
|
25
|
+
return if questionnaire.question_hash.key?(sexp.key)
|
26
|
+
|
27
|
+
fail "sexp_variable #{key} uses nonexistent question #{sexp.key}."
|
28
|
+
end
|
29
|
+
|
30
|
+
def validate_value_is_number(questionnaire, sexp)
|
31
|
+
question = questionnaire.question_hash[sexp.key]
|
32
|
+
case question
|
33
|
+
when Questions::IntegerQuestion, Questions::FloatQuestion, Questions::SelectQuestion, Questions::RadioQuestion
|
34
|
+
return
|
35
|
+
end
|
36
|
+
|
37
|
+
fail "sexp_variable #{key} uses non-numeric question #{sexp.key} for number_value."
|
38
|
+
end
|
39
|
+
|
40
|
+
def validate_value_is_string(questionnaire, sexp)
|
41
|
+
question = questionnaire.question_hash[sexp.key]
|
42
|
+
case question
|
43
|
+
when Questions::StringQuestion, Questions::TextareaQuestion
|
44
|
+
return
|
45
|
+
end
|
46
|
+
|
47
|
+
fail "sexp_variable #{key} uses non-string question #{sexp.key} for string_value."
|
48
|
+
end
|
49
|
+
end
|
50
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
module Quby::Compiler::Entities
|
2
|
+
module SexpVariables
|
3
|
+
class Base < Dry::Struct
|
4
|
+
end
|
5
|
+
|
6
|
+
# recursive dependencies, we so we define the classes first.
|
7
|
+
class NumberValue < Base; end
|
8
|
+
class Number < Base; end
|
9
|
+
class NumberReducer < Base; end
|
10
|
+
class NumberMethod < Base; end
|
11
|
+
|
12
|
+
NumericType = Number | NumberReducer | NumberMethod | NumberValue
|
13
|
+
|
14
|
+
class NumberValue
|
15
|
+
attribute :op, Quby::Types::Symbol.enum(:number_value)
|
16
|
+
attribute :key, Quby::Types::Symbol
|
17
|
+
end
|
18
|
+
|
19
|
+
class StringValue < Base
|
20
|
+
attribute :op, Quby::Types::Symbol.enum(:string_value)
|
21
|
+
attribute :key, Quby::Types::Symbol
|
22
|
+
end
|
23
|
+
|
24
|
+
class Number
|
25
|
+
attribute :op, Quby::Types::Symbol.enum(:value)
|
26
|
+
attribute :value, Quby::Types::Integer | Quby::Types::Float
|
27
|
+
end
|
28
|
+
|
29
|
+
# returning a Number
|
30
|
+
class NumberReducer
|
31
|
+
attribute :op, Quby::Types::Symbol.enum(:sum, :subtract, :multiply, :divide)
|
32
|
+
attribute :values, Quby::Types::Array.of(NumericType)
|
33
|
+
end
|
34
|
+
|
35
|
+
# returning a Number
|
36
|
+
class NumberMethod
|
37
|
+
attribute :op, Quby::Types::Symbol.enum(:round)
|
38
|
+
attribute :value, NumericType
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -192,7 +192,7 @@ module Quby
|
|
192
192
|
{
|
193
193
|
key: option.key,
|
194
194
|
value: option.value,
|
195
|
-
description: option.description,
|
195
|
+
description: option.label ? "#{option.label} #{option.description}" : option.description,
|
196
196
|
context_free_description: option.context_free_description,
|
197
197
|
questions: option.questions.map {|question| question_as_json(question)},
|
198
198
|
inner_title: option.inner_title,
|
@@ -23,7 +23,9 @@ module Quby
|
|
23
23
|
questions: questions,
|
24
24
|
textvars: textvars,
|
25
25
|
validations: validations,
|
26
|
-
visibilityRules: visibility_rules.as_json
|
26
|
+
visibilityRules: visibility_rules.as_json,
|
27
|
+
sexpVariables: sexp_variables,
|
28
|
+
cssVars: css_vars,
|
27
29
|
}
|
28
30
|
end
|
29
31
|
|
@@ -83,10 +85,17 @@ module Quby
|
|
83
85
|
end
|
84
86
|
|
85
87
|
def float_question(question)
|
86
|
-
|
88
|
+
number_question(question)
|
87
89
|
end
|
88
90
|
|
89
91
|
def integer_question(question)
|
92
|
+
{
|
93
|
+
**number_question(question),
|
94
|
+
**split_to_units_question(question),
|
95
|
+
}.compact
|
96
|
+
end
|
97
|
+
|
98
|
+
def number_question(question)
|
90
99
|
{
|
91
100
|
**base_question(question),
|
92
101
|
**slider_question(question),
|
@@ -94,8 +103,8 @@ module Quby
|
|
94
103
|
maximum: question.maximum,
|
95
104
|
size: size(question),
|
96
105
|
unit: question.as != :slider && question.unit,
|
97
|
-
|
98
|
-
end
|
106
|
+
}.compact
|
107
|
+
end
|
99
108
|
|
100
109
|
def radio_question(question)
|
101
110
|
{
|
@@ -141,6 +150,7 @@ module Quby
|
|
141
150
|
description: handle_html(question.description, type: :question_description),
|
142
151
|
contextDescription: handle_html(question.context_description, type: :prose, v1_markdown: false),
|
143
152
|
type: question_type(question),
|
153
|
+
cssVars: question.css_vars,
|
144
154
|
hidden: question.hidden?,
|
145
155
|
displayModes: question.display_modes,
|
146
156
|
viewSelector: question.view_selector,
|
@@ -165,6 +175,13 @@ module Quby
|
|
165
175
|
}
|
166
176
|
end
|
167
177
|
|
178
|
+
def split_to_units_question(question)
|
179
|
+
{
|
180
|
+
units: question.units,
|
181
|
+
conversions: question.conversions,
|
182
|
+
}
|
183
|
+
end
|
184
|
+
|
168
185
|
def question_type(question)
|
169
186
|
{
|
170
187
|
date: 'date_parts',
|
@@ -200,8 +217,10 @@ module Quby
|
|
200
217
|
type: 'option',
|
201
218
|
key: option.key,
|
202
219
|
value: option.question.type != :check_box && option.value,
|
220
|
+
label: option.label, # TODO fallback on description and empty description if no label (after quby2 has been deployed)
|
203
221
|
description: option.question.type == :select ? option.description : handle_html(option.description),
|
204
|
-
questions: option.question.type != :select && option.questions.map{ question(_1) },
|
222
|
+
questions: option.question.type != :select && option.questions.map{ question(_1) },
|
223
|
+
hidden: option.hidden.presence,
|
205
224
|
viewId: option.view_id
|
206
225
|
}.compact
|
207
226
|
end
|
@@ -237,9 +256,9 @@ module Quby
|
|
237
256
|
when :simple
|
238
257
|
html_sanitizer.sanitize(html, tags: %w[strong em sup sub br span], attributes: %w[class])
|
239
258
|
when :question_description
|
240
|
-
html_sanitizer.sanitize(html, tags: %w[strong em b i u sup sub p span br ul ol li], attributes: %w[class])
|
259
|
+
html_sanitizer.sanitize(html, tags: %w[strong em b i u sup sub pre blockquote p span br ul ol li a], attributes: %w[class])
|
241
260
|
when :prose
|
242
|
-
html_sanitizer.sanitize(html, tags: %w[strong em b i u sup sub pre blockquote p span br ul ol li a h1 h2 h3 h4], attributes: %w[href class target])
|
261
|
+
html_sanitizer.sanitize(html, tags: %w[strong em b i u sup sub pre blockquote p span br ul ol li a h1 h2 h3 h4 hr], attributes: %w[href class target])
|
243
262
|
end
|
244
263
|
elsif v1_markdown
|
245
264
|
Quby::Compiler::MarkdownParser.new(html).to_html
|
@@ -26,6 +26,7 @@ module Quby
|
|
26
26
|
validate_outcome_tables(questionnaire)
|
27
27
|
validate_markdown_fields(questionnaire) if questionnaire.validate_html
|
28
28
|
validate_raw_content_items(questionnaire) if questionnaire.validate_html
|
29
|
+
validate_sexp_variables(questionnaire)
|
29
30
|
# Some compilation errors are Exceptions (pure syntax errors) and some StandardErrors (NameErrors)
|
30
31
|
rescue Exception => exception # rubocop:disable Lint/RescueException
|
31
32
|
definition.errors.add(:sourcecode, message: "Questionnaire error: #{definition.key}\n" \
|
@@ -364,6 +365,12 @@ scores_schema tables to the resulting seed."
|
|
364
365
|
fail "#{key || html} contains invalid html: #{fragment.errors.map(&:to_s).join(', ')}."
|
365
366
|
end
|
366
367
|
|
368
|
+
def validate_sexp_variables(questionnaire)
|
369
|
+
questionnaire.sexp_variables.each_value do |sexp_variable|
|
370
|
+
sexp_variable.validate(questionnaire)
|
371
|
+
end
|
372
|
+
end
|
373
|
+
|
367
374
|
def delete_prefix(key, questionnaire)
|
368
375
|
key.delete_prefix("#{questionnaire.key}_")
|
369
376
|
end
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: quby-compiler
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.17
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Marten Veldthuis
|
8
8
|
bindir: exe
|
9
9
|
cert_chain: []
|
10
|
-
date: 2025-
|
10
|
+
date: 2025-04-16 00:00:00.000000000 Z
|
11
11
|
dependencies:
|
12
12
|
- !ruby/object:Gem::Dependency
|
13
13
|
name: activemodel
|
@@ -150,6 +150,7 @@ files:
|
|
150
150
|
- lib/quby/compiler/dsl/charting/overview_chart_builder.rb
|
151
151
|
- lib/quby/compiler/dsl/charting/radar_chart_builder.rb
|
152
152
|
- lib/quby/compiler/dsl/helpers.rb
|
153
|
+
- lib/quby/compiler/dsl/merge(values(:v_1, :v_2), values(v_4).rb
|
153
154
|
- lib/quby/compiler/dsl/panel_builder.rb
|
154
155
|
- lib/quby/compiler/dsl/question_builder.rb
|
155
156
|
- lib/quby/compiler/dsl/questionnaire_builder.rb
|
@@ -165,6 +166,7 @@ files:
|
|
165
166
|
- lib/quby/compiler/dsl/questions/text_question_builder.rb
|
166
167
|
- lib/quby/compiler/dsl/score_builder.rb
|
167
168
|
- lib/quby/compiler/dsl/score_schema_builder.rb
|
169
|
+
- lib/quby/compiler/dsl/sexp_variable_builder.rb
|
168
170
|
- lib/quby/compiler/dsl/standardized_panel_generators.rb
|
169
171
|
- lib/quby/compiler/dsl/table_builder.rb
|
170
172
|
- lib/quby/compiler/entities.rb
|
@@ -188,6 +190,7 @@ files:
|
|
188
190
|
- lib/quby/compiler/entities/questionnaire.rb
|
189
191
|
- lib/quby/compiler/entities/questions/checkbox_question.rb
|
190
192
|
- lib/quby/compiler/entities/questions/concerns/slider.rb
|
193
|
+
- lib/quby/compiler/entities/questions/concerns/split_to_units.rb
|
191
194
|
- lib/quby/compiler/entities/questions/date_question.rb
|
192
195
|
- lib/quby/compiler/entities/questions/deprecated_question.rb
|
193
196
|
- lib/quby/compiler/entities/questions/float_question.rb
|
@@ -198,6 +201,8 @@ files:
|
|
198
201
|
- lib/quby/compiler/entities/questions/text_question.rb
|
199
202
|
- lib/quby/compiler/entities/score_calculation.rb
|
200
203
|
- lib/quby/compiler/entities/score_schema.rb
|
204
|
+
- lib/quby/compiler/entities/sexp_variable.rb
|
205
|
+
- lib/quby/compiler/entities/sexp_variables.rb
|
201
206
|
- lib/quby/compiler/entities/subscore_schema.rb
|
202
207
|
- lib/quby/compiler/entities/table.rb
|
203
208
|
- lib/quby/compiler/entities/text.rb
|