pict-section-login 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (25) hide show
  1. package/example_applications/custom_login/Custom-Login-Application.js +75 -0
  2. package/example_applications/custom_login/html/index.html +110 -0
  3. package/example_applications/custom_login/package.json +27 -0
  4. package/example_applications/harness_app/Harness-App-Application.js +167 -0
  5. package/example_applications/harness_app/Harness-App-Configuration.json +4 -0
  6. package/example_applications/harness_app/html/index.html +90 -0
  7. package/example_applications/harness_app/package.json +28 -0
  8. package/example_applications/harness_app/providers/PictRouter-HarnessApp.json +24 -0
  9. package/example_applications/harness_app/views/PictView-HarnessApp-Books.js +172 -0
  10. package/example_applications/harness_app/views/PictView-HarnessApp-Dashboard.js +158 -0
  11. package/example_applications/harness_app/views/PictView-HarnessApp-Layout.js +86 -0
  12. package/example_applications/harness_app/views/PictView-HarnessApp-Login.js +58 -0
  13. package/example_applications/harness_app/views/PictView-HarnessApp-TopBar.js +157 -0
  14. package/example_applications/harness_app/views/PictView-HarnessApp-Users.js +188 -0
  15. package/example_applications/oauth_login/OAuth-Login-Application.js +78 -0
  16. package/example_applications/oauth_login/html/index.html +57 -0
  17. package/example_applications/oauth_login/package.json +27 -0
  18. package/example_applications/orator_login/Orator-Login-Application.js +61 -0
  19. package/example_applications/orator_login/html/index.html +51 -0
  20. package/example_applications/orator_login/package.json +27 -0
  21. package/package.json +53 -0
  22. package/source/Pict-Section-Login-DefaultConfiguration.js +265 -0
  23. package/source/Pict-Section-Login.js +533 -0
  24. package/test/Browser_Integration_tests.js +588 -0
  25. package/test/Pict-Section-Login_tests.js +593 -0
