reflekt 0.2.0 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 6a460a27dcd832266459649d57e9b9ba8ae599ec653944d5ea375803cd549f28
4
- data.tar.gz: a4665017add098fdf3c12e73a27600767e432a71d7b45ea7b64be5ef8c0f0667
3
+ metadata.gz: d9282a0295c04e95cec339bfa6563a517ac12d964f6310320056669ad52b86e1
4
+ data.tar.gz: 8ad30ad01a3c021d60eb645e56ddf7aea528860ca30588bb9269dac0a5cc74d8
5
5
  SHA512:
6
- metadata.gz: 18191d516773841418776543dea540e708964a0783038a13fa7b28b59913ec9f41a6148208c6bc375274ff82adeae2e96da803397a2203a518166c9ca303ad6d
7
- data.tar.gz: 8c5ca58649349c019370fdcb0b83bda51ebd3dbdca7ac2a1e745b35dd64856811fe791c3d148c756ee47b24154a79d229656fb4f8c0b2f0598555da742dddc17
6
+ metadata.gz: e7be8cc94f17f83c4c5131862c0ffa424c7976f4baae38d535e2a45f77318d47543493b0259dc0a7a62ad7481a380615c09030060d29ef0462c4ab6bfa6d5cb2
7
+ data.tar.gz: 7fcee25ce29344e2181a8db3f3020c11ab4668560651869e81cfa5e059aa31ae35ce45c06892a19946b8509f2d592e0dc7d171ede27b1d6b5f45fa1dbff3744c
@@ -1,13 +1,7 @@
1
1
  require 'set'
2
-
3
- # Production.
2
+ require 'erb'
4
3
  require 'rowdb'
5
4
 
6
- # Development.
7
- #require_relative '../../rowdb/lib/rowdb.rb'
8
- #require_relative '../../rowdb/lib/adapters/Adapter.rb'
9
- #require_relative '../../rowdb/lib/adapters/FileSystem.rb'
10
-
11
5
  ################################################################################
12
6
  # REFLEKT
13
7
  #
@@ -19,27 +13,60 @@ require 'rowdb'
19
13
 
20
14
  module Reflekt
21
15
 
22
- @@clone_count = 5
16
+ @@reflekt_clone_count = 5
23
17
 
24
18
  def initialize(*args)
25
19
 
26
20
  @reflekt_forked = false
27
21
  @reflekt_clones = []
28
22
 
23
+ # Limit the amount of clones that can be created per instance.
24
+ # A method called 30,000 times doesn't need that many reflections.
25
+ @reflekt_limit = 5
26
+ @reflekt_count = 0
27
+
29
28
  # Override methods.
30
29
  self.class.instance_methods(false).each do |method|
31
30
  self.define_singleton_method(method) do |*args|
32
31
 
33
32
  # When method called in flow.
34
33
  if @reflekt_forked
35
- unless self.class.deflekted?(method)
36
- # Reflekt on method.
37
- @reflekt_clones.each do |clone|
38
- reflekt_action(clone, method, *args)
34
+
35
+ if @reflekt_count < @reflekt_limit
36
+ unless self.class.deflekted?(method)
37
+
38
+ # Reflekt on method.
39
+ @reflekt_clones.each do |clone|
40
+ reflekt_action(clone, method, *args)
41
+ end
42
+
43
+ # Save results.
44
+ @@reflekt_db.write()
45
+
46
+ # Render results.
47
+ @@reflekt_json = File.read("#{@@reflekt_output_path}/db.json")
48
+ template = File.read("#{@@reflekt_path}/web/template.html.erb")
49
+ rendered = ERB.new(template).result(binding)
50
+ File.open("#{@@reflekt_output_path}/index.html", 'w+') do |f|
51
+ f.write rendered
52
+ end
53
+
54
+ # Add JS.
55
+ alpinejs = File.read("#{@@reflekt_path}/web/alpine.js")
56
+ File.open("#{@@reflekt_output_path}/alpine.js", 'w+') do |f|
57
+ f.write alpinejs
58
+ end
59
+
60
+ # Add CSS.
61
+ stylesheet = File.read("#{@@reflekt_path}/web/style.css")
62
+ File.open("#{@@reflekt_output_path}/style.css", 'w+') do |f|
63
+ f.write stylesheet
64
+ end
65
+
39
66
  end
40
- # Save results.
41
- @@db.write()
67
+ @reflekt_count = @reflekt_count + 1
42
68
  end
69
+
43
70
  end
44
71
 
45
72
  # Continue method flow.
@@ -58,7 +85,7 @@ module Reflekt
58
85
 
59
86
  def reflekt_fork()
60
87
 
61
- @@clone_count.times do |clone|
88
+ @@reflekt_clone_count.times do |clone|
62
89
  @reflekt_clones << self.clone
63
90
  end
64
91
 
@@ -68,7 +95,10 @@ module Reflekt
68
95
 
69
96
  def reflekt_action(clone, method, *args)
70
97
 
71
- # Create new arguments.
98
+ class_name = clone.class.to_s
99
+ method_name = method.to_s
100
+
101
+ # Create new arguments that are deviations on inputted type.
72
102
  new_args = []
73
103
  args.each do |arg|
74
104
  case arg
@@ -82,62 +112,64 @@ module Reflekt
82
112
  # Action method with new arguments.
83
113
  begin
84
114
  clone.send(method, *new_args)
115
+
85
116
  # Build reflection.
86
117
  reflection = {
87
118
  "time" => Time.now.to_i,
88
- "class" => clone.class.to_s,
89
- "method" => method.to_s,
90
119
  }
91
- # When error.
120
+ # When fail.
92
121
  rescue StandardError => error
93
122
  reflection["status"] = "error"
94
123
  reflection["error"] = error
95
- # When success.
124
+ # When pass.
96
125
  else
97
- reflection["status"] = "success"
126
+ reflection["status"] = "pass"
98
127
  end
128
+
99
129
  # Save reflection.
100
- @@db.get('reflections')
101
- .push(reflection)
130
+ @@reflekt_db.get("#{class_name}.#{method_name}")
131
+ .push(reflection)
102
132
 
103
133
  end
104
134
 
105
135
  private
106
136
 
107
- # Prepend Klass to the instance's singleton class.
108
137
  def self.prepended(base)
