annotate src/layout/Layout.test.ts @ 108:5e6840229a05

rewrite freeStatements rendering to put more planning in layout
author drewp@bigasterisk.com
date Fri, 18 Mar 2022 11:57:38 -0700
parents 2468f2227d22
children cbcd82d21356
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
rev   line source
104
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
1 import { Quad, Store, Term } from "n3";
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
2 import { n3Graph } from "./fetchAndParse";
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
3 import { AlignedTable, Layout, LayoutResult } from "./Layout";
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
4 import { EX, rdf } from "./namespaces";
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
5 import { ViewConfig } from "./ViewConfig";
88
ac7ad087d474 graph view rewrites and fixes for the multi-subject table
drewp@bigasterisk.com
parents:
diff changeset
6
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
7 const twoStatements = async (): Promise<Store> => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
8 return n3Graph(`
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
9 @prefix : <http://example.com/> .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
10 :g1 {
104
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
11 :a0 :b0 :c0 .
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
12 :d0 :e0 :f0 .
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
13 }
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
14 `);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
15 };
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
16
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
17 const typedStatements = async (): Promise<Store> => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
18 return n3Graph(`
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
19 @prefix : <http://example.com/> .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
20 :g1 {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
21 :a a :T1 ; :color :red .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
22 :b a :T1 ; :color :blue .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
23 :c a :T1 .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
24 :d a :T2 ; :size :big .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
25 :e a :T1,:T2; :size :small
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
26 }
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
27 `);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
28 };
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
29 function G1(s: Term, p: Term, o: Term): Quad {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
30 return new Quad(s, p, o, EX("g1"));
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
31 }
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
32
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
33 describe("Layout", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
34 it("accepts a ViewConfig", async () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
35 const vc = new ViewConfig();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
36 await vc.readFromGraph(`
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
37 @prefix ex: <http://example.com/> .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
38 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
39
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
40 <> a ex:View; rdfs:label "repos" .`);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
41 const layout = new Layout(vc);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
42 const lr = layout.plan(await twoStatements());
88
ac7ad087d474 graph view rewrites and fixes for the multi-subject table
drewp@bigasterisk.com
parents:
diff changeset
43 });
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
44 it("defaults to putting all triples in the ungrouped list", async () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
45 const layout = new Layout();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
46 const lr = layout.plan(await twoStatements());
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
47 expect(lr).toEqual({
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
48 sections: [
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
49 {
108
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
50 subjRows: [
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
51 { subj: EX("a0"), predRows: [{ pred: EX("b0"), objs: [EX("c0")] }] },
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
52 { subj: EX("d0"), predRows: [{ pred: EX("e0"), objs: [EX("f0")] }] },
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
53 ],
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
54 },
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
55 ],
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
56 });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
57 });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
58 describe("makes a table as requested by ViewConfig", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
59 let lr: LayoutResult;
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
60
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
61 beforeAll(async () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
62 const vc = new ViewConfig();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
63 await vc.readFromGraph(`
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
64 @prefix : <http://example.com/> .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
65 @prefix rdfs: <http://www.w3.org/2000/01/rdf-schema#> .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
66
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
67 <> a :View; :table [ :primaryType :T1 ] .`);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
68 const layout = new Layout(vc);
104
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
69 lr = layout.plan(await typedStatements());
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
70 });
108
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
71 it("returns 2 sections", () => {
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
72 expect(lr.sections).toHaveLength(2);
108
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
73 });
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
74 it("puts the right type in the table", async () => {
104
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
75 const sec0 = lr.sections[0] as AlignedTable;
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
76 expect(sec0.columnHeaders).toEqual([
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
77 { rdfType: EX("T1"), pred: EX("color") },
108
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
78 { rdfType: EX("T1"), pred: EX("size") },
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
79 ]);
104
1aea03d306af WIP Layout. tests are passing but they're a little wrong
drewp@bigasterisk.com
parents: 103
diff changeset
80 expect(sec0.rows).toEqual([
108
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
81 [EX("a"), EX("red"), null],
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
82 [EX("b"), EX("blue"), null],
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
83 [EX("c"), null, null],
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
84 [EX("e"), null, EX("small")],
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
85 ]);
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
86 });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
87 it("leaves the rest ungrouped", async () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
88 expect(lr.sections[1]).toEqual({
108
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
89 subjRows: [
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
90 {
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
91 subj: EX("d"),
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
92 predRows: [
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
93 { pred: EX("size"), objs: [EX("big")] },
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
94 { pred: rdf.type, objs: [EX("T2")] },
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
95 ],
5e6840229a05 rewrite freeStatements rendering to put more planning in layout
drewp@bigasterisk.com
parents: 106
diff changeset
96 },
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
97 ],
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
98 });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
99 });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
100 });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
101 it("makes a table out of ungrouped triples with the same type", async () => {});
88
ac7ad087d474 graph view rewrites and fixes for the multi-subject table
drewp@bigasterisk.com
parents:
diff changeset
102 });
ac7ad087d474 graph view rewrites and fixes for the multi-subject table
drewp@bigasterisk.com
parents:
diff changeset
103
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
104 // describe("equality", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
105 // test("investigation of https://github.com/rdfjs/N3.js/issues/265", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
106 // const x = namedNode("x");
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
107 // const x2 = namedNode("x");
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
108 // // (NamedNode.prototype as any).hashCode = () => 0;
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
109 // // expect((x as any).hashCode()).toEqual((x2 as any).hashCode())
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
110 // expect(x === x2).toBeFalsy();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
111 // expect(x == x2).toBeFalsy();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
112 // expect(x.equals(x2)).toBeTruthy();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
113 // let imap = Immutable.Map();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
114 // imap = imap.set(x, 11);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
115 // imap = imap.set(x, 22);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
116 // imap = imap.set(x2, 33);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
117 // expect(imap.has(x)).toBeTruthy();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
118 // expect(imap.has(x2)).toBeTruthy();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
119 // expect(imap.size).toEqual(1);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
120 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
121 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
122
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
123 // describe("groupByRdfType", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
124 // test("finds multiple graphs", () => {});
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
125 // test("works", async () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
126 // const store = new Store();
88
ac7ad087d474 graph view rewrites and fixes for the multi-subject table
drewp@bigasterisk.com
parents:
diff changeset
127
103
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
128 // const parser = new Parser();
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
129 // await new Promise((res, rej) => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
130 // parser.parse(
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
131 // `PREFIX : <urn:>
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
132 // :rs1 a :Foo; :pred1 "obj1" .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
133 // :rs2 a :Foo; :pred1 "obj2" .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
134 // :rs3 a :Bar .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
135 // :rs4 :pred1 "obj4" .
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
136 // `,
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
137 // (error, quad: Quad, prefixes: Prefixes) => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
138 // if (quad) {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
139 // store.addQuad(quad);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
140 // } else {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
141 // res(undefined);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
142 // }
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
143 // }
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
144 // );
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
145 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
146 // const grouped = groupByRdfType(store);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
147 // expect(Array.from(grouped.byType.keys())).toHaveLength(2);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
148 // expect(grouped.byType.get(namedNode("urn:Foo"))).toEqual(
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
149 // Immutable.Set([namedNode("urn:rs1"), namedNode("urn:rs2")])
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
150 // );
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
151 // expect(grouped.byType.get(namedNode("urn:Bar"))).toEqual(
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
152 // Immutable.Set([namedNode("urn:rs3")])
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
153 // );
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
154 // expect(grouped.untypedSubjs).toEqual([namedNode("urn:rs4")]);
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
155 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
156
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
157 // describe("MultiSubjsTypeBlockLayout", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
158 // test("gathers subjs", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
159
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
160 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
161 // test("gathers preds", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
162
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
163 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
164 // test("cells reports filled cells", () => {
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
165
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
166 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
167 // });
f12feced00ce WIP rewriting Layout
drewp@bigasterisk.com
parents: 88
diff changeset
168 // });