@@ -0,0 +1,188 @@
1
+ const libPictView = require('pict-view');
2
+
3
+ const _ViewConfiguration =
4
+ {
5
+ ViewIdentifier: "HarnessApp-Users",
6
+
7
+ DefaultRenderable: "HarnessApp-Users-Content",
8
+ DefaultDestinationAddress: "#HarnessApp-Content-Container",
9
+
10
+ AutoRender: false,
11
+
12
+ CSS: /*css*/`
13
+ .harnessapp-users h1
14
+ {
15
+ font-size: 1.8rem;
16
+ margin: 0 0 1rem 0;
17
+ color: #264653;
18
+ }
19
+ .harnessapp-users-grid
20
+ {
21
+ display: flex;
22
+ gap: 1rem;
23
+ flex-wrap: wrap;
24
+ }
25
+ .harnessapp-user-card
26
+ {
27
+ background: #fff;
28
+ border: 1px solid #D4A373;
29
+ border-radius: 6px;
30
+ padding: 1rem 1.25rem;
31
+ min-width: 200px;
32
+ flex: 0 0 auto;
33
+ box-shadow: 0 2px 8px rgba(38,70,83,0.08);
34
+ display: flex;
35
+ align-items: center;
36
+ gap: 0.75rem;
37
+ }
38
+ .harnessapp-user-card-avatar
39
+ {
40
+ width: 36px;
41
+ height: 36px;
42
+ border-radius: 50%;
43
+ background: #264653;
44
+ color: #FAEDCD;
45
+ display: flex;
46
+ align-items: center;
47
+ justify-content: center;
48
+ font-weight: 700;
49
+ font-size: 0.85rem;
50
+ flex-shrink: 0;
51
+ }
52
+ .harnessapp-user-card-info
53
+ {
54
+ font-size: 0.85rem;
55
+ color: #264653;
56
+ }
57
+ .harnessapp-user-card-info .login-id
58
+ {
59
+ font-weight: 600;
60
+ font-size: 0.9rem;
61
+ }
62
+ .harnessapp-user-card-info .full-name
63
+ {
64
+ color: #888;
65
+ font-size: 0.8rem;
66
+ }
67
+ .harnessapp-user-card-info .user-id
68
+ {
69
+ background: #264653;
70
+ color: #FAEDCD;
71
+ font-size: 0.65rem;
72
+ font-weight: 700;
73
+ padding: 0.1rem 0.4rem;
74
+ border-radius: 9999px;
75
+ margin-left: 0.25rem;
76
+ }
77
+ .harnessapp-users-loading
78
+ {
79
+ padding: 2rem;
80
+ text-align: center;
81
+ color: #999;
82
+ font-size: 0.9rem;
83
+ }
84
+ `,
85
+
86
+ Templates:
87
+ [
88
+ {
89
+ Hash: "HarnessApp-Users-Template",
90
+ Template: /*html*/`
91
+ <div class="harnessapp-users">
92
+ <h1>Users</h1>
93
+ <div id="HarnessApp-Users-GridContainer">
94
+ <div class="harnessapp-users-loading">Loading users&hellip;</div>
95
+ </div>
96
+ </div>
97
+ `
98
+ }
99
+ ],
100
+
101
+ Renderables:
102
+ [
103
+ {
104
+ RenderableHash: "HarnessApp-Users-Content",
105
+ TemplateHash: "HarnessApp-Users-Template",
106
+ DestinationAddress: "#HarnessApp-Content-Container",
107
+ RenderMethod: "replace"
108
+ }
109
+ ]
110
+ };
111
+
112
+ class HarnessAppUsersView extends libPictView
113
+ {
114
+ constructor(pFable, pOptions, pServiceHash)
115
+ {
116
+ super(pFable, pOptions, pServiceHash);
117
+ }
118
+
119
+ onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent)
120
+ {
121
+ this._loadUsers();
122
+ return super.onAfterRender(pRenderable, pRenderDestinationAddress, pRecord, pContent);
123
+ }
124
+
125
+ _loadUsers()
126
+ {
127
+ fetch('/1.0/Demo/Users')
128
+ .then((pResponse) =>
129
+ {
130
+ return pResponse.json();
131
+ })
132
+ .then((pData) =>
133
+ {
134
+ let tmpUsers = (pData && Array.isArray(pData.Users)) ? pData.Users : [];
135
+ this._renderGrid(tmpUsers);
136
+ })
137
+ .catch((pError) =>
138
+ {
139
+ this.log.error('Failed to load users: ' + pError.message);
140
+ let tmpContainer = this.services.ContentAssignment.getElement('#HarnessApp-Users-GridContainer');
141
+ if (tmpContainer && tmpContainer.length > 0)
142
+ {
143
+ tmpContainer[0].innerHTML = '<div class="harnessapp-users-loading">Failed to load users. Is the server running?</div>';
144
+ }
145
+ });
146
+ }
147
+
148
+ _renderGrid(pUsers)
149
+ {
150
+ let tmpContainer = this.services.ContentAssignment.getElement('#HarnessApp-Users-GridContainer');
151
+ if (!tmpContainer || tmpContainer.length < 1)
152
+ {
153
+ return;
154
+ }
155
+
156
+ if (pUsers.length < 1)
157
+ {
158
+ tmpContainer[0].innerHTML = '<div class="harnessapp-users-loading">No users found.</div>';
159
+ return;
160
+ }
161
+
162
+ let tmpHTML = '<div class="harnessapp-users-grid">';
163
+
164
+ for (let i = 0; i < pUsers.length; i++)
165
+ {
166
+ let tmpUser = pUsers[i];
167
+ let tmpInitial = (tmpUser.LoginID || '?').charAt(0).toUpperCase();
168
+
169
+ tmpHTML += '<div class="harnessapp-user-card">';
170
+ tmpHTML += '<div class="harnessapp-user-card-avatar">' + tmpInitial + '</div>';
171
+ tmpHTML += '<div class="harnessapp-user-card-info">';
172
+ tmpHTML += '<div class="login-id">' + (tmpUser.LoginID || '') + ' <span class="user-id">ID ' + (tmpUser.IDUser || '') + '</span></div>';
173
+ if (tmpUser.FullName)
174
+ {
175
+ tmpHTML += '<div class="full-name">' + tmpUser.FullName + '</div>';
176
+ }
177
+ tmpHTML += '</div>';
178
+ tmpHTML += '</div>';
179
+ }
180
+
181
+ tmpHTML += '</div>';
182
+ tmpContainer[0].innerHTML = tmpHTML;
183
+ }
184
+ }
185
+
186
+ module.exports = HarnessAppUsersView;
187
+
188
+ module.exports.default_configuration = _ViewConfiguration;
@@ -0,0 +1,78 @@
1
+ const libPictApplication = require('pict-application');
2
+ const libPictSectionLogin = require('../../source/Pict-Section-Login.js');
3
+
4
+ /**
5
+ * orator-authentication with OAuth.
6
+ *
7
+ * Enables ShowOAuthProviders so the section fetches the provider list
8
+ * from /1.0/OAuth/Providers and renders branded sign-in buttons for
9
+ * Google, Microsoft, etc. Standard username/password login is still
10
+ * available alongside the OAuth buttons.
11
+ */
12
+ class OAuthLoginView extends libPictSectionLogin
13
+ {
14
+ constructor(pFable, pOptions, pServiceHash)
15
+ {
16
+ super(pFable, pOptions, pServiceHash);
17
+ }
18
+
19
+ onLoginSuccess(pSessionData)
20
+ {
21
+ this.log.info('Authenticated (standard):', pSessionData);
22
+ }
23
+
24
+ onSessionChecked(pSessionData)
25
+ {
26
+ if (pSessionData && pSessionData.LoggedIn)
27
+ {
28
+ this.log.info('Active session found:', pSessionData);
29
+ }
30
+ }
31
+ }
32
+
33
+ const _OAuthLoginViewConfiguration = (
34
+ {
35
+ "ViewIdentifier": "OAuthLogin",
36
+ "TargetElementAddress": "#Pict-Login-Container",
37
+ "ShowOAuthProviders": true
38
+ // All endpoint defaults match orator-authentication:
39
+ // LoginEndpoint: "/1.0/Authenticate" (POST)
40
+ // LogoutEndpoint: "/1.0/Deauthenticate"
41
+ // CheckSessionEndpoint: "/1.0/CheckSession"
42
+ // OAuthProvidersEndpoint: "/1.0/OAuth/Providers"
43
+ // OAuthBeginEndpoint: "/1.0/OAuth/Begin"
44
+ // CheckSessionOnLoad: true
45
+ });
46
+
47
+ class OAuthLoginApplication extends libPictApplication
48
+ {
49
+ constructor(pFable, pOptions, pServiceHash)
50
+ {
51
+ super(pFable, pOptions, pServiceHash);
52
+
53
+ this.pict.addView('OAuthLogin', _OAuthLoginViewConfiguration, OAuthLoginView);
54
+ }
55
+
56
+ onAfterInitialize()
57
+ {
58
+ super.onAfterInitialize();
59
+ let tmpView = this.pict.views.OAuthLogin;
60
+ if (tmpView)
61
+ {
62
+ tmpView.render();
63
+ }
64
+ }
65
+ }
66
+
67
+ module.exports = OAuthLoginApplication;
68
+
69
+ module.exports.default_configuration = (
70
+ {
71
+ "Name": "OAuth Login Example",
72
+ "Hash": "OAuthLoginExample",
73
+ "MainViewportViewIdentifier": "OAuthLogin",
74
+ "pict_configuration":
75
+ {
76
+ "Product": "OAuthLogin-Example"
77
+ }
78
+ });
@@ -0,0 +1,57 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>OAuth Login - Pict Example</title>
7
+ <!-- PICT Dynamic View CSS Container -->
8
+ <style id="PICT-CSS"></style>
9
+ <!-- Red Rock Mesa Theme — Pict Example App -->
10
+ <style>
11
+ *, *::before, *::after { box-sizing: border-box; }
12
+ body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background: #FAEDCD; color: #264653; }
13
+
14
+ /* --- Header Bar --- */
15
+ .pict-example-header { display: flex; align-items: stretch; background: #264653; border-bottom: 3px solid #E76F51; }
16
+ .pict-example-badge { background: #E76F51; color: #fff; padding: 0.6rem 1rem; font-size: 0.7rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; display: flex; align-items: center; gap: 0.5rem; }
17
+ .pict-example-badge svg { width: 14px; height: 14px; fill: #fff; flex-shrink: 0; }
18
+ .pict-example-app-name { padding: 0.6rem 1rem; color: #FAEDCD; font-size: 1.1rem; font-weight: 600; display: flex; align-items: center; }
19
+ .pict-example-module { margin-left: auto; padding: 0.6rem 1rem; color: #D4A373; font-size: 0.75rem; display: flex; align-items: center; letter-spacing: 0.03em; }
20
+
21
+ /* --- Content Area --- */
22
+ .pict-example-content { padding: 1.5rem; }
23
+
24
+ /* --- Info Banner --- */
25
+ .pict-example-info { background: #264653; color: #FAEDCD; border-radius: 6px; padding: 1rem 1.25rem; margin-bottom: 1.5rem; font-size: 0.85rem; line-height: 1.5; }
26
+ .pict-example-info code { background: rgba(250,237,205,0.15); padding: 0.15rem 0.4rem; border-radius: 3px; font-size: 0.8rem; }
27
+ .pict-example-info ul { margin: 0.5rem 0 0 1.25rem; padding: 0; }
28
+ .pict-example-info li { margin-bottom: 0.25rem; }
29
+ </style>
30
+ <script src="./pict.js" type="text/javascript"></script>
31
+ <script type="text/javascript">Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(OAuthLoginExample, 1); });</script>
32
+ </head>
33
+ <body>
34
+ <div class="pict-example-header">
35
+ <div class="pict-example-badge">
36
+ <svg viewBox="0 0 16 16"><polygon points="8,1 10,6 16,6 11,9.5 13,15 8,11.5 3,15 5,9.5 0,6 6,6"/></svg>
37
+ Pict Example
38
+ </div>
39
+ <div class="pict-example-app-name">OAuth Login</div>
40
+ <div class="pict-example-module">pict-section-login</div>
41
+ </div>
42
+ <div class="pict-example-content">
43
+ <div class="pict-example-info">
44
+ This example uses <code>pict-section-login</code> with <strong>OAuth enabled</strong>
45
+ (<code>ShowOAuthProviders: true</code>). It requires:
46
+ <ul>
47
+ <li>A running Orator server with <code>orator-authentication</code></li>
48
+ <li>OAuth providers configured (e.g. Google, Microsoft) in the server&rsquo;s <code>OAuthProviders</code> option</li>
49
+ </ul>
50
+ On load the section queries <code>/1.0/OAuth/Providers</code> and renders branded buttons
51
+ for each configured provider alongside the standard username/password form.
52
+ </div>
53
+ <div id="Pict-Login-Container"></div>
54
+ </div>
55
+ <script src="./oauth_login_example.js" type="text/javascript"></script>
56
+ </body>
57
+ </html>
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "oauth_login_example",
3
+ "version": "1.0.0",
4
+ "description": "OAuth login example — pict-section-login with Google/Microsoft OAuth + standard login",
5
+ "main": "OAuth-Login-Application.js",
6
+ "scripts": {
7
+ "start": "node OAuth-Login-Application.js",
8
+ "build": "npx quack build && npx quack copy"
9
+ },
10
+ "author": "steven velozo <steven@velozo.com>",
11
+ "license": "MIT",
12
+ "devDependencies": {
13
+ },
14
+ "copyFilesSettings": {
15
+ "whenFileExists": "overwrite"
16
+ },
17
+ "copyFiles": [
18
+ {
19
+ "from": "./html/*",
20
+ "to": "./dist/"
21
+ },
22
+ {
23
+ "from": "../../node_modules/pict/dist/*",
24
+ "to": "./dist/"
25
+ }
26
+ ]
27
+ }
@@ -0,0 +1,61 @@
1
+ const libPictApplication = require('pict-application');
2
+ const libPictSectionLogin = require('../../source/Pict-Section-Login.js');
3
+
4
+ /**
5
+ * Standard orator-authentication login.
6
+ *
7
+ * All endpoint defaults already match orator-authentication, so we only
8
+ * need to specify the view identifier and target element. This is the
9
+ * minimal configuration for a production-style integration.
10
+ */
11
+ class OratorLoginView extends libPictSectionLogin
12
+ {
13
+ constructor(pFable, pOptions, pServiceHash)
14
+ {
15
+ super(pFable, pOptions, pServiceHash);
16
+ }
17
+ }
18
+
19
+ const _OratorLoginViewConfiguration = (
20
+ {
21
+ "ViewIdentifier": "OratorLogin",
22
+ "TargetElementAddress": "#Pict-Login-Container"
23
+ // All other settings use defaults that match orator-authentication:
24
+ // LoginEndpoint: "/1.0/Authenticate" (POST)
25
+ // LogoutEndpoint: "/1.0/Deauthenticate"
26
+ // CheckSessionEndpoint: "/1.0/CheckSession"
27
+ // CheckSessionOnLoad: true
28
+ });
29
+
30
+ class OratorLoginApplication extends libPictApplication
31
+ {
32
+ constructor(pFable, pOptions, pServiceHash)
33
+ {
34
+ super(pFable, pOptions, pServiceHash);
35
+
36
+ this.pict.addView('OratorLogin', _OratorLoginViewConfiguration, OratorLoginView);
37
+ }
38
+
39
+ onAfterInitialize()
40
+ {
41
+ super.onAfterInitialize();
42
+ let tmpView = this.pict.views.OratorLogin;
43
+ if (tmpView)
44
+ {
45
+ tmpView.render();
46
+ }
47
+ }
48
+ }
49
+
50
+ module.exports = OratorLoginApplication;
51
+
52
+ module.exports.default_configuration = (
53
+ {
54
+ "Name": "Orator Login Example",
55
+ "Hash": "OratorLoginExample",
56
+ "MainViewportViewIdentifier": "OratorLogin",
57
+ "pict_configuration":
58
+ {
59
+ "Product": "OratorLogin-Example"
60
+ }
61
+ });
@@ -0,0 +1,51 @@
1
+ <!doctype html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8">
5
+ <meta name="viewport" content="width=device-width, initial-scale=1">
6
+ <title>Orator Login - Pict Example</title>
7
+ <!-- PICT Dynamic View CSS Container -->
8
+ <style id="PICT-CSS"></style>
9
+ <!-- Red Rock Mesa Theme — Pict Example App -->
10
+ <style>
11
+ *, *::before, *::after { box-sizing: border-box; }
12
+ body { margin: 0; padding: 0; font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, Helvetica, Arial, sans-serif; background: #FAEDCD; color: #264653; }
13
+
14
+ /* --- Header Bar --- */
15
+ .pict-example-header { display: flex; align-items: stretch; background: #264653; border-bottom: 3px solid #E76F51; }
16
+ .pict-example-badge { background: #E76F51; color: #fff; padding: 0.6rem 1rem; font-size: 0.7rem; font-weight: 800; text-transform: uppercase; letter-spacing: 0.1em; display: flex; align-items: center; gap: 0.5rem; }
17
+ .pict-example-badge svg { width: 14px; height: 14px; fill: #fff; flex-shrink: 0; }
18
+ .pict-example-app-name { padding: 0.6rem 1rem; color: #FAEDCD; font-size: 1.1rem; font-weight: 600; display: flex; align-items: center; }
19
+ .pict-example-module { margin-left: auto; padding: 0.6rem 1rem; color: #D4A373; font-size: 0.75rem; display: flex; align-items: center; letter-spacing: 0.03em; }
20
+
21
+ /* --- Content Area --- */
22
+ .pict-example-content { padding: 1.5rem; }
23
+
24
+ /* --- Info Banner --- */
25
+ .pict-example-info { background: #264653; color: #FAEDCD; border-radius: 6px; padding: 1rem 1.25rem; margin-bottom: 1.5rem; font-size: 0.85rem; line-height: 1.5; }
26
+ .pict-example-info code { background: rgba(250,237,205,0.15); padding: 0.15rem 0.4rem; border-radius: 3px; font-size: 0.8rem; }
27
+ </style>
28
+ <script src="./pict.js" type="text/javascript"></script>
29
+ <script type="text/javascript">Pict.safeOnDocumentReady(() => { Pict.safeLoadPictApplication(OratorLoginExample, 1); });</script>
30
+ </head>
31
+ <body>
32
+ <div class="pict-example-header">
33
+ <div class="pict-example-badge">
34
+ <svg viewBox="0 0 16 16"><polygon points="8,1 10,6 16,6 11,9.5 13,15 8,11.5 3,15 5,9.5 0,6 6,6"/></svg>
35
+ Pict Example
36
+ </div>
37
+ <div class="pict-example-app-name">Orator Login</div>
38
+ <div class="pict-example-module">pict-section-login</div>
39
+ </div>
40
+ <div class="pict-example-content">
41
+ <div class="pict-example-info">
42
+ This example uses <code>pict-section-login</code> with the <strong>default endpoints</strong>
43
+ that match <code>orator-authentication</code>. It requires a running Orator server on the
44
+ same origin with orator-authentication configured. On page load the section automatically
45
+ calls <code>/1.0/CheckSession</code> to restore any existing session from the cookie.
46
+ </div>
47
+ <div id="Pict-Login-Container"></div>
48
+ </div>
49
+ <script src="./orator_login_example.js" type="text/javascript"></script>
50
+ </body>
51
+ </html>
@@ -0,0 +1,27 @@
1
+ {
2
+ "name": "orator_login_example",
3
+ "version": "1.0.0",
4
+ "description": "Standard orator-authentication login example — pict-section-login with default endpoints",
5
+ "main": "Orator-Login-Application.js",
6
+ "scripts": {
7
+ "start": "node Orator-Login-Application.js",
8
+ "build": "npx quack build && npx quack copy"
9
+ },
10
+ "author": "steven velozo <steven@velozo.com>",
11
+ "license": "MIT",
12
+ "devDependencies": {
13
+ },
14
+ "copyFilesSettings": {
15
+ "whenFileExists": "overwrite"
16
+ },
17
+ "copyFiles": [
18
+ {
19
+ "from": "./html/*",
20
+ "to": "./dist/"
21
+ },
22
+ {
23
+ "from": "../../node_modules/pict/dist/*",
24
+ "to": "./dist/"
25
+ }
26
+ ]
27
+ }
package/package.json ADDED
@@ -0,0 +1,53 @@
1
+ {
2
+ "name": "pict-section-login",
3
+ "version": "0.0.1",
4
+ "description": "Pict login section for authentication UIs — works with orator-authentication or any custom backend",
5
+ "main": "source/Pict-Section-Login.js",
6
+ "scripts": {
7
+ "start": "node source/Pict-Section-Login.js",
8
+ "build": "npx quack build",
9
+ "test": "npx quack test",
10
+ "tests": "npx quack test -g",
11
+ "coverage": "npx quack coverage",
12
+ "test-browser": "npx mocha test/Browser_Integration_tests.js --timeout 60000",
13
+ "example": "npx quack examples"
14
+ },
15
+ "repository": {
16
+ "type": "git",
17
+ "url": "git+https://github.com/stevenvelozo/pict-section-login.git"
18
+ },
19
+ "author": "steven velozo <steven@velozo.com>",
20
+ "license": "MIT",
21
+ "bugs": {
22
+ "url": "https://github.com/stevenvelozo/pict-section-login/issues"
23
+ },
24
+ "homepage": "https://github.com/stevenvelozo/pict-section-login#readme",
25
+ "devDependencies": {
26
+ "browser-env": "^3.3.0",
27
+ "pict": "^1.0.350",
28
+ "pict-application": "^1.0.33",
29
+ "puppeteer": "^24.38.0",
30
+ "quackage": "^1.0.59"
31
+ },
32
+ "mocha": {
33
+ "diff": true,
34
+ "extension": [
35
+ "js"
36
+ ],
37
+ "package": "./package.json",
38
+ "reporter": "spec",
39
+ "slow": "75",
40
+ "timeout": "5000",
41
+ "ui": "tdd",
42
+ "watch-files": [
43
+ "source/**/*.js",
44
+ "test/**/*.js"
45
+ ],
46
+ "watch-ignore": [
47
+ "lib/vendor"
48
+ ]
49
+ },
50
+ "dependencies": {
51
+ "pict-view": "^1.0.67"
52
+ }
53
+ }