109
- base.singleton_class.prepend(Klass)
138
+ # Prepend class methods to the instance's singleton class.
139
+ base.singleton_class.prepend(SingletonClassMethods)
110
140
 
111
- @@setup ||= setup_klass
141
+ @@reflekt_setup ||= reflekt_setup_class
112
142
  end
113
143
 
114
- # Setup Klass.
115
- def self.setup_klass()
144
+ # Setup class.
145
+ def self.reflekt_setup_class()
116
146
 
117
147
  # Receive configuration from host application.
118
148
  $ENV ||= {}
119
149
  $ENV[:reflekt] ||= $ENV[:reflekt] = {}
120
150
 
151
+ @@reflekt_path = File.dirname(File.realpath(__FILE__))
152
+
121
153
  # Create "reflections" directory in configured path.
122
154
  if $ENV[:reflekt][:output_path]
123
- dir_path = File.join($ENV[:reflekt][:output_path], 'reflections')
155
+ @@reflekt_output_path = File.join($ENV[:reflekt][:output_path], 'reflections')
124
156
  # Create "reflections" directory in current execution path.
125
157
  else
126
- dir_path = File.join(Dir.pwd, 'reflections')
158
+ @@reflekt_output_path = File.join(Dir.pwd, 'reflections')
127
159
  end
128
160
 
129
- unless Dir.exist? dir_path
130
- Dir.mkdir(dir_path)
161
+ unless Dir.exist? @@reflekt_output_path
162
+ Dir.mkdir(@@reflekt_output_path)
131
163
  end
132
164
 
133
165
  # Create database.
134
- @@db = Rowdb.new(dir_path + '/db.json')
135
- @@db.defaults({"reflections" => []})
166
+ @@reflekt_db = Rowdb.new(@@reflekt_output_path + '/db.json')
167
+ @@reflekt_db.defaults({ :reflekt => { :api_version => 1 }}).write()
136
168
 
137
169
  return true
138
170
  end
139
171
 
140
- module Klass
172
+ module SingletonClassMethods
141
173
 
142
174
  @@deflekted_methods = Set.new
143
175
 
@@ -155,6 +187,10 @@ module Reflekt
155
187
  false
156
188
  end
157
189
 
190
+ def reflekt_limit(amount)
191
+ @reflekt_limit = amount
192
+ end
193
+
158
194
  end
159
195
 
160
196
  end
