Added tests for examples (#2216)
This adds a new test to validate the structure and syntax of all examples and moves the existing example test into the mocha test suite.
This commit is contained in:
parent
26626dedad
commit
1f7a245c44
|
@ -1,11 +1,11 @@
|
|||
<h2>Comments</h2>
|
||||
<pre><code>
|
||||
* Line Comments
|
||||
" End of line comment used as line comment.
|
||||
value = 1. " End of line comment
|
||||
" End of line comment used as line comment.
|
||||
value = 1. " End of line comment
|
||||
|
||||
DATA:
|
||||
"! ABAPDoc comment
|
||||
"! ABAPDoc comment
|
||||
value TYPE i.
|
||||
</code></pre>
|
||||
|
||||
|
@ -16,7 +16,7 @@ my_string = 'Simple string'.
|
|||
my_string = 'String with an escaped '' inside'.
|
||||
my_string = |A string template: { nvalue } times|.
|
||||
my_string = |A string template: { nvalue } times|.
|
||||
my_string = |Characters \|, \{, and \} have to be escaped by \\ in literal text.|.
|
||||
my_string = |Characters \|, \{, and \} have to be escaped by \\ in literal text.|.
|
||||
</code></pre>
|
||||
|
||||
<h2>Numbers and Operators</h2>
|
||||
|
@ -62,4 +62,4 @@ DATA lo_instace TYPE REF TO lcl_my_class.
|
|||
CREATE OBJECT lo_instace.
|
||||
|
||||
my_structure-component = lo_instace->my_method( ).
|
||||
</code></pre>
|
||||
</code></pre>
|
||||
|
|
|
@ -55,100 +55,100 @@ export {
|
|||
|
||||
# Whether to consider UDP "connections" for scan detection.
|
||||
# Can lead to false positives due to UDP fanout from some P2P apps.
|
||||
const suppress_UDP_scan_checks = F &redef;
|
||||
const suppress_UDP_scan_checks = F &redef;
|
||||
|
||||
const activate_priv_port_check = T &redef;
|
||||
const activate_landmine_check = F &redef;
|
||||
const landmine_thresh_trigger = 5 &redef;
|
||||
const activate_priv_port_check = T &redef;
|
||||
const activate_landmine_check = F &redef;
|
||||
const landmine_thresh_trigger = 5 &redef;
|
||||
|
||||
const landmine_address: set[addr] &redef;
|
||||
const landmine_address: set[addr] &redef;
|
||||
|
||||
const scan_summary_trigger = 25 &redef;
|
||||
const port_summary_trigger = 20 &redef;
|
||||
const lowport_summary_trigger = 10 &redef;
|
||||
const scan_summary_trigger = 25 &redef;
|
||||
const port_summary_trigger = 20 &redef;
|
||||
const lowport_summary_trigger = 10 &redef;
|
||||
|
||||
# Raise ShutdownThresh after this many failed attempts
|
||||
const shut_down_thresh = 100 &redef;
|
||||
const shut_down_thresh = 100 &redef;
|
||||
|
||||
# Which services should be analyzed when detecting scanning
|
||||
# (not consulted if analyze_all_services is set).
|
||||
const analyze_services: set[port] &redef;
|
||||
const analyze_all_services = T &redef;
|
||||
const analyze_services: set[port] &redef;
|
||||
const analyze_all_services = T &redef;
|
||||
|
||||
# Track address scaners only if at least these many hosts contacted.
|
||||
const addr_scan_trigger = 0 &redef;
|
||||
const addr_scan_trigger = 0 &redef;
|
||||
|
||||
# Ignore address scanners for further scan detection after
|
||||
# scanning this many hosts.
|
||||
# 0 disables.
|
||||
const ignore_scanners_threshold = 0 &redef;
|
||||
const ignore_scanners_threshold = 0 &redef;
|
||||
|
||||
# Report a scan of peers at each of these points.
|
||||
const report_peer_scan: vector of count = {
|
||||
20, 100, 1000, 10000, 50000, 100000, 250000, 500000, 1000000,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
const report_outbound_peer_scan: vector of count = {
|
||||
100, 1000, 10000,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
# Report a scan of ports at each of these points.
|
||||
const report_port_scan: vector of count = {
|
||||
50, 250, 1000, 5000, 10000, 25000, 65000,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
# Once a source has scanned this many different ports (to however many
|
||||
# different remote hosts), start tracking its per-destination access.
|
||||
const possible_port_scan_thresh = 20 &redef;
|
||||
const possible_port_scan_thresh = 20 &redef;
|
||||
|
||||
# Threshold for scanning privileged ports.
|
||||
const priv_scan_trigger = 5 &redef;
|
||||
const priv_scan_trigger = 5 &redef;
|
||||
const troll_skip_service = {
|
||||
25/tcp, 21/tcp, 22/tcp, 20/tcp, 80/tcp,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
const report_accounts_tried: vector of count = {
|
||||
20, 100, 1000, 10000, 100000, 1000000,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
const report_remote_accounts_tried: vector of count = {
|
||||
100, 500,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
# Report a successful password guessing if the source attempted
|
||||
# at least this many.
|
||||
const password_guessing_success_threshhold = 20 &redef;
|
||||
const password_guessing_success_threshhold = 20 &redef;
|
||||
|
||||
const skip_accounts_tried: set[addr] &redef;
|
||||
const skip_accounts_tried: set[addr] &redef;
|
||||
|
||||
const addl_web = {
|
||||
81/tcp, 443/tcp, 8000/tcp, 8001/tcp, 8080/tcp, }
|
||||
&redef;
|
||||
&redef;
|
||||
|
||||
const skip_services = { 113/tcp, } &redef;
|
||||
const skip_services = { 113/tcp, } &redef;
|
||||
const skip_outbound_services = { 21/tcp, addl_web, }
|
||||
&redef;
|
||||
&redef;
|
||||
|
||||
const skip_scan_sources = {
|
||||
255.255.255.255, # who knows why we see these, but we do
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
const skip_scan_nets: set[subnet] = {} &redef;
|
||||
const skip_scan_nets: set[subnet] = {} &redef;
|
||||
|
||||
# List of well known local server/ports to exclude for scanning
|
||||
# purposes.
|
||||
const skip_dest_server_ports: set[addr, port] = {} &redef;
|
||||
const skip_dest_server_ports: set[addr, port] = {} &redef;
|
||||
|
||||
# Reverse (SYN-ack) scans seen from these ports are considered
|
||||
# to reflect possible SYN-flooding backscatter, and not true
|
||||
# (stealth) scans.
|
||||
const backscatter_ports = {
|
||||
80/tcp, 8080/tcp, 53/tcp, 53/udp, 179/tcp, 6666/tcp, 6667/tcp,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
const report_backscatter: vector of count = {
|
||||
20,
|
||||
} &redef;
|
||||
} &redef;
|
||||
|
||||
global check_scan:
|
||||
function(c: connection, established: bool, reverse: bool): bool;
|
||||
|
@ -174,14 +174,14 @@ export {
|
|||
# Indexed by scanner address, yields # distinct peers scanned.
|
||||
# pre_distinct_peers tracks until addr_scan_trigger hosts first.
|
||||
global pre_distinct_peers: table[addr] of set[addr]
|
||||
&read_expire = 15 mins &redef;
|
||||
&read_expire = 15 mins &redef;
|
||||
|
||||
global distinct_peers: table[addr] of set[addr]
|
||||
&read_expire = 15 mins &expire_func=scan_summary &redef;
|
||||
&read_expire = 15 mins &expire_func=scan_summary &redef;
|
||||
global distinct_ports: table[addr] of set[port]
|
||||
&read_expire = 15 mins &expire_func=port_summary &redef;
|
||||
&read_expire = 15 mins &expire_func=port_summary &redef;
|
||||
global distinct_low_ports: table[addr] of set[port]
|
||||
&read_expire = 15 mins &expire_func=lowport_summary &redef;
|
||||
&read_expire = 15 mins &expire_func=lowport_summary &redef;
|
||||
|
||||
# Indexed by scanner address, yields a table with scanned hosts
|
||||
# (and ports).
|
||||
|
@ -196,23 +196,23 @@ export {
|
|||
global accounts_tried: table[addr] of set[string, string]
|
||||
&read_expire = 1 days;
|
||||
|
||||
global ignored_scanners: set[addr] &create_expire = 1 day &redef;
|
||||
global ignored_scanners: set[addr] &create_expire = 1 day &redef;
|
||||
|
||||
# These tables track whether a threshold has been reached.
|
||||
# More precisely, the counter is the next index of threshold vector.
|
||||
global shut_down_thresh_reached: table[addr] of bool &default=F;
|
||||
global rb_idx: table[addr] of count
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
global rps_idx: table[addr] of count
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
global rops_idx: table[addr] of count
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
global rpts_idx: table[addr,addr] of count
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
global rat_idx: table[addr] of count
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
global rrat_idx: table[addr] of count
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
&default=1 &read_expire = 1 days &redef;
|
||||
}
|
||||
|
||||
global thresh_check: function(v: vector of count, idx: table[addr] of count,
|
||||
|
@ -388,7 +388,7 @@ function check_scan(c: connection, established: bool, reverse: bool): bool
|
|||
{ # XXXXX
|
||||
|
||||
if ( orig !in distinct_peers )
|
||||
distinct_peers[orig] = set() &mergeable;
|
||||
distinct_peers[orig] = set() &mergeable;
|
||||
|
||||
if ( resp !in distinct_peers[orig] )
|
||||
add distinct_peers[orig][resp];
|
||||
|
@ -448,7 +448,7 @@ function check_scan(c: connection, established: bool, reverse: bool): bool
|
|||
if ( orig !in distinct_ports || service !in distinct_ports[orig] )
|
||||
{
|
||||
if ( orig !in distinct_ports )
|
||||
distinct_ports[orig] = set() &mergeable;
|
||||
distinct_ports[orig] = set() &mergeable;
|
||||
|
||||
if ( service !in distinct_ports[orig] )
|
||||
add distinct_ports[orig][service];
|
||||
|
@ -456,7 +456,7 @@ function check_scan(c: connection, established: bool, reverse: bool): bool
|
|||
if ( |distinct_ports[orig]| >= possible_port_scan_thresh &&
|
||||
orig !in scan_triples )
|
||||
{
|
||||
scan_triples[orig] = table() &mergeable;
|
||||
scan_triples[orig] = table() &mergeable;
|
||||
add possible_scan_sources[orig];
|
||||
}
|
||||
}
|
||||
|
@ -469,7 +469,7 @@ function check_scan(c: connection, established: bool, reverse: bool): bool
|
|||
service !in distinct_low_ports[orig] )
|
||||
{
|
||||
if ( orig !in distinct_low_ports )
|
||||
distinct_low_ports[orig] = set() &mergeable;
|
||||
distinct_low_ports[orig] = set() &mergeable;
|
||||
|
||||
add distinct_low_ports[orig][service];
|
||||
|
||||
|
@ -494,10 +494,10 @@ function check_scan(c: connection, established: bool, reverse: bool): bool
|
|||
if ( orig in possible_scan_sources )
|
||||
{
|
||||
if ( orig !in scan_triples )
|
||||
scan_triples[orig] = table() &mergeable;
|
||||
scan_triples[orig] = table() &mergeable;
|
||||
|
||||
if ( resp !in scan_triples[orig] )
|
||||
scan_triples[orig][resp] = set() &mergeable;
|
||||
scan_triples[orig][resp] = set() &mergeable;
|
||||
|
||||
if ( service !in scan_triples[orig][resp] )
|
||||
{
|
||||
|
|
|
@ -334,14 +334,14 @@ keymap ; => {:a 1, :b 2, :c 3}
|
|||
java.util.Calendar))
|
||||
|
||||
; Use the class name with a "." at the end to make a new instance
|
||||
(Date.) ; <a date object>
|
||||
(Date.) ; <a date object>
|
||||
|
||||
; Use . to call methods. Or, use the ".method" shortcut
|
||||
(. (Date.) getTime) ; <a timestamp>
|
||||
(. (Date.) getTime) ; <a timestamp>
|
||||
(.getTime (Date.)) ; exactly the same thing.
|
||||
|
||||
; Use / to call static methods
|
||||
(System/currentTimeMillis) ; <a timestamp> (system is always present)
|
||||
(System/currentTimeMillis) ; <a timestamp> (system is always present)
|
||||
|
||||
; Use doto to make dealing with (mutable) classes more tolerable
|
||||
(import java.util.Calendar)
|
||||
|
|
|
@ -65,10 +65,10 @@ def sum(elms int...) int {
|
|||
thesum = sum(1, 2, 3, 4, 5)
|
||||
|
||||
//partially defined typedef
|
||||
typedef NameMap<X> = java.util.ArrayList<java.util.HashMap<String, java.util.HashSet<X>>>
|
||||
typedef NameMap<X> = java.util.ArrayList<java.util.HashMap<String, java.util.HashSet<X>>>
|
||||
|
||||
//using typedefs...
|
||||
nm NameMap<String>= new NameMap<String>()
|
||||
nm NameMap<String>= new NameMap<String>()
|
||||
|
||||
@Annotation
|
||||
class MyClass(a int, b int, c String){
|
||||
|
@ -79,11 +79,11 @@ mc1 = MyClass(12, 14, "hi there")
|
|||
mc2 = mc1@ //copy mc1
|
||||
|
||||
assert mc1 == mc2//same values!
|
||||
assert mc1 &<> mc2//different objects!
|
||||
assert mc1 &<> mc2//different objects!
|
||||
|
||||
mc3 = mc1@(a = 100)//copy mc1 but overwrite value of a
|
||||
assert 'MyClass(100, 14, "hi there")' == mc3.toString()
|
||||
|
||||
mc4 = mc1@(<a, b>)//copy mc1 but exclude a and b
|
||||
mc4 = mc1@(<a, b>)//copy mc1 but exclude a and b
|
||||
assert 'MyClass(0, 0, "hi there")' == mc3.toString()
|
||||
</code></pre>
|
||||
|
|
|
@ -10,7 +10,7 @@
|
|||
# VERSION 0.0.1
|
||||
|
||||
FROM ubuntu
|
||||
MAINTAINER Victor Vieux <victor@docker.com>
|
||||
MAINTAINER Victor Vieux <victor@docker.com>
|
||||
|
||||
LABEL Description="This image is used to start the foobar executable" Vendor="ACME Products" Version="1.0"
|
||||
RUN apt-get update && apt-get install -y inotify-tools nginx apache2 openssh-server
|
||||
|
|
|
@ -55,8 +55,7 @@ BV{ 1 2 3 4 }</code></pre>
|
|||
|
||||
<h2>Regular Expressions</h2>
|
||||
<pre><code>USE: regexp
|
||||
R/ abcde?.*+\?\.\*\+\/\\\/idmsr-idmsr/idmsr-idmsr</code>
|
||||
</pre>
|
||||
R/ abcde?.*+\?\.\*\+\/\\\/idmsr-idmsr/idmsr-idmsr</code></pre>
|
||||
|
||||
<h2>Colon parsing words</h2>
|
||||
<pre><code>: a ( -- ) ;
|
||||
|
@ -73,9 +72,9 @@ GENERIC#: x 1 ( x: integer quot: ( x -- y ) -- )</code></pre>
|
|||
|
||||
new last-index + - neg
|
||||
|
||||
<array> <=> SYNTAX: x $[ xyz ]
|
||||
<array> <=> SYNTAX: x $[ xyz ]
|
||||
|
||||
set-x change-x with-variable ?of if* (gensym) hex. $description reader>> >>setter writer<<
|
||||
set-x change-x with-variable ?of if* (gensym) hex. $description reader>> >>setter writer<<
|
||||
|
||||
string>number >hex base> mutater!
|
||||
</code></pre>
|
||||
|
|
|
@ -3,7 +3,7 @@
|
|||
|
||||
<h2>Control Flow</h2>
|
||||
|
||||
Liquid provides multiple control flow statements.
|
||||
<p>Liquid provides multiple control flow statements.</p>
|
||||
|
||||
<h3>if</h3>
|
||||
<pre><code>
|
||||
|
@ -18,7 +18,7 @@ Liquid provides multiple control flow statements.
|
|||
|
||||
<h3>unless</h3>
|
||||
|
||||
The opposite of <code>if</code> – executes a block of code only if a certain condition is not met.
|
||||
<p>The opposite of <code>if</code> – executes a block of code only if a certain condition is not met.</p>
|
||||
|
||||
<pre><code>
|
||||
{% unless product.title == 'Awesome Shoes' %}
|
||||
|
@ -28,7 +28,7 @@ These shoes are not awesome.
|
|||
|
||||
<h3>case</h3>
|
||||
|
||||
Creates a switch statement to compare a variable with different values. <code>case</code> initializes the switch statement, and <code>when</code> compares its values.
|
||||
<p>Creates a switch statement to compare a variable with different values. <code>case</code> initializes the switch statement, and <code>when</code> compares its values.</p>
|
||||
|
||||
<pre><code>
|
||||
{% assign handle = 'cake' %}
|
||||
|
@ -44,10 +44,10 @@ Creates a switch statement to compare a variable with different values. <code>ca
|
|||
|
||||
<h3>for</h3>
|
||||
|
||||
Repeatedly executes a block of code.
|
||||
<p>Repeatedly executes a block of code.</p>
|
||||
|
||||
break = Causes the loop to stop iterating when it encounters the break tag.
|
||||
continue = Causes the loop to skip the current iteration when it encounters the continue tag.
|
||||
<p>break = Causes the loop to stop iterating when it encounters the break tag. <br>
|
||||
continue = Causes the loop to skip the current iteration when it encounters the continue tag.</p>
|
||||
|
||||
<pre><code>
|
||||
{% for i in (1..10) %}
|
||||
|
|
|
@ -72,6 +72,6 @@ bar
|
|||
baz"></code></pre>
|
||||
|
||||
<h2>XML tags with non-ASCII characters</h2>
|
||||
<pre><code><Läufer>foo</Läufer>
|
||||
<tag läufer="läufer">bar</tag>
|
||||
<läufer:tag>baz</läufer:tag></code></pre>
|
||||
<pre><code><Läufer>foo</Läufer>
|
||||
<tag läufer="läufer">bar</tag>
|
||||
<läufer:tag>baz</läufer:tag></code></pre>
|
||||
|
|
|
@ -28,14 +28,14 @@ print($array[0]); // Prints "first\n"
|
|||
print($array[1]); // Prints "second\n"
|
||||
print($array[2]); // Prints "third\n"
|
||||
|
||||
vector $roger = <<3.0, 7.7, 9.1>>;
|
||||
vector $more = <<4.5, 6.789, 9.12356>>;
|
||||
vector $roger = <<3.0, 7.7, 9.1>>;
|
||||
vector $more = <<4.5, 6.789, 9.12356>>;
|
||||
// Assign a vector to variable $test:
|
||||
vector $test = <<3.0, 7.7, 9.1>>;
|
||||
vector $test = <<3.0, 7.7, 9.1>>;
|
||||
$test = <<$test.x, 5.5, $test.z>>
|
||||
// $test is now <<3.0, 5.5, 9.1>>
|
||||
// $test is now <<3.0, 5.5, 9.1>>
|
||||
|
||||
matrix $a3[3][4] = <<2.5, 4.5, 3.25, 8.05;
|
||||
matrix $a3[3][4] = <<2.5, 4.5, 3.25, 8.05;
|
||||
1.12, 1.3, 9.5, 5.2;
|
||||
7.23, 6.006, 2.34, 4.67>></code></pre>
|
||||
|
||||
|
|
|
@ -7,14 +7,14 @@
|
|||
<pre class="language-cpp"><code>// OpenCL functions, constants, etc. are also highlighted in OpenCL host code in the c or cpp language
|
||||
cl::Event KernelFilterImages::runSingle(const cl::Image2D& imgSrc, SPImage2D& imgDst)
|
||||
{
|
||||
const size_t rows = imgSrc.getImageInfo<CL_IMAGE_HEIGHT>();
|
||||
const size_t cols = imgSrc.getImageInfo<CL_IMAGE_WIDTH>();
|
||||
const size_t rows = imgSrc.getImageInfo<CL_IMAGE_HEIGHT>();
|
||||
const size_t cols = imgSrc.getImageInfo<CL_IMAGE_WIDTH>();
|
||||
|
||||
ASSERT(rows > 0 && cols > 0, "The image object seems to be invalid, no rows/cols set");
|
||||
ASSERT(imgSrc.getImageInfo<CL_IMAGE_FORMAT>().image_channel_data_type == CL_FLOAT, "Only float type images are supported");
|
||||
ASSERT(imgSrc.getInfo<CL_MEM_FLAGS>() == CL_MEM_READ_ONLY || imgSrc.getInfo<CL_MEM_FLAGS>() == CL_MEM_READ_WRITE, "Can't read the input image");
|
||||
ASSERT(imgSrc.getImageInfo<CL_IMAGE_FORMAT>().image_channel_data_type == CL_FLOAT, "Only float type images are supported");
|
||||
ASSERT(imgSrc.getInfo<CL_MEM_FLAGS>() == CL_MEM_READ_ONLY || imgSrc.getInfo<CL_MEM_FLAGS>() == CL_MEM_READ_WRITE, "Can't read the input image");
|
||||
|
||||
imgDst = std::make_shared<cl::Image2D>(*context, CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), cols, rows);
|
||||
imgDst = std::make_shared<cl::Image2D>(*context, CL_MEM_READ_WRITE, cl::ImageFormat(CL_R, CL_FLOAT), cols, rows);
|
||||
|
||||
cl::Kernel kernel(*program, "filter_single");
|
||||
kernel.setArg(0, imgSrc);
|
||||
|
|
|
@ -58,8 +58,8 @@ d:2006.07.04
|
|||
|
||||
<h2>Verbs</h2>
|
||||
<pre><code>99+L
|
||||
x<42|x>98
|
||||
(x<42)|x>98
|
||||
x<42|x>98
|
||||
(x<42)|x>98
|
||||
42~(4 2;(1 0))
|
||||
(4 2)~(4; 2*1)</code></pre>
|
||||
|
||||
|
|
|
@ -1,21 +1,16 @@
|
|||
<h2>Comments</h2>
|
||||
<pre>
|
||||
<code># This is a comment</code>
|
||||
</pre>
|
||||
<pre><code># This is a comment</code></pre>
|
||||
|
||||
<h2>Strings</h2>
|
||||
<pre>
|
||||
<code>"foo \"bar\" baz"
|
||||
<pre><code>"foo \"bar\" baz"
|
||||
'foo \'bar\' baz'
|
||||
""" "Multi-line" strings
|
||||
are supported."""
|
||||
''' 'Multi-line' strings
|
||||
are supported.'''</code>
|
||||
</pre>
|
||||
are supported.'''</code></pre>
|
||||
|
||||
<h2>Python</h2>
|
||||
<pre>
|
||||
<code>class Dog:
|
||||
<pre><code>class Dog:
|
||||
|
||||
tricks = [] # mistaken use of a class variable
|
||||
|
||||
|
@ -23,19 +18,15 @@ are supported.'''</code>
|
|||
self.name = name
|
||||
|
||||
def add_trick(self, trick):
|
||||
self.tricks.append(trick)</code>
|
||||
</pre>
|
||||
self.tricks.append(trick)</code></pre>
|
||||
|
||||
<h2>Properties</h2>
|
||||
<pre>
|
||||
<code>style my_text is text:
|
||||
<pre><code>style my_text is text:
|
||||
size 40
|
||||
font "gentium.ttf"</code>
|
||||
</pre>
|
||||
font "gentium.ttf"</code></pre>
|
||||
|
||||
<h2>Configuration</h2>
|
||||
<pre>
|
||||
<code>init -1:
|
||||
<pre><code>init -1:
|
||||
python hide:
|
||||
|
||||
## Should we enable the use of developer tools? This should be
|
||||
|
@ -52,8 +43,7 @@ are supported.'''</code>
|
|||
## This controls the title of the window, when Ren'Py is
|
||||
## running in a window.
|
||||
|
||||
config.window_title = u"The Question"</code>
|
||||
</pre>
|
||||
config.window_title = u"The Question"</code></pre>
|
||||
|
||||
|
||||
<h2>Full example</h2>
|
||||
|
@ -120,4 +110,4 @@ label start:
|
|||
|
||||
"... to ask her later.":
|
||||
|
||||
jump later</code></pre>
|
||||
jump later</code></pre>
|
||||
|
|
|
@ -11,7 +11,7 @@ comment */
|
|||
<h2>Commands</h2>
|
||||
<pre><code>{template .helloNames}
|
||||
// Greet the person.
|
||||
{call .helloName data="all" /}<br>
|
||||
{call .helloName data="all" /}<br>
|
||||
// Greet the additional people.
|
||||
{foreach $additionalName in $additionalNames}
|
||||
{call .helloName}
|
||||
|
@ -33,4 +33,4 @@ comment */
|
|||
<h2>Literal section</h2>
|
||||
<pre><code>{literal}
|
||||
This is not a {$variable}
|
||||
{/literal}</code></pre>
|
||||
{/literal}</code></pre>
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<h2>Introduction</h2>
|
||||
The queries shown here can be found in the SPARQL specifications:
|
||||
<a href="https://www.w3.org/TR/sparql11-query/">https://www.w3.org/TR/sparql11-query/</a>
|
||||
|
||||
<p>The queries shown here can be found in the SPARQL specifications:
|
||||
<a href="https://www.w3.org/TR/sparql11-query/">https://www.w3.org/TR/sparql11-query/</a></p>
|
||||
|
||||
<h2>query 2.1.6 Examples of Query Syntax</h2>
|
||||
|
||||
|
@ -269,7 +270,7 @@ FILTER regex(str(?mbox), "@work.example") }
|
|||
}
|
||||
</code></pre>
|
||||
|
||||
The final example query is not based on the SPARQL 1.1 queries.
|
||||
<p>The final example query is not based on the SPARQL 1.1 queries.</p>
|
||||
|
||||
<h2>Full Example query</h2>
|
||||
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<h2>Full example</h2>
|
||||
<pre></code>1..48
|
||||
<pre><code>1..48
|
||||
ok 1 Description # Directive
|
||||
# Diagnostic
|
||||
....
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<h2>Comments</h2>
|
||||
<pre><code">// Single line comment
|
||||
<pre><code>// Single line comment
|
||||
/** Multi-line
|
||||
doc comment */</code></pre>
|
||||
|
||||
<h2>Strings</h2>
|
||||
<pre><code">"foo \"bar\" baz"
|
||||
<pre><code>"foo \"bar\" baz"
|
||||
"Multi-line strings ending with a \
|
||||
are supported too."
|
||||
"""Verbatim strings
|
||||
|
@ -13,10 +13,10 @@ multi-line strings like this too."""
|
|||
@"Template string with variables $var1 $(var2 * 2)"</code></pre>
|
||||
|
||||
<h2>Regex</h2>
|
||||
<pre><code">/foo?[ ]*bar/</code></pre>
|
||||
<pre><code>/foo?[ ]*bar/</code></pre>
|
||||
|
||||
<h2>Full example</h2>
|
||||
<pre><code">using Gtk;
|
||||
<pre><code>using Gtk;
|
||||
|
||||
int main (string[] args) {
|
||||
Gtk.init(ref args);
|
||||
|
@ -30,4 +30,4 @@ int main (string[] args) {
|
|||
|
||||
Gtk.main();
|
||||
return 0;
|
||||
}</code></pre>
|
||||
}</code></pre>
|
||||
|
|
|
@ -1,10 +1,6 @@
|
|||
"use strict";
|
||||
|
||||
const { parallel } = require('gulp');
|
||||
const fs = require('fs');
|
||||
const git = require('simple-git/promise')(__dirname);
|
||||
// use the JSON file because this file is less susceptible to merge conflicts
|
||||
const { languages } = require('../components.json');
|
||||
|
||||
|
||||
/**
|
||||
|
@ -19,46 +15,6 @@ function gitChanges() {
|
|||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks that all languages have and example.
|
||||
*/
|
||||
async function hasExample() {
|
||||
const exampleFiles = new Set(fs.readdirSync(__dirname + '/../examples'));
|
||||
const ignore = new Set([
|
||||
// these are libraries and not languages
|
||||
'markup-templating',
|
||||
't4-templating',
|
||||
// this does alter some languages but it's mainly a library
|
||||
'javadoclike',
|
||||
// Regex doesn't have any classes supported by our themes and mainly extends other languages
|
||||
'regex'
|
||||
]);
|
||||
|
||||
/** @type {string[]} */
|
||||
const missing = [];
|
||||
for (const lang in languages) {
|
||||
if (lang === 'meta') {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!exampleFiles.delete(`prism-${lang}.html`)) {
|
||||
if (!ignore.has(lang)) {
|
||||
missing.push(lang);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const errors = missing.map(id => `Missing example for ${id}.`);
|
||||
for (const file of exampleFiles) {
|
||||
errors.push(`The examples file "${file}" has no language associated with it.`);
|
||||
}
|
||||
|
||||
if (errors.length) {
|
||||
throw new Error(errors.join('\n'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
premerge: parallel(gitChanges, hasExample)
|
||||
premerge: gitChanges
|
||||
};
|
||||
|
|
|
@ -994,6 +994,22 @@
|
|||
"integrity": "sha512-A46qtFgd+g7pDZinpnwiRJtxbC1hpgf0uzP3iG89scHk0AUC7A1TGxf5OiiOUv/JMZR8GOt8hL900hV0bOy5xA==",
|
||||
"dev": true
|
||||
},
|
||||
"dom-serializer": {
|
||||
"version": "0.2.2",
|
||||
"resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
|
||||
"integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"domelementtype": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.0.1.tgz",
|
||||
"integrity": "sha512-5HOHUDsYZWV8FGWN0Njbr/Rn7f/eWSQi1v7+HsUVwXgn8nWWlL64zKDkS0n8ZmQ3mlWOMuXOnR+7Nx/5tMO5AQ==",
|
||||
"dev": true
|
||||
},
|
||||
"domexception": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/domexception/-/domexception-1.0.1.tgz",
|
||||
|
@ -1003,6 +1019,26 @@
|
|||
"webidl-conversions": "^4.0.2"
|
||||
}
|
||||
},
|
||||
"domhandler": {
|
||||
"version": "3.0.0",
|
||||
"resolved": "https://registry.npmjs.org/domhandler/-/domhandler-3.0.0.tgz",
|
||||
"integrity": "sha512-eKLdI5v9m67kbXQbJSNn1zjh0SDzvzWVWtX+qEI3eMjZw8daH9k8rlj1FZY9memPwjiskQFbe7vHVVJIAqoEhw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"domutils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.0.0.tgz",
|
||||
"integrity": "sha512-n5SelJ1axbO636c2yUtOGia/IcJtVtlhQbFiVDBZHKV5ReJO1ViX7sFEemtuyoAnBxk5meNSYgA8V4s0271efg==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"dom-serializer": "^0.2.1",
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.0.0"
|
||||
}
|
||||
},
|
||||
"duplexify": {
|
||||
"version": "3.7.1",
|
||||
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
|
||||
|
@ -1056,6 +1092,12 @@
|
|||
"once": "^1.4.0"
|
||||
}
|
||||
},
|
||||
"entities": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/entities/-/entities-2.0.0.tgz",
|
||||
"integrity": "sha512-D9f7V0JSRwIxlRI2mjMqufDrRDnx8p+eEOz7aUM9SuvF8gsBzra0/6tbjl1m8eQHrZlYj6PxqE00hZ1SAIKPLw==",
|
||||
"dev": true
|
||||
},
|
||||
"error-ex": {
|
||||
"version": "1.3.2",
|
||||
"resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
|
||||
|
@ -2496,6 +2538,18 @@
|
|||
"whatwg-encoding": "^1.0.1"
|
||||
}
|
||||
},
|
||||
"htmlparser2": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-4.0.0.tgz",
|
||||
"integrity": "sha512-cChwXn5Vam57fyXajDtPXL1wTYc8JtLbr2TN76FYu05itVVVealxLowe2B3IEznJG4p9HAYn/0tJaRlGuEglFQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"domelementtype": "^2.0.1",
|
||||
"domhandler": "^3.0.0",
|
||||
"domutils": "^2.0.0",
|
||||
"entities": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"http-signature": {
|
||||
"version": "1.2.0",
|
||||
"resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
|
||||
|
|
|
@ -8,11 +8,12 @@
|
|||
"test:aliases": "mocha tests/aliases-test.js",
|
||||
"test:core": "mocha tests/core/**/*.js",
|
||||
"test:dependencies": "mocha tests/dependencies-test.js",
|
||||
"test:examples": "mocha tests/examples-test.js",
|
||||
"test:languages": "mocha tests/run.js",
|
||||
"test:patterns": "mocha tests/pattern-tests.js",
|
||||
"test:plugins": "mocha tests/plugins/**/*.js",
|
||||
"test:runner": "mocha tests/testrunner-tests.js",
|
||||
"test": "npm run test:runner && npm run test:core && npm run test:dependencies && npm run test:languages && npm run test:plugins && npm run test:aliases && npm run test:patterns"
|
||||
"test": "npm run test:runner && npm run test:core && npm run test:dependencies && npm run test:languages && npm run test:plugins && npm run test:aliases && npm run test:patterns && npm run test:examples"
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@ -36,6 +37,7 @@
|
|||
"gulp-rename": "^1.2.0",
|
||||
"gulp-replace": "^1.0.0",
|
||||
"gulp-uglify": "^3.0.1",
|
||||
"htmlparser2": "^4.0.0",
|
||||
"jsdom": "^13.0.0",
|
||||
"mocha": "^6.2.0",
|
||||
"pump": "^3.0.0",
|
||||
|
|
|
@ -0,0 +1,187 @@
|
|||
const fs = require('fs');
|
||||
const { assert } = require('chai');
|
||||
const { Parser } = require('htmlparser2');
|
||||
// use the JSON file because this file is less susceptible to merge conflicts
|
||||
const { languages } = require('../components.json');
|
||||
|
||||
|
||||
describe('Examples', function () {
|
||||
|
||||
const exampleFiles = new Set(fs.readdirSync(__dirname + '/../examples'));
|
||||
const ignore = new Set([
|
||||
// these are libraries and not languages
|
||||
'markup-templating',
|
||||
't4-templating',
|
||||
// this does alter some languages but it's mainly a library
|
||||
'javadoclike',
|
||||
// Regex doesn't have any classes supported by our themes and mainly extends other languages
|
||||
'regex'
|
||||
]);
|
||||
const validFiles = new Set();
|
||||
|
||||
/** @type {string[]} */
|
||||
const missing = [];
|
||||
for (const lang in languages) {
|
||||
if (lang === 'meta') {
|
||||
continue;
|
||||
}
|
||||
|
||||
const file = `prism-${lang}.html`;
|
||||
if (!exampleFiles.has(file)) {
|
||||
if (!ignore.has(lang)) {
|
||||
missing.push(lang);
|
||||
}
|
||||
} else {
|
||||
validFiles.add(file);
|
||||
}
|
||||
}
|
||||
|
||||
const superfluous = [...exampleFiles].filter(f => !validFiles.has(f));
|
||||
|
||||
|
||||
it('- should be available for every language', function () {
|
||||
assert.isEmpty(missing, 'Following languages do not have an example file in ./examples/\n'
|
||||
+ missing.join('\n'));
|
||||
});
|
||||
|
||||
it('- should only be available for registered languages', function () {
|
||||
assert.isEmpty(superfluous, 'Following files are not associated with any language\n'
|
||||
+ superfluous.map(f => `./examples/${f}`).join('\n'));
|
||||
});
|
||||
|
||||
describe('Validate HTML templates', function () {
|
||||
for (const file of validFiles) {
|
||||
it('- ./examples/' + file, async function () {
|
||||
const content = fs.readFileSync(__dirname + '/../examples/' + file, 'utf-8');
|
||||
await validateHTML(content);
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* Validates the given HTML string of an example file.
|
||||
*
|
||||
* @param {string} html
|
||||
*/
|
||||
async function validateHTML(html) {
|
||||
const root = await parseHTML(html);
|
||||
|
||||
/**
|
||||
* @param {TagNode} node
|
||||
*/
|
||||
function checkCodeElements(node) {
|
||||
if (node.tagName === 'code') {
|
||||
assert.equal(node.children.length, 1,
|
||||
'A <code> element is only allowed to contain text, no tags. '
|
||||
+ 'Did you perhaps not escape all "<" characters?');
|
||||
|
||||
const child = node.children[0];
|
||||
if (child.type !== 'text') {
|
||||
// throw to help TypeScript's flow analysis
|
||||
throw assert.equal(child.type, 'text', 'The child of a <code> element must be text only.');
|
||||
}
|
||||
|
||||
const text = child.rawText;
|
||||
|
||||
assert.notMatch(text, /</, 'All "<" characters have to be escape with "<".');
|
||||
assert.notMatch(text, /&(?!amp;|lt;|gt;)(?:[#\w]+);/, 'Only certain entities are allowed.');
|
||||
} else {
|
||||
node.children.forEach(n => {
|
||||
if (n.type === 'tag') {
|
||||
checkCodeElements(n);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
for (const node of root.children) {
|
||||
if (node.type === 'text') {
|
||||
assert.isEmpty(node.rawText.trim(), 'All non-whitespace text has to be in <p> tags.');
|
||||
} else {
|
||||
// only known tags
|
||||
assert.match(node.tagName, /^(?:h2|h3|p|pre|ul|ol)$/, 'Only some tags are allowed as top level tags.');
|
||||
|
||||
// <pre> elements must have only one child, a <code> element
|
||||
if (node.tagName === 'pre') {
|
||||
assert.equal(node.children.length, 1,
|
||||
'<pre> element must have one and only one child node, a <code> element.'
|
||||
+ ' This also means that spaces and line breaks around the <code> element are not allowed.');
|
||||
|
||||
const child = node.children[0];
|
||||
if (child.type !== 'tag') {
|
||||
// throw to help TypeScript's flow analysis
|
||||
throw assert.equal(child.type, 'tag', 'The child of a <pre> element must be a <code> element.');
|
||||
}
|
||||
assert.equal(child.tagName, 'code', 'The child of a <pre> element must be a <code> element.');
|
||||
}
|
||||
|
||||
checkCodeElements(node);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the given HTML fragment and returns a simple tree of the fragment.
|
||||
*
|
||||
* @param {string} html
|
||||
* @returns {Promise<TagNode>}
|
||||
*
|
||||
* @typedef TagNode
|
||||
* @property {"tag"} type
|
||||
* @property {string | null} tagName
|
||||
* @property {Object<string, string>} attributes
|
||||
* @property {(TagNode | TextNode)[]} children
|
||||
*
|
||||
* @typedef TextNode
|
||||
* @property {"text"} type
|
||||
* @property {string} rawText
|
||||
*/
|
||||
function parseHTML(html) {
|
||||
return new Promise((resolve, reject) => {
|
||||
/** @type {TagNode} */
|
||||
const tree = {
|
||||
type: 'tag',
|
||||
tagName: null,
|
||||
attributes: {},
|
||||
children: []
|
||||
};
|
||||
/** @type {TagNode[]} */
|
||||
let stack = [tree];
|
||||
|
||||
const p = new Parser({
|
||||
onerror(err) {
|
||||
reject(err)
|
||||
},
|
||||
onend() {
|
||||
resolve(tree);
|
||||
},
|
||||
|
||||
ontext(data) {
|
||||
stack[stack.length - 1].children.push({
|
||||
type: 'text',
|
||||
rawText: data
|
||||
});
|
||||
},
|
||||
|
||||
onopentag(name, attrs) {
|
||||
/** @type {TagNode} */
|
||||
const newElement = {
|
||||
type: 'tag',
|
||||
tagName: name,
|
||||
attributes: attrs,
|
||||
children: []
|
||||
};
|
||||
stack[stack.length - 1].children.push(newElement);
|
||||
stack.push(newElement);
|
||||
},
|
||||
onclosetag() {
|
||||
stack.pop();
|
||||
}
|
||||
|
||||
}, { lowerCaseTags: false });
|
||||
p.end(html);
|
||||
});
|
||||
}
|
Loading…
Reference in New Issue