@@ -0,0 +1,8 @@
1
+ /**
2
+ * Minified by jsDelivr using Terser v3.14.1.
3
+ * Original file: /gh/alpinejs/alpine@2.6.0/dist/alpine.js
4
+ *
5
+ * Do NOT use SRI with dynamically generated files! More information: https://www.jsdelivr.com/using-sri-with-dynamic-files
6
+ */
7
+ !function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e=e||self).Alpine=t()}(this,function(){"use strict";function e(e,t,n){return t in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}function t(e,t){var n=Object.keys(e);if(Object.getOwnPropertySymbols){var i=Object.getOwnPropertySymbols(e);t&&(i=i.filter(function(t){return Object.getOwnPropertyDescriptor(e,t).enumerable})),n.push.apply(n,i)}return n}function n(n){for(var i=1;i<arguments.length;i++){var r=null!=arguments[i]?arguments[i]:{};i%2?t(Object(r),!0).forEach(function(t){e(n,t,r[t])}):Object.getOwnPropertyDescriptors?Object.defineProperties(n,Object.getOwnPropertyDescriptors(r)):t(Object(r)).forEach(function(e){Object.defineProperty(n,e,Object.getOwnPropertyDescriptor(r,e))})}return n}function i(e){return Array.from(new Set(e))}function r(){return navigator.userAgent.includes("Node.js")||navigator.userAgent.includes("jsdom")}function s(e,t){"template"!==e.tagName.toLowerCase()?console.warn(`Alpine: [${t}] directive should only be added to <template> tags. See https://github.com/alpinejs/alpine#${t}`):1!==e.content.childElementCount&&console.warn(`Alpine: <template> tag with [${t}] encountered with multiple element roots. Make sure <template> only has a single child node.`)}function o(e){return e.toLowerCase().replace(/-(\w)/g,(e,t)=>t.toUpperCase())}function a(e,t){var n;return function(){var i=this,r=arguments;clearTimeout(n),n=setTimeout(function(){n=null,e.apply(i,r)},t)}}function l(e,t,n={}){return"function"==typeof e?e.call(t):new Function(["$data",...Object.keys(n)],`var __alpine_result; with($data) { __alpine_result = ${e} }; return __alpine_result`)(t,...Object.values(n))}const c=/^x-(on|bind|data|text|html|model|if|for|show|cloak|transition|ref|spread)\b/;function u(e){const t=m(e.name);return c.test(t)}function d(e,t,n){let i=Array.from(e.attributes).filter(u).map(f),r=i.filter(e=>"spread"===e.type)[0];if(r){let e=l(r.expression,t.$data);i=i.concat(Object.entries(e).map(([e,t])=>f({name:e,value:t})))}return n?i.filter(e=>e.type===n):function(e){let t=["bind","model","show","catch-all"];return e.sort((e,n)=>{let i=-1===t.indexOf(e.type)?"catch-all":e.type,r=-1===t.indexOf(n.type)?"catch-all":n.type;return t.indexOf(i)-t.indexOf(r)})}(i)}function f({name:e,value:t}){const n=m(e),i=n.match(c),r=n.match(/:([a-zA-Z0-9\-:]+)/),s=n.match(/\.[^.\]]+(?=[^\]]*$)/g)||[];return{type:i?i[1]:null,value:r?r[1]:null,modifiers:s.map(e=>e.replace(".","")),expression:t}}function m(e){return e.startsWith("@")?e.replace("@","x-on:"):e.startsWith(":")?e.replace(":","x-bind:"):e}function p(e,t=Boolean){return e.split(" ").filter(t)}const h="in",v="out";function b(e,t,n,i=!1){if(i)return t();if(e.__x_transition&&e.__x_transition.type===h)return;const r=d(e,n,"transition"),s=d(e,n,"show")[0];if(s&&s.modifiers.includes("transition")){let n=s.modifiers;if(n.includes("out")&&!n.includes("in"))return t();const i=n.includes("in")&&n.includes("out");(function(e,t,n){const i={duration:g(t,"duration",150),origin:g(t,"origin","center"),first:{opacity:0,scale:g(t,"scale",95)},second:{opacity:1,scale:100}};x(e,t,n,()=>{},i,h)})(e,n=i?n.filter((e,t)=>t<n.indexOf("out")):n,t)}else r.some(e=>["enter","enter-start","enter-end"].includes(e.value))?function(e,t,n,i){let r=n=>"function"==typeof n?t.evaluateReturnExpression(e,n):n;const s=p(r((n.find(e=>"enter"===e.value)||{expression:""}).expression)),o=p(r((n.find(e=>"enter-start"===e.value)||{expression:""}).expression)),a=p(r((n.find(e=>"enter-end"===e.value)||{expression:""}).expression));_(e,s,o,a,i,()=>{},h)}(e,n,r,t):t()}function y(e,t,n,i=!1){if(i)return t();if(e.__x_transition&&e.__x_transition.type===v)return;const r=d(e,n,"transition"),s=d(e,n,"show")[0];if(s&&s.modifiers.includes("transition")){let n=s.modifiers;if(n.includes("in")&&!n.includes("out"))return t();const i=n.includes("in")&&n.includes("out");(function(e,t,n,i){const r={duration:n?g(t,"duration",150):g(t,"duration",150)/2,origin:g(t,"origin","center"),first:{opacity:1,scale:100},second:{opacity:0,scale:g(t,"scale",95)}};x(e,t,()=>{},i,r,v)})(e,n=i?n.filter((e,t)=>t>n.indexOf("out")):n,i,t)}else r.some(e=>["leave","leave-start","leave-end"].includes(e.value))?function(e,t,n,i){const r=p((n.find(e=>"leave"===e.value)||{expression:""}).expression),s=p((n.find(e=>"leave-start"===e.value)||{expression:""}).expression),o=p((n.find(e=>"leave-end"===e.value)||{expression:""}).expression);_(e,r,s,o,()=>{},i,v)}(e,0,r,t):t()}function g(e,t,n){if(-1===e.indexOf(t))return n;const i=e[e.indexOf(t)+1];if(!i)return n;if("scale"===t&&!E(i))return n;if("duration"===t){let e=i.match(/([0-9]+)ms/);if(e)return e[1]}return"origin"===t&&["top","right","left","center","bottom"].includes(e[e.indexOf(t)+2])?[i,e[e.indexOf(t)+2]].join(" "):i}function x(e,t,n,i,r,s){e.__x_transition&&(cancelAnimationFrame(e.__x_transition.nextFrame),e.__x_transition.callback&&e.__x_transition.callback());const o=e.style.opacity,a=e.style.transform,l=e.style.transformOrigin,c=!t.includes("opacity")&&!t.includes("scale"),u=c||t.includes("opacity"),d=c||t.includes("scale"),f={start(){u&&(e.style.opacity=r.first.opacity),d&&(e.style.transform=`scale(${r.first.scale/100})`)},during(){d&&(e.style.transformOrigin=r.origin),e.style.transitionProperty=[u?"opacity":"",d?"transform":""].join(" ").trim(),e.style.transitionDuration=`${r.duration/1e3}s`,e.style.transitionTimingFunction="cubic-bezier(0.4, 0.0, 0.2, 1)"},show(){n()},end(){u&&(e.style.opacity=r.second.opacity),d&&(e.style.transform=`scale(${r.second.scale/100})`)},hide(){i()},cleanup(){u&&(e.style.opacity=o),d&&(e.style.transform=a),d&&(e.style.transformOrigin=l),e.style.transitionProperty=null,e.style.transitionDuration=null,e.style.transitionTimingFunction=null}};w(e,f,s)}function _(e,t,n,i,r,s,o){e.__x_transition&&(cancelAnimationFrame(e.__x_transition.nextFrame),e.__x_transition.callback&&e.__x_transition.callback());const a=e.__x_original_classes||[],l={start(){e.classList.add(...n)},during(){e.classList.add(...t)},show(){r()},end(){e.classList.remove(...n.filter(e=>!a.includes(e))),e.classList.add(...i)},hide(){s()},cleanup(){e.classList.remove(...t.filter(e=>!a.includes(e))),e.classList.remove(...i.filter(e=>!a.includes(e)))}};w(e,l,o)}function w(e,t,n){e.__x_transition={type:n,callback:O(()=>{t.hide(),e.isConnected&&t.cleanup(),delete e.__x_transition}),nextFrame:null},t.start(),t.during(),e.__x_transition.nextFrame=requestAnimationFrame(()=>{let n=1e3*Number(getComputedStyle(e).transitionDuration.replace(/,.*/,"").replace("s",""));0===n&&(n=1e3*Number(getComputedStyle(e).animationDuration.replace("s",""))),t.show(),e.__x_transition.nextFrame=requestAnimationFrame(()=>{t.end(),setTimeout(e.__x_transition.callback,n)})})}function E(e){return!isNaN(e)}function O(e){let t=!1;return function(){t||(t=!0,e.apply(this,arguments))}}function k(e,t,i,r,o){s(t,"x-for");let a=A("function"==typeof i?e.evaluateReturnExpression(t,i):i),l=function(e,t,n,i){let r=d(t,e,"if")[0];if(r&&!e.evaluateReturnExpression(t,r.expression))return[];return e.evaluateReturnExpression(t,n.items,i)}(e,t,a,o),c=t;l.forEach((i,s)=>{let u=function(e,t,i,r,s){let o=s?n({},s):{};o[e.item]=t,e.index&&(o[e.index]=i);e.collection&&(o[e.collection]=r);return o}(a,i,s,l,o()),f=function(e,t,n,i){let r=d(t,e,"bind").filter(e=>"key"===e.value)[0];return r?e.evaluateReturnExpression(t,r.expression,()=>i):n}(e,t,s,u),m=function(e,t){if(!e)return;if(e.__x_for_key===t)return e;let n=e;for(;n;){if(n.__x_for_key===t)return n.parentElement.insertBefore(n,e);n=!(!n.nextElementSibling||void 0===n.nextElementSibling.__x_for_key)&&n.nextElementSibling}}(c.nextElementSibling,f);m?(delete m.__x_for_key,m.__x_for=u,e.updateElements(m,()=>m.__x_for)):(b(m=function(e,t){let n=document.importNode(e.content,!0);return t.parentElement.insertBefore(n,t.nextElementSibling),t.nextElementSibling}(t,c),()=>{},e,r),m.__x_for=u,e.initializeElements(m,()=>m.__x_for)),(c=m).__x_for_key=f}),function(e,t){var n=!(!e.nextElementSibling||void 0===e.nextElementSibling.__x_for_key)&&e.nextElementSibling;for(;n;){let e=n,i=n.nextElementSibling;y(n,()=>{e.remove()},t),n=!(!i||void 0===i.__x_for_key)&&i}}(c,e)}function A(e){let t=/,([^,\}\]]*)(?:,([^,\}\]]*))?$/,n=e.match(/([\s\S]*?)\s+(?:in|of)\s+([\s\S]*)/);if(!n)return;let i={};i.items=n[2].trim();let r=n[1].trim().replace(/^\(|\)$/g,""),s=r.match(t);return s?(i.item=r.replace(t,"").trim(),i.index=s[1].trim(),s[2]&&(i.collection=s[2].trim())):i.item=r,i}function S(e,t,n,r,s,a,l){var c=e.evaluateReturnExpression(t,r,s);if("value"===n){if(me.ignoreFocusedForValueBinding&&document.activeElement.isSameNode(t))return;if(void 0===c&&r.match(/\./)&&(c=""),"radio"===t.type)void 0===t.attributes.value&&"bind"===a?t.value=c:"bind"!==a&&(t.checked=t.value==c);else if("checkbox"===t.type)"string"==typeof c&&"bind"===a?t.value=c:"bind"!==a&&(Array.isArray(c)?t.checked=c.some(e=>e==t.value):t.checked=!!c);else if("SELECT"===t.tagName)!function(e,t){const n=[].concat(t).map(e=>e+"");Array.from(e.options).forEach(e=>{e.selected=n.includes(e.value||e.text)})}(t,c);else{if(t.value===c)return;t.value=c}}else if("class"===n)if(Array.isArray(c)){const e=t.__x_original_classes||[];t.setAttribute("class",i(e.concat(c)).join(" "))}else if("object"==typeof c){Object.keys(c).sort((e,t)=>c[e]-c[t]).forEach(e=>{c[e]?p(e).forEach(e=>t.classList.add(e)):p(e).forEach(e=>t.classList.remove(e))})}else{const e=t.__x_original_classes||[],n=p(c);t.setAttribute("class",i(e.concat(n)).join(" "))}else n=l.includes("camel")?o(n):n,[null,void 0,!1].includes(c)?t.removeAttribute(n):!function(e){return["disabled","checked","required","readonly","hidden","open","selected","autofocus","itemscope","multiple","novalidate","allowfullscreen","allowpaymentrequest","formnovalidate","autoplay","controls","loop","muted","playsinline","default","ismap","reversed","async","defer","nomodule"].includes(e)}(n)?$(t,n,c):$(t,n,n)}function $(e,t,n){e.getAttribute(t)!=n&&e.setAttribute(t,n)}function P(e,t,n,i,r,s={}){const l={passive:i.includes("passive")};if(i.includes("camel")&&(n=o(n)),i.includes("away")){let o=a=>{t.contains(a.target)||t.offsetWidth<1&&t.offsetHeight<1||(C(e,r,a,s),i.includes("once")&&document.removeEventListener(n,o,l))};document.addEventListener(n,o,l)}else{let o=i.includes("window")?window:i.includes("document")?document:t,c=a=>{if(o!==window&&o!==document||document.body.contains(t)){if(!(function(e){return["keydown","keyup"].includes(e)}(n)&&function(e,t){let n=t.filter(e=>!["window","document","prevent","stop"].includes(e));if(n.includes("debounce")){let e=n.indexOf("debounce");n.splice(e,E((n[e+1]||"invalid-wait").split("ms")[0])?2:1)}if(0===n.length)return!1;if(1===n.length&&n[0]===D(e.key))return!1;const i=["ctrl","shift","alt","meta","cmd","super"].filter(e=>n.includes(e));if(n=n.filter(e=>!i.includes(e)),i.length>0){const t=i.filter(t=>("cmd"!==t&&"super"!==t||(t="meta"),e[`${t}Key`]));if(t.length===i.length&&n[0]===D(e.key))return!1}return!0}(a,i)||(i.includes("prevent")&&a.preventDefault(),i.includes("stop")&&a.stopPropagation(),i.includes("self")&&a.target!==t))){C(e,r,a,s).then(e=>{!1===e?a.preventDefault():i.includes("once")&&o.removeEventListener(n,c,l)})}}else o.removeEventListener(n,c,l)};if(i.includes("debounce")){let e=i[i.indexOf("debounce")+1]||"invalid-wait",t=E(e.split("ms")[0])?Number(e.split("ms")[0]):250;c=a(c,t)}o.addEventListener(n,c,l)}}function C(e,t,i,r){return e.evaluateCommandExpression(i.target,t,()=>n(n({},r()),{},{$event:i}))}function D(e){switch(e){case"/":return"slash";case" ":case"Spacebar":return"space";default:return e&&e.replace(/([a-z])([A-Z])/g,"$1-$2").replace(/[_\s]/,"-").toLowerCase()}}function j(e,t,n){return"radio"===e.type&&(e.hasAttribute("name")||e.setAttribute("name",n)),(n,i)=>{if(n instanceof CustomEvent&&n.detail)return n.detail;if("checkbox"===e.type){if(Array.isArray(i)){const e=t.includes("number")?T(n.target.value):n.target.value;return n.target.checked?i.concat([e]):i.filter(t=>t!==e)}return n.target.checked}if("select"===e.tagName.toLowerCase()&&e.multiple)return t.includes("number")?Array.from(n.target.selectedOptions).map(e=>{return T(e.value||e.text)}):Array.from(n.target.selectedOptions).map(e=>e.value||e.text);{const e=n.target.value;return t.includes("number")?T(e):t.includes("trim")?e.trim():e}}}function T(e){const t=e?parseFloat(e):null;return E(t)?t:e}const{isArray:L}=Array,{getPrototypeOf:N,create:z,defineProperty:R,defineProperties:F,isExtensible:I,getOwnPropertyDescriptor:M,getOwnPropertyNames:B,getOwnPropertySymbols:U,preventExtensions:q,hasOwnProperty:W}=Object,{push:K,concat:G,map:H}=Array.prototype;function V(e){return void 0===e}function Z(e){return"function"==typeof e}const J=new WeakMap;function Q(e,t){J.set(e,t)}const X=e=>J.get(e)||e;function Y(e,t){return e.valueIsObservable(t)?e.getProxy(t):t}function ee(e,t,n){G.call(B(n),U(n)).forEach(i=>{let r=M(n,i);r.configurable||(r=ue(e,r,Y)),R(t,i,r)}),q(t)}class te{constructor(e,t){this.originalTarget=t,this.membrane=e}get(e,t){const{originalTarget:n,membrane:i}=this,r=n[t],{valueObserved:s}=i;return s(n,t),i.getProxy(r)}set(e,t,n){const{originalTarget:i,membrane:{valueMutated:r}}=this;return i[t]!==n?(i[t]=n,r(i,t)):"length"===t&&L(i)&&r(i,t),!0}deleteProperty(e,t){const{originalTarget:n,membrane:{valueMutated:i}}=this;return delete n[t],i(n,t),!0}apply(e,t,n){}construct(e,t,n){}has(e,t){const{originalTarget:n,membrane:{valueObserved:i}}=this;return i(n,t),t in n}ownKeys(e){const{originalTarget:t}=this;return G.call(B(t),U(t))}isExtensible(e){const t=I(e);if(!t)return t;const{originalTarget:n,membrane:i}=this,r=I(n);return r||ee(i,e,n),r}setPrototypeOf(e,t){}getPrototypeOf(e){const{originalTarget:t}=this;return N(t)}getOwnPropertyDescriptor(e,t){const{originalTarget:n,membrane:i}=this,{valueObserved:r}=this.membrane;r(n,t);let s=M(n,t);if(V(s))return s;const o=M(e,t);return V(o)?((s=ue(i,s,Y)).configurable||R(e,t,s),s):o}preventExtensions(e){const{originalTarget:t,membrane:n}=this;return ee(n,e,t),q(t),!0}defineProperty(e,t,n){const{originalTarget:i,membrane:r}=this,{valueMutated:s}=r,{configurable:o}=n;if(W.call(n,"writable")&&!W.call(n,"value")){const e=M(i,t);n.value=e.value}return R(i,t,function(e){return W.call(e,"value")&&(e.value=X(e.value)),e}(n)),!1===o&&R(e,t,ue(r,n,Y)),s(i,t),!0}}function ne(e,t){return e.valueIsObservable(t)?e.getReadOnlyProxy(t):t}class ie{constructor(e,t){this.originalTarget=t,this.membrane=e}get(e,t){const{membrane:n,originalTarget:i}=this,r=i[t],{valueObserved:s}=n;return s(i,t),n.getReadOnlyProxy(r)}set(e,t,n){return!1}deleteProperty(e,t){return!1}apply(e,t,n){}construct(e,t,n){}has(e,t){const{originalTarget:n,membrane:{valueObserved:i}}=this;return i(n,t),t in n}ownKeys(e){const{originalTarget:t}=this;return G.call(B(t),U(t))}setPrototypeOf(e,t){}getOwnPropertyDescriptor(e,t){const{originalTarget:n,membrane:i}=this,{valueObserved:r}=i;r(n,t);let s=M(n,t);if(V(s))return s;const o=M(e,t);return V(o)?(s=ue(i,s,ne),W.call(s,"set")&&(s.set=void 0),s.configurable||R(e,t,s),s):o}preventExtensions(e){return!1}defineProperty(e,t,n){return!1}}function re(e){let t=void 0;return L(e)?t=[]:"object"==typeof e&&(t={}),t}const se=Object.prototype;function oe(e){if(null===e)return!1;if("object"!=typeof e)return!1;if(L(e))return!0;const t=N(e);return t===se||null===t||null===N(t)}const ae=(e,t)=>{},le=(e,t)=>{},ce=e=>e;function ue(e,t,n){const{set:i,get:r}=t;return W.call(t,"value")?t.value=n(e,t.value):(V(r)||(t.get=function(){return n(e,r.call(X(this)))}),V(i)||(t.set=function(t){i.call(X(this),e.unwrapProxy(t))})),t}class de{constructor(e){if(this.valueDistortion=ce,this.valueMutated=le,this.valueObserved=ae,this.valueIsObservable=oe,this.objectGraph=new WeakMap,!V(e)){const{valueDistortion:t,valueMutated:n,valueObserved:i,valueIsObservable:r}=e;this.valueDistortion=Z(t)?t:ce,this.valueMutated=Z(n)?n:le,this.valueObserved=Z(i)?i:ae,this.valueIsObservable=Z(r)?r:oe}}getProxy(e){const t=X(e),n=this.valueDistortion(t);if(this.valueIsObservable(n)){const i=this.getReactiveState(t,n);return i.readOnly===e?e:i.reactive}return n}getReadOnlyProxy(e){e=X(e);const t=this.valueDistortion(e);return this.valueIsObservable(t)?this.getReactiveState(e,t).readOnly:t}unwrapProxy(e){return X(e)}getReactiveState(e,t){const{objectGraph:n}=this;let i=n.get(t);if(i)return i;const r=this;return i={get reactive(){const n=new te(r,t),i=new Proxy(re(t),n);return Q(i,e),R(this,"reactive",{value:i}),i},get readOnly(){const n=new ie(r,t),i=new Proxy(re(t),n);return Q(i,e),R(this,"readOnly",{value:i}),i}},n.set(t,i),i}}class fe{constructor(e,t=null){this.$el=e;const n=this.$el.getAttribute("x-data"),i=""===n?"{}":n,r=this.$el.getAttribute("x-init");let s={$el:this.$el},o=t?t.$el:this.$el;Object.entries(me.magicProperties).forEach(([e,t])=>{Object.defineProperty(s,`$${e}`,{get:function(){return t(o)}})}),this.unobservedData=t?t.getUnobservedData():l(i,s);let{membrane:a,data:c}=this.wrapDataInObservable(this.unobservedData);var u;this.$data=c,this.membrane=a,this.unobservedData.$el=this.$el,this.unobservedData.$refs=this.getRefsProxy(),this.nextTickStack=[],this.unobservedData.$nextTick=(e=>{this.nextTickStack.push(e)}),this.watchers={},this.unobservedData.$watch=((e,t)=>{this.watchers[e]||(this.watchers[e]=[]),this.watchers[e].push(t)}),Object.entries(me.magicProperties).forEach(([e,t])=>{Object.defineProperty(this.unobservedData,`$${e}`,{get:function(){return t(o)}})}),this.showDirectiveStack=[],this.showDirectiveLastElement,t||me.onBeforeComponentInitializeds.forEach(e=>e(this)),r&&!t&&(this.pauseReactivity=!0,u=this.evaluateReturnExpression(this.$el,r),this.pauseReactivity=!1),this.initializeElements(this.$el),this.listenForNewElementsToInitialize(),"function"==typeof u&&u.call(this.$data),t||setTimeout(()=>{me.onComponentInitializeds.forEach(e=>e(this))},0)}getUnobservedData(){return function(e,t){let n=e.unwrapProxy(t),i={};return Object.keys(n).forEach(e=>{["$el","$refs","$nextTick","$watch"].includes(e)||(i[e]=n[e])}),i}(this.membrane,this.$data)}wrapDataInObservable(e){var t=this;let n=a(function(){t.updateElements(t.$el)},0);return function(e,t){let n=new de({valueMutated(e,n){t(e,n)}});return{data:n.getProxy(e),membrane:n}}(e,(e,i)=>{t.watchers[i]?t.watchers[i].forEach(t=>t(e[i])):Object.keys(t.watchers).filter(e=>e.includes(".")).forEach(n=>{let r=n.split(".");i===r[r.length-1]&&r.reduce((r,s)=>(Object.is(e,r)&&t.watchers[n].forEach(t=>t(e[i])),r[s]),t.getUnobservedData())}),t.pauseReactivity||n()})}walkAndSkipNestedComponents(e,t,n=(()=>{})){!function e(t,n){if(!1===n(t))return;let i=t.firstElementChild;for(;i;)e(i,n),i=i.nextElementSibling}(e,e=>e.hasAttribute("x-data")&&!e.isSameNode(this.$el)?(e.__x||n(e),!1):t(e))}initializeElements(e,t=(()=>{})){this.walkAndSkipNestedComponents(e,e=>void 0===e.__x_for_key&&(void 0===e.__x_inserted_me&&void this.initializeElement(e,t)),e=>{e.__x=new fe(e)}),this.executeAndClearRemainingShowDirectiveStack(),this.executeAndClearNextTickStack(e)}initializeElement(e,t){e.hasAttribute("class")&&d(e,this).length>0&&(e.__x_original_classes=p(e.getAttribute("class"))),this.registerListeners(e,t),this.resolveBoundAttributes(e,!0,t)}updateElements(e,t=(()=>{})){this.walkAndSkipNestedComponents(e,e=>{if(void 0!==e.__x_for_key&&!e.isSameNode(this.$el))return!1;this.updateElement(e,t)},e=>{e.__x=new fe(e)}),this.executeAndClearRemainingShowDirectiveStack(),this.executeAndClearNextTickStack(e)}executeAndClearNextTickStack(e){e===this.$el&&this.nextTickStack.length>0&&requestAnimationFrame(()=>{for(;this.nextTickStack.length>0;)this.nextTickStack.shift()()})}executeAndClearRemainingShowDirectiveStack(){this.showDirectiveStack.reverse().map(e=>new Promise(t=>{e(e=>{t(e)})})).reduce((e,t)=>e.then(()=>t.then(e=>e())),Promise.resolve(()=>{})),this.showDirectiveStack=[],this.showDirectiveLastElement=void 0}updateElement(e,t){this.resolveBoundAttributes(e,!1,t)}registerListeners(e,t){d(e,this).forEach(({type:i,value:r,modifiers:s,expression:o})=>{switch(i){case"on":P(this,e,r,s,o,t);break;case"model":!function(e,t,i,r,s){var o="select"===t.tagName.toLowerCase()||["checkbox","radio"].includes(t.type)||i.includes("lazy")?"change":"input";P(e,t,o,i,`${r} = rightSideOfExpression($event, ${r})`,()=>n(n({},s()),{},{rightSideOfExpression:j(t,i,r)}))}(this,e,s,o,t)}})}resolveBoundAttributes(e,t=!1,n){let i=d(e,this);i.forEach(({type:r,value:o,modifiers:a,expression:l})=>{switch(r){case"model":S(this,e,"value",l,n,r,a);break;case"bind":if("template"===e.tagName.toLowerCase()&&"key"===o)return;S(this,e,o,l,n,r,a);break;case"text":var c=this.evaluateReturnExpression(e,l,n);!function(e,t,n){void 0===t&&n.match(/\./)&&(t=""),e.innerText=t}(e,c,l);break;case"html":!function(e,t,n,i){t.innerHTML=e.evaluateReturnExpression(t,n,i)}(this,e,l,n);break;case"show":c=this.evaluateReturnExpression(e,l,n);!function(e,t,n,i,r=!1){const s=()=>{t.style.display="none"},o=()=>{1===t.style.length&&"none"===t.style.display?t.removeAttribute("style"):t.style.removeProperty("display")};if(!0===r)return void(n?o():s());const a=i=>{n?(("none"===t.style.display||t.__x_transition)&&b(t,()=>{o()},e),i(()=>{})):"none"!==t.style.display?y(t,()=>{i(()=>{s()})},e):i(()=>{})};i.includes("immediate")?a(e=>e()):(e.showDirectiveLastElement&&!e.showDirectiveLastElement.contains(t)&&e.executeAndClearRemainingShowDirectiveStack(),e.showDirectiveStack.push(a),e.showDirectiveLastElement=t)}(this,e,c,a,t);break;case"if":if(i.some(e=>"for"===e.type))return;c=this.evaluateReturnExpression(e,l,n);!function(e,t,n,i,r){s(t,"x-if");const o=t.nextElementSibling&&!0===t.nextElementSibling.__x_inserted_me;if(!n||o&&!t.__x_transition)!n&&o&&y(t.nextElementSibling,()=>{t.nextElementSibling.remove()},e,i);else{const n=document.importNode(t.content,!0);t.parentElement.insertBefore(n,t.nextElementSibling),b(t.nextElementSibling,()=>{},e,i),e.initializeElements(t.nextElementSibling,r),t.nextElementSibling.__x_inserted_me=!0}}(this,e,c,t,n);break;case"for":k(this,e,l,t,n);break;case"cloak":e.removeAttribute("x-cloak")}})}evaluateReturnExpression(e,t,i=(()=>{})){return l(t,this.$data,n(n({},i()),{},{$dispatch:this.getDispatchFunction(e)}))}evaluateCommandExpression(e,t,i=(()=>{})){return function(e,t,n={}){if("function"==typeof e)return Promise.resolve(e.call(t,n.$event));let i=Function;if(i=Object.getPrototypeOf(async function(){}).constructor,Object.keys(t).includes(e)){let i=new Function(["dataContext",...Object.keys(n)],`with(dataContext) { return ${e} }`)(t,...Object.values(n));return"function"==typeof i?Promise.resolve(i.call(t,n.$event)):Promise.resolve()}return Promise.resolve(new i(["dataContext",...Object.keys(n)],`with(dataContext) { ${e} }`)(t,...Object.values(n)))}(t,this.$data,n(n({},i()),{},{$dispatch:this.getDispatchFunction(e)}))}getDispatchFunction(e){return(t,n={})=>{e.dispatchEvent(new CustomEvent(t,{detail:n,bubbles:!0}))}}listenForNewElementsToInitialize(){const e=this.$el;new MutationObserver(e=>{for(let t=0;t<e.length;t++){const n=e[t].target.closest("[x-data]");if(n&&n.isSameNode(this.$el)){if("attributes"===e[t].type&&"x-data"===e[t].attributeName){const n=l(e[t].target.getAttribute("x-data")||"{}",{$el:this.$el});Object.keys(n).forEach(e=>{this.$data[e]!==n[e]&&(this.$data[e]=n[e])})}e[t].addedNodes.length>0&&e[t].addedNodes.forEach(e=>{1!==e.nodeType||e.__x_inserted_me||(!e.matches("[x-data]")||e.__x?this.initializeElements(e):e.__x=new fe(e))})}}}).observe(e,{childList:!0,attributes:!0,subtree:!0})}getRefsProxy(){var e=this;return new Proxy({},{get(t,n){return"$isAlpineProxy"===n||(e.walkAndSkipNestedComponents(e.$el,e=>{e.hasAttribute("x-ref")&&e.getAttribute("x-ref")===n&&(i=e)}),i);var i}})}}const me={version:"2.6.0",pauseMutationObserver:!1,magicProperties:{},onComponentInitializeds:[],onBeforeComponentInitializeds:[],ignoreFocusedForValueBinding:!1,start:async function(){r()||await new Promise(e=>{"loading"==document.readyState?document.addEventListener("DOMContentLoaded",e):e()}),this.discoverComponents(e=>{this.initializeComponent(e)}),document.addEventListener("turbolinks:load",()=>{this.discoverUninitializedComponents(e=>{this.initializeComponent(e)})}),this.listenForNewUninitializedComponentsAtRunTime(e=>{this.initializeComponent(e)})},discoverComponents:function(e){document.querySelectorAll("[x-data]").forEach(t=>{e(t)})},discoverUninitializedComponents:function(e,t=null){const n=(t||document).querySelectorAll("[x-data]");Array.from(n).filter(e=>void 0===e.__x).forEach(t=>{e(t)})},listenForNewUninitializedComponentsAtRunTime:function(e){const t=document.querySelector("body");new MutationObserver(e=>{if(!this.pauseMutationObserver)for(let t=0;t<e.length;t++)e[t].addedNodes.length>0&&e[t].addedNodes.forEach(e=>{1===e.nodeType&&(e.parentElement&&e.parentElement.closest("[x-data]")||this.discoverUninitializedComponents(e=>{this.initializeComponent(e)},e.parentElement))})}).observe(t,{childList:!0,attributes:!0,subtree:!0})},initializeComponent:function(e){if(!e.__x)try{e.__x=new fe(e)}catch(e){setTimeout(()=>{throw e},0)}},clone:function(e,t){t.__x||(t.__x=new fe(t,e))},addMagicProperty:function(e,t){this.magicProperties[e]=t},onComponentInitialized:function(e){this.onComponentInitializeds.push(e)},onBeforeComponentInitialized:function(e){this.onBeforeComponentInitializeds.push(e)}};return r()||(window.Alpine=me,window.deferLoadingAlpine?window.deferLoadingAlpine(function(){window.Alpine.start()}):window.Alpine.start()),me});
8
+ //# sourceMappingURL=/sm/54d8acf4bec59c2ac38179fad55c741f03c418f9ea483b114454c0827631f4ba.map
@@ -0,0 +1,76 @@
1
+ body {
2
+ padding: 0.5rem;
3
+ background: #C9D2E6;
4
+ font-family: 'Roboto', sans-serif;
5
+ }
6
+
7
+ .container {
8
+ margin: 0 auto;
9
+ max-width: 800px;
10
+ padding: 2rem;
11
+ background: white;
12
+ }
13
+
14
+ #header {
15
+
16
+ }
17
+
18
+ #logo {
19
+ display: block;
20
+ margin: 0 auto;
21
+ max-width: 100px;
22
+ }
23
+
24
+ ul.panels,
25
+ ul.reflections {
26
+ padding-left: 0;
27
+ }
28
+
29
+ li.panel {
30
+ list-style: none;
31
+ padding: 1rem;
32
+ border: 5px solid #dadcdc;
33
+ }
34
+
35
+ /* Reflection. */
36
+ .reflection {
37
+ display: flex;
38
+ align-items: center;
39
+ flex-direction: row;
40
+ color: white;
41
+ background: #A9B6D2;
42
+ }
43
+ .reflection.class {
44
+ padding: 2rem;
45
+ margin-bottom: 1rem;
46
+ }
47
+ .reflection.class h2 {
48
+ margin: 0;
49
+ }
50
+
51
+ .reflection.method {
52
+ padding: 2rem;
53
+ margin-left: 1rem;
54
+ margin-bottom: 1rem;
55
+ }
56
+
57
+ /* Stats. */
58
+ .stats {
59
+ margin-left: auto;
60
+ }
61
+ .stat {
62
+ color: #efefef;
63
+ font-size: 3.5rem;
64
+ font-family: 'Merriweather', serif;
65
+ }
66
+ .method .stat {
67
+ font-size: 2.5rem;
68
+ }
69
+
70
+ /* State. */
71
+ .reflection.pass {
72
+ background: #008C32;
73
+ }
74
+ .reflection.fail {
75
+ background: #D04700;
76
+ }
@@ -0,0 +1,133 @@
1
+ <!DOCTYPE html>
2
+ <html>
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <title>Reflekt</title>
6
+ <meta name="description" content="">
7
+ <meta name="author" content="">
8
+ <meta name="viewport" content="width=device-width, initial-scale=1">
9
+ <link rel="stylesheet" href="style.css">
10
+ <link rel="shortcut icon" href="">
11
+ <link href="https://fonts.googleapis.com/css2?family=Roboto:wght@300;400;700&display=swap" rel="stylesheet">
12
+ <link href="https://fonts.googleapis.com/css2?family=Merriweather&display=swap" rel="stylesheet">
13
+ </head>
14
+ <body>
15
+
16
+ <script>
17
+
18
+ function getReflections() {
19
+
20
+ var reflections = JSON.parse(<%= @@reflekt_json %>);
21
+ console.log(reflections);
22
+ var results = {};
23
+
24
+ if ('reflekt' in reflections) {
25
+ delete(reflections.reflekt);
26
+ }
27
+
28
+ // Classes.
29
+ for ([class_id, class_value] of Object.entries(reflections)) {
30
+
31
+ // Class pass rate.
32
+ results[class_id] = {
33
+ 'stats': {
34
+ 'pass_rate': undefined,
35
+ 'test_count': 0,
36
+ 'pass_count': 0
37
+ },
38
+ 'methods': {}
39
+ };
40
+
41
+ // Methods.
42
+ for ([method_id, method] of Object.entries(class_value)) {
43
+
44
+ // Method pass rate.
45
+ var pass_count = method.reduce(function(obj, v) {
46
+ obj[v.status] = (obj[v.status] || 0) + 1;
47
+ return obj;
48
+ }, {});
49
+
50
+ var pass_rate = (pass_count['pass'] / method.length) * 100;
51
+ results[class_id]['methods'][method_id] = {
52
+ 'stats': {
53
+ 'pass_rate': pass_rate,
54
+ 'test_count': method.length,
55
+ 'pass_count': pass_count['pass']
56
+ }
57
+ };
58
+ if (pass_rate == 100) {
59
+ results[class_id]['methods'][method_id]['status'] = 'pass';
60
+ }
61
+ else if (pass_rate < 100) {
62
+ results[class_id]['methods'][method_id]['status'] = 'fail';
63
+ }
64
+
65
+ // Class pass rate.
66
+ results[class_id]['stats']['test_count'] += method.length;
67
+ results[class_id]['stats']['pass_count'] += pass_count['pass'];
68
+
69
+ }
70
+
71
+ // Class pass rate.
72
+ var class_stats = results[class_id]['stats'];
73
+ var pass_rate = (class_stats['pass_count'] / class_stats['test_count']) * 100;
74
+ class_stats['pass_rate'] = pass_rate;
75
+ if (pass_rate == 100) {
76
+ results[class_id]['status'] = 'pass';
77
+ }
78
+ else if (pass_rate < 100) {
79
+ results[class_id]['status'] = 'fail';
80
+ }
81
+ }
82
+
83
+ return { refs: results };
84
+ }
85
+
86
+ </script>
87
+
88
+ <div class="container" x-data="getReflections()">
89
+
90
+ <div id="header">
91
+ <svg id="logo" enable-background="new 0 0 500 500" viewBox="0 0 500 500" xmlns="http://www.w3.org/2000/svg">
92
+ <path d="m307.5 80.5h-115l-57.5 205h230z" fill="#0047d0"/>
93
+ <path d="m178 76.5-53.1-44-117.9 139 116 112z" fill="#d04800"/>
94
+ <path d="m190.4 467.5h115l57.5-168h-229z" fill="#0047d0" opacity=".7"/>
95
+ <path d="m177 467.5-81-85-92-197 115 113z" fill="#d04800" opacity=".7"/>
96
+ <g fill="#008c33"><path d="m322 76.5 53.1-44 118 139-116 112z"/><path d="m320 467.5 84-85 92-197-117 113z" opacity=".7"/></g>
97
+ </svg>
98
+ </div>
99
+
100
+ <ul class="panels">
101
+ <template x-for="[class_id, klass] in Object.entries(getReflections()['refs'])" :key="class_id">
102
+
103
+ <li class="panel">
104
+
105
+ <div class="reflection class" x-bind:class="` ${ klass.status } `">
106
+ <h2 x-text="` ${class_id}() `"></h2>
107
+ <div class="stats">
108
+ <div class="stat" x-text="` ${klass.stats.pass_rate}% `"></div>
109
+ </div>
110
+ </div>
111
+
112
+ <ul class="reflections methods">
113
+ <template x-for="[method_id, method] in Object.entries(klass['methods'])" :key="method_id">
114
+ <li class="reflection method" x-bind:class="` ${ method.status } `">
115
+ <h3 x-text="` ${method_id}() `"></h3>
116
+ <div class="stats">
117
+ <div class="stat" x-text="` ${method.stats.pass_rate}% `"></div>
118
+ </div>
119
+ </li>
120
+ </template>
121
+ </ul>
122
+
123
+ </li>
124
+ </template>
125
+
126
+ </ul>
127
+
128
+ </div>
129
+
130
+ <script src="alpine.js"></script>
131
+
132
+ </body>
133
+ </html>
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: reflekt
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.7.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Maedi Prichard
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-18 00:00:00.000000000 Z
11
+ date: 2020-07-22 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rowdb
@@ -24,13 +24,16 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
- description: Reflective testing that's completely automated.
27
+ description: Testing that's completely automated.
28
28
  email: maediprichard@gmailcom
29
29
  executables: []
30
30
  extensions: []
31
31
  extra_rdoc_files: []
32
32
  files:
33
33
  - lib/reflekt.rb
34
+ - lib/web/alpine.js
35
+ - lib/web/style.css
36
+ - lib/web/template.html.erb
34
37
  homepage: https://github.com/maedi/reflekt
35
38
  licenses:
36
39
  - MPL-2.0
@@ -53,5 +56,5 @@ requirements: []
53
56
  rubygems_version: 3.0.2
54
57
  signing_key:
55
58
  specification_version: 4
56
- summary: Reflective testing that's completely automated.
59
+ summary: Reflective testing.
57
60
  test_files: []