├── .gitignore ├── backend ├── .gitignore ├── web │ └── index.php ├── config.example.php ├── composer.json ├── tests │ ├── ApplicationTest.php │ └── FeedbackActionTest.php ├── app.php ├── phpunit.xml.dist └── src │ └── Actions │ └── FeedbackAction.php ├── tests ├── fixtures │ ├── titles │ │ ├── 15382769.json │ │ ├── 10391.json │ │ ├── 45093094.json │ │ └── 118613.json │ ├── metadata │ │ ├── Helene_Fischer_2010.jpg.json │ │ ├── Lars_Kindgen.json │ │ ├── Seeteufel.json │ │ ├── Königsberg,_Bavaria.json │ │ ├── Königsberg_in_Bayern.json │ │ ├── Mona_Lisa.jpg.json │ │ ├── CardinalMarkE.jpg.json │ │ ├── John_Flamsteed.jpg.json │ │ ├── Anime-Cosplay_14.JPG.json │ │ ├── Helene Fischer 2010.jpg.json │ │ ├── LRO_Tycho_Central_Peak.jpg.json │ │ ├── Seilsäge.jpg.json │ │ ├── A_Punjab_Village,_1925.webm.json │ │ ├── Cox_and_box.pdf.json │ │ ├── JapaneseToiletControlPanel.jpg.json │ │ ├── 1950_Yankees.jpg.json │ │ ├── Hektor_Philippi.JPG.json │ │ ├── Wien Karlsplatz3.jpg.json │ │ ├── Fiesta-Zuschauer Z1.jpeg.json │ │ ├── NatMonumFengegKapell.jpg.json │ │ ├── Air_France_A380_F-HPJA.jpg.json │ │ ├── Commodore_Plus_4_Knurri.png.json │ │ ├── 05 Air from Suite in C minor.ogg.json │ │ ├── Gerardus_t'_Hooft_at_Harvard.jpg.json │ │ ├── 13-09-29-nordfriesisches-wattenmeer-RalfR-15.jpg.json │ │ ├── Brandenburg gate sunset quadriga.jpg.json │ │ ├── The_Little_Princess_(1939)_full.ogv.json │ │ ├── 1_FC_Bamberg_-_1_FC_Nürnberg_1901.jpg.json │ │ ├── 1871_Proclamation_of_the_German_Empire.jpg.json │ │ ├── Inisheer Gardens 2002 dry-stone walls.jpg.json │ │ └── 03602 - Monti, Gaetano - Allegoria (1832) - Porta Venezia, Milano - Foto Giovanni Dall'Orto 23-Jun-2007.jpg.json │ ├── images │ │ ├── Lars_Kindgen.json │ │ ├── Seeteufel.json │ │ ├── Königsberg,_Bavaria.json │ │ └── Königsberg_in_Bayern.json │ ├── templates │ │ ├── Seilsäge.jpg.json │ │ ├── Fiesta-Zuschauer Z1.jpeg.json │ │ ├── Hektor_Philippi.JPG.json │ │ ├── 1_FC_Bamberg_-_1_FC_Nürnberg_1901.jpg.json │ │ ├── Helene Fischer 2010.jpg.json │ │ ├── 1950_Yankees.jpg.json │ │ ├── JapaneseToiletControlPanel.jpg.json │ │ ├── Commodore_Plus_4_Knurri.png.json │ │ ├── 03602 - Monti, Gaetano - Allegoria (1832) - Porta Venezia, Milano - Foto Giovanni Dall'Orto 23-Jun-2007.jpg.json │ │ ├── Brandenburg gate sunset quadriga.jpg.json │ │ ├── Cox_and_box.pdf.json │ │ ├── NatMonumFengegKapell.jpg.json │ │ ├── 05 Air from Suite in C minor.ogg.json │ │ ├── Gerardus_t'_Hooft_at_Harvard.jpg.json │ │ ├── The_Little_Princess_(1939)_full.ogv.json │ │ ├── Inisheer Gardens 2002 dry-stone walls.jpg.json │ │ ├── CardinalMarkE.jpg.json │ │ ├── Wien Karlsplatz3.jpg.json │ │ ├── LRO_Tycho_Central_Peak.jpg.json │ │ └── John_Flamsteed.jpg.json │ ├── imageinfo │ │ ├── Cscr-featured.svg.json │ │ ├── Anime-Cosplay 14.JPG.json │ │ ├── Germany location map.svg.json │ │ └── Baumeister-Königsberg.JPG.json │ └── revisions │ │ ├── Fiesta-Zuschauer Z1.jpeg.json │ │ └── 1950_Yankees.jpg.json ├── index.html ├── tests.js ├── array-find.js ├── TestHelpers.js ├── app │ ├── DialogueStep.tests.js │ ├── DialogueScreen.tests.js │ ├── Dialogue.tests.js │ ├── Api.local.tests.js │ ├── AttributionDialogue.tests.js │ ├── Api.tests.js │ └── ProgressBarView.tests.js └── LocalApi.js ├── .jshintignore ├── js ├── app │ ├── templates │ │ ├── QuestionMark.handlebars │ │ ├── ImageSuggestion.handlebars │ │ ├── SmallButton.handlebars │ │ ├── MoreInformation.handlebars │ │ ├── Done.handlebars │ │ ├── DialogueScreen.handlebars │ │ ├── ProgressBar.handlebars │ │ ├── PublicDomain.handlebars │ │ ├── InfoBox.handlebars │ │ ├── Dialogue.handlebars │ │ ├── CreatorStep.handlebars │ │ ├── ChangeStep.handlebars │ │ ├── TypeOfUseStep.handlebars │ │ ├── ImagePreview.handlebars │ │ ├── DosAndDonts.handlebars │ │ ├── CompilationStep.handlebars │ │ ├── EditingStep.handlebars │ │ ├── AuthorStep.handlebars │ │ ├── Attribution.handlebars │ │ └── LicenceStep.handlebars │ ├── ChangeStep.js │ ├── views │ │ ├── DialogueStepView.js │ │ ├── ImageSuggestionView.js │ │ ├── ChangeStepView.js │ │ ├── LicenceStepView.js │ │ ├── InfoBoxView.js │ │ ├── PublicDomainDialogueView.js │ │ ├── DialogueScreen.js │ │ └── ProgressBarView.js │ ├── Spinner.js │ ├── Author.js │ ├── LicenceStep.js │ ├── Messages.js │ ├── ApplicationError.js │ ├── BackToTopButton.js │ ├── DialogueStep.js │ ├── Dialogue.js │ ├── AttributionDialogue.js │ ├── WikiAsset.js │ └── ImageInfo.js ├── background.js ├── view_helpers.js └── scrolling_effects.js ├── fonts ├── glyphicons-halflings-regular.eot ├── glyphicons-halflings-regular.ttf ├── glyphicons-halflings-regular.woff └── glyphicons-halflings-regular.woff2 ├── .editorconfig ├── i18n ├── en │ ├── feedback.html │ ├── private-use.html │ ├── legal.html │ └── about.html ├── pl │ ├── feedback.html │ ├── private-use.html │ ├── legal.html │ └── about.html ├── es │ ├── feedback.html │ ├── private-use.html │ ├── legal.html │ └── about.html ├── pt │ ├── feedback.html │ ├── private-use.html │ ├── legal.html │ └── about.html ├── de │ ├── feedback.html │ ├── private-use.html │ ├── legal.html │ └── about.html └── uk │ ├── private-use.html │ └── legal.html ├── .travis.yml ├── css ├── noscript.css └── justifiedGallery.min.css ├── .jshintrc ├── .jscsrc ├── images ├── wikimedia_icon_reload.svg ├── wikimedia_icon_language.svg ├── wikimedia_icon_cc.svg ├── cc.svg └── how_it_works-3.svg ├── package.json ├── index.php └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.idea 2 | node_modules 3 | js/bundle.min.js 4 | -------------------------------------------------------------------------------- /backend/.gitignore: -------------------------------------------------------------------------------- 1 | composer.lock 2 | config.php 3 | vendor/ 4 | -------------------------------------------------------------------------------- /tests/fixtures/titles/15382769.json: -------------------------------------------------------------------------------- 1 | "File:Helene_Fischer_2010.jpg" -------------------------------------------------------------------------------- /tests/fixtures/titles/10391.json: -------------------------------------------------------------------------------- 1 | "File:JapaneseToiletControlPanel.jpg" -------------------------------------------------------------------------------- /tests/fixtures/titles/45093094.json: -------------------------------------------------------------------------------- 1 | "File:A_Punjab_Village,_1925.webm" -------------------------------------------------------------------------------- /tests/fixtures/titles/118613.json: -------------------------------------------------------------------------------- 1 | "File:Gerardus_t%27_Hooft_at_Harvard.jpg" -------------------------------------------------------------------------------- /tests/fixtures/metadata/Helene_Fischer_2010.jpg.json: -------------------------------------------------------------------------------- 1 | Helene Fischer 2010.jpg.json -------------------------------------------------------------------------------- /backend/web/index.php: -------------------------------------------------------------------------------- 1 | run(); 4 | -------------------------------------------------------------------------------- /.jshintignore: -------------------------------------------------------------------------------- 1 | lib/ 2 | **/node_modules 3 | **/*.min.js 4 | **/*.bundle.js 5 | tests/array-find.js 6 | -------------------------------------------------------------------------------- /js/app/templates/QuestionMark.handlebars: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /tests/fixtures/images/Lars_Kindgen.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 8776953, 3 | "ns": 0, 4 | "title": "Lars Kindgen" 5 | } 6 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Lars_Kindgen.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 8776953, 3 | "ns": 0, 4 | "title": "Lars Kindgen" 5 | } 6 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Seeteufel.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 1710912, 3 | "ns": 2, 4 | "title": "User:Seeteufel" 5 | } 6 | -------------------------------------------------------------------------------- /js/app/templates/ImageSuggestion.handlebars: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /js/app/templates/SmallButton.handlebars: -------------------------------------------------------------------------------- 1 | 2 | {{{content}}} 3 | 4 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Königsberg,_Bavaria.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 5933384, 3 | "ns": 0, 4 | "title": "K\u00f6nigsberg, Bavaria" 5 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Königsberg_in_Bayern.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 21330, 3 | "ns": 0, 4 | "title": "K\u00f6nigsberg in Bayern" 5 | } -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmde/Lizenzhinweisgenerator/HEAD/fonts/glyphicons-halflings-regular.eot -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmde/Lizenzhinweisgenerator/HEAD/fonts/glyphicons-halflings-regular.ttf -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmde/Lizenzhinweisgenerator/HEAD/fonts/glyphicons-halflings-regular.woff -------------------------------------------------------------------------------- /fonts/glyphicons-halflings-regular.woff2: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wmde/Lizenzhinweisgenerator/HEAD/fonts/glyphicons-halflings-regular.woff2 -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # http://editorconfig.org 2 | root = true 3 | 4 | [*] 5 | charset = utf-8 6 | indent_style = tab 7 | end_of_line = lf 8 | trim_trailing_whitespace = true 9 | insert_final_newline = true 10 | -------------------------------------------------------------------------------- /tests/fixtures/images/Seeteufel.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 1710912, 3 | "ns": 2, 4 | "title": "User:Seeteufel", 5 | "images": [ 6 | { 7 | "ns": 6, 8 | "title": "File:Anime-Cosplay 14.JPG" 9 | } 10 | ] 11 | } 12 | -------------------------------------------------------------------------------- /js/app/templates/MoreInformation.handlebars: -------------------------------------------------------------------------------- 1 | 7 | -------------------------------------------------------------------------------- /js/app/templates/Done.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 | {{translate 'dialogue.done-headline'}} 4 | {{/inline}} 5 | 6 | {{#*inline 'content'}} 7 | {{text}} 8 | {{/inline}} 9 | {{/dialogueBubble}} 10 | -------------------------------------------------------------------------------- /i18n/en/feedback.html: -------------------------------------------------------------------------------- 1 |

2 | I found a bug! 3 |

4 |

5 | Please let us know if there is something that did not work as intended or could be improved. 6 |

7 |

8 | All kinds of feedback are more than welcome. 9 |

10 | -------------------------------------------------------------------------------- /i18n/pl/feedback.html: -------------------------------------------------------------------------------- 1 |

2 | Znalazłem(-am) błąd! 3 |

4 |

5 | Prosimy, daj nam znać, jeśli coś nie zadziałało tak, jak powinno. 6 |

7 |

8 | Wszystkie rodzaje wiadomości zwrotnych są mile widziane. 9 |

10 | -------------------------------------------------------------------------------- /i18n/es/feedback.html: -------------------------------------------------------------------------------- 1 |

2 | ¡Encontré un error! 3 |

4 |

5 | Por favor, haznos saber si hay algo que no ha funcionado como se esperaba o que podría ser mejorado. 6 |

7 |

8 | Todo tipo de comentarios son bienvenidos. 9 |

10 | -------------------------------------------------------------------------------- /i18n/pt/feedback.html: -------------------------------------------------------------------------------- 1 |

2 | Encontrei um erro! 3 |

4 |

5 | Informe-nos, por favor, se existir algo que não funcione como esperado ou que possa ser melhorado. 6 |

7 |

8 | Todos os comentários são mais do que bem-vindos. 9 |

10 | -------------------------------------------------------------------------------- /backend/config.example.php: -------------------------------------------------------------------------------- 1 | true, 4 | 'swiftmailer.transport' => Swift_SendmailTransport::newInstance('/usr/sbin/sendmail -bs'), 5 | 'feedback_email' => 'mail@example.com', // the email address that receives the feedback 6 | ]; 7 | -------------------------------------------------------------------------------- /i18n/de/feedback.html: -------------------------------------------------------------------------------- 1 |

2 | Ich habe einen Fehler gefunden! 3 |

4 |

5 | Bitte teilen Sie uns hier mit, was nicht wie gedacht funktioniert hat oder verbessert werden sollte. 6 |

7 |

8 | Wir freuen uns natürlich auch über jede andere Art von Rückmeldung. 9 |

-------------------------------------------------------------------------------- /js/app/templates/DialogueScreen.handlebars: -------------------------------------------------------------------------------- 1 |
2 | 3 |
4 |
5 | {{title}} 6 |
7 | 8 | {{{imagePreview}}} 9 | 10 |
11 |
12 | -------------------------------------------------------------------------------- /tests/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | QUnit tests 6 | 7 | 8 | 9 |
10 |
11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /js/app/templates/ProgressBar.handlebars: -------------------------------------------------------------------------------- 1 | 9 | -------------------------------------------------------------------------------- /js/app/templates/PublicDomain.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble noProgressBar=1}} 2 | {{#*inline 'title'}} 3 | {{translate 'dialogue.public-domain-picture'}} 4 | {{/inline}} 5 | 6 | {{#*inline 'content'}} 7 |
8 | {{{translate 'dialogue.public-domain-text'}}} 9 |
10 | {{/inline}} 11 | {{/dialogueBubble}} 12 | -------------------------------------------------------------------------------- /backend/composer.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wmde/attribution_generator", 3 | "autoload": { 4 | "psr-4": { 5 | "AttributionGenerator\\": "src" 6 | } 7 | }, 8 | "require": { 9 | "silex/silex": "~1.3", 10 | "swiftmailer/swiftmailer": "~5.4" 11 | }, 12 | "license": "GPL-2.0+", 13 | "require-dev": { 14 | "symfony/browser-kit": "~2.7" 15 | } 16 | } 17 | -------------------------------------------------------------------------------- /js/app/templates/InfoBox.handlebars: -------------------------------------------------------------------------------- 1 |
2 | {{#unless noCloseButton}} 3 | 4 | {{/unless}} 5 | 6 |
7 | {{{content}}} 8 |
9 | 10 |
11 | {{{buttons}}} 12 |
13 | 14 |
15 |
16 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Seilsäge.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 2725632, 3 | "ns": 6, 4 | "title": "Datei:Seilsäge.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Vorlage:Bild-CC-by-sa/3.0" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Vorlage:Information" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Mona_Lisa.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 51033, 3 | "ns": 6, 4 | "title": "File:Mona Lisa.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/6/6a/Mona_Lisa.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Mona_Lisa.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/templates/Fiesta-Zuschauer Z1.jpeg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 7948879, 3 | "ns": 6, 4 | "title": "Datei:Fiesta-Zuschauer Z1.jpeg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Vorlage:Bild-CC-0" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Vorlage:Information" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /tests/fixtures/templates/Hektor_Philippi.JPG.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 3782721, 3 | "ns": 6, 4 | "title": "Datei:Hektor Philippi.JPG", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Vorlage:Bild-CC-by-sa/3.0/de" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Vorlage:Information" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | 3 | node_js: 4 | - '0.10' 5 | 6 | sudo: false 7 | 8 | install: 9 | - travis_retry npm install qunit-phantomjs-runner jshint jscs 10 | - npm install && npm run build-test 11 | 12 | script: 13 | - phantomjs ./node_modules/qunit-phantomjs-runner/runner.js ./tests/index.html 14 | - ./node_modules/jshint/bin/jshint . 15 | - ./node_modules/jscs/bin/jscs . 16 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/CardinalMarkE.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 30058, 3 | "ns": 6, 4 | "title": "File:CardinalMarkE.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/5/55/CardinalMarkE.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:CardinalMarkE.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/John_Flamsteed.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 72909, 3 | "ns": 6, 4 | "title": "File:John Flamsteed.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/1/19/John_Flamsteed.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:John_Flamsteed.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /backend/tests/ApplicationTest.php: -------------------------------------------------------------------------------- 1 | createClient(); 12 | $client->request( 'GET', '/' ); 13 | $this->assertTrue( $client->getResponse()->isOk() ); 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /js/app/ChangeStep.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | DialogueStep = require( './DialogueStep' ), 5 | ChangeStepView = require( './views/ChangeStepView' ); 6 | 7 | var ChangeStep = function( licence ) { 8 | this._name = 'change'; 9 | this._view = new ChangeStepView( licence ); 10 | }; 11 | 12 | $.extend( ChangeStep.prototype, DialogueStep.prototype ); 13 | 14 | module.exports = ChangeStep; 15 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Anime-Cosplay_14.JPG.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 14660210, 3 | "ns": 6, 4 | "title": "File:Anime-Cosplay 14.JPG", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/7/76/Anime-Cosplay_14.JPG", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Anime-Cosplay_14.JPG", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Helene Fischer 2010.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 15382769, 3 | "ns": 6, 4 | "title": "File:Helene Fischer 2010.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/8/84/Helene_Fischer_2010.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Helene_Fischer_2010.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/LRO_Tycho_Central_Peak.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 15728898, 3 | "ns": 6, 4 | "title": "File:LRO Tycho Central Peak.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/b/b3/LRO_Tycho_Central_Peak.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:LRO_Tycho_Central_Peak.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Seilsäge.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 2725632, 3 | "ns": 6, 4 | "title": "Datei:Seilsäge.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/de/1/11/Seils%C3%A4ge.jpg", 9 | "descriptionurl": "https://de.wikipedia.org/wiki/Datei:Seils%C3%A4ge.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/A_Punjab_Village,_1925.webm.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 45093094, 3 | "ns": 6, 4 | "title": "File:A Punjab Village, 1925.webm", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/8/8e/A_Punjab_Village%2C_1925.webm", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:A_Punjab_Village,_1925.webm", 10 | "mediatype": "VIDEO" 11 | } 12 | ] 13 | } 14 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Cox_and_box.pdf.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 25600734, 3 | "ns": 6, 4 | "title": "File:Cox and box.pdf", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/8/8b/Cox_and_box.pdf", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Cox_and_box.pdf", 10 | "mediatype": "OFFICE" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/JapaneseToiletControlPanel.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 10391, 3 | "ns": 6, 4 | "title": "File:JapaneseToiletControlPanel.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/e/e4/JapaneseToiletControlPanel.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:JapaneseToiletControlPanel.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /css/noscript.css: -------------------------------------------------------------------------------- 1 | .yes-script { 2 | display:none; 3 | } 4 | 5 | .landing-screen { 6 | background-image: url('https://upload.wikimedia.org/wikipedia/commons/3/3a/A_day_of_fishing_aground.jpg'); 7 | } 8 | 9 | .no-script { 10 | background-color: rgba(0, 0, 0, 0.25); 11 | display: block; 12 | top: 60%; 13 | position: absolute; 14 | width: 100%; 15 | padding: 20px 25px; 16 | } 17 | 18 | .no-script h2 { 19 | padding: 0; 20 | margin: 0; 21 | } 22 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/1950_Yankees.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 17475162, 3 | "ns": 6, 4 | "title": "File:1950 Yankees.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/3/3b/1950_Yankees.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:1950_Yankees.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /js/background.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | images = require( '../data/background_images.json' ); 5 | 6 | var daysSince1970 = Math.round( 7 | ( new Date() ).getTime() / ( 60 * 1000 * 60 * 24 ) 8 | ); 9 | 10 | var imageNr = daysSince1970 % images.length; 11 | 12 | $( '#attribution' ).html( images[ imageNr ].attribution ); 13 | $( '#landing-screen' ).css( 14 | 'background-image', 15 | 'url(' + images[ imageNr ].url + ')' 16 | ); 17 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Hektor_Philippi.JPG.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 3782721, 3 | "ns": 6, 4 | "title": "Datei:Hektor Philippi.JPG", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/de/1/14/Hektor_Philippi.JPG", 9 | "descriptionurl": "https://de.wikipedia.org/wiki/Datei:Hektor_Philippi.JPG", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Wien Karlsplatz3.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 180102, 3 | "ns": 6, 4 | "title": "File:Wien Karlsplatz3.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/5/56/Wien_Karlsplatz3.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Wien_Karlsplatz3.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Fiesta-Zuschauer Z1.jpeg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 7948879, 3 | "ns": 6, 4 | "title": "Datei:Fiesta-Zuschauer Z1.jpeg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/de/f/fe/Fiesta-Zuschauer_Z1.jpeg", 9 | "descriptionurl": "https://de.wikipedia.org/wiki/Datei:Fiesta-Zuschauer_Z1.jpeg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/NatMonumFengegKapell.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 16084837, 3 | "ns": 6, 4 | "title": "File:NatMonumFengegKapell.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/9/99/NatMonumFengegKapell.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:NatMonumFengegKapell.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /js/app/templates/Dialogue.handlebars: -------------------------------------------------------------------------------- 1 |
2 | {{#unless noProgressBar}} 3 |
4 | {{/unless}} 5 | 6 |
7 |
8 | 9 |
10 |

11 | {{> title}} 12 |

13 |
14 | {{> content}} 15 |
16 |
17 |
18 |
19 | -------------------------------------------------------------------------------- /js/app/views/DialogueStepView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ); 4 | 5 | /** 6 | * @param {Function} template 7 | * @constructor 8 | */ 9 | var DialogueStepView = function( template ) { 10 | this._template = template; 11 | }; 12 | 13 | $.extend( DialogueStepView.prototype, { 14 | /** 15 | * @type {Function} 16 | */ 17 | _template: null, 18 | 19 | render: function() { 20 | return $( this._template() ); 21 | } 22 | } ); 23 | 24 | module.exports = DialogueStepView; 25 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/Air_France_A380_F-HPJA.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 17330926, 3 | "ns": 6, 4 | "title": "File:Air France A380 F-HPJA.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/d/db/Air_France_A380_F-HPJA.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Air_France_A380_F-HPJA.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Commodore_Plus_4_Knurri.png.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 35393196, 3 | "ns": 6, 4 | "title": "File:Commodore Plus 4 Knurri.png", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/4/4f/Commodore_Plus_4_Knurri.png", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Commodore_Plus_4_Knurri.png", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /js/app/views/ImageSuggestionView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | template = require( '../templates/ImageSuggestion.handlebars' ); 5 | 6 | var ImageSuggestionView = function( imageInfo ) { 7 | this._imageInfo = imageInfo; 8 | }; 9 | 10 | $.extend( ImageSuggestionView.prototype, { 11 | _imageInfo: null, 12 | 13 | render: function() { 14 | return template( { 15 | thumbnail: this._imageInfo.getThumbnail().url 16 | } ); 17 | } 18 | } ); 19 | 20 | module.exports = ImageSuggestionView; 21 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/05 Air from Suite in C minor.ogg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 11995203, 3 | "ns": 6, 4 | "title": "File:05 Air from Suite in C minor.ogg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/4/4a/05_Air_from_Suite_in_C_minor.ogg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:05_Air_from_Suite_in_C_minor.ogg", 10 | "mediatype": "AUDIO" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Gerardus_t'_Hooft_at_Harvard.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 118613, 3 | "ns": 6, 4 | "title": "File:Gerardus t' Hooft at Harvard.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/f/f4/Gerardus_t%27_Hooft_at_Harvard.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Gerardus_t%27_Hooft_at_Harvard.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/13-09-29-nordfriesisches-wattenmeer-RalfR-15.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 28842137, 3 | "ns": 6, 4 | "title": "File:13-09-29-nordfriesisches-wattenmeer-RalfR-15.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/d/df/13-09-29-nordfriesisches-wattenmeer-RalfR-15.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:13-09-29-nordfriesisches-wattenmeer-RalfR-15.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Brandenburg gate sunset quadriga.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 24379, 3 | "ns": 6, 4 | "title": "File:Brandenburg gate sunset quadriga.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/5/57/Brandenburg_gate_sunset_quadriga.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Brandenburg_gate_sunset_quadriga.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/The_Little_Princess_(1939)_full.ogv.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 31180014, 3 | "ns": 6, 4 | "title": "File:The Little Princess (1939) full.ogv", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/5/5a/The_Little_Princess_%281939%29_full.ogv", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:The_Little_Princess_(1939)_full.ogv", 10 | "mediatype": "VIDEO" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/1_FC_Bamberg_-_1_FC_Nürnberg_1901.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 6021018, 3 | "ns": 6, 4 | "title": "Datei:1 FC Bamberg - 1 FC Nürnberg 1901.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/de/f/fb/1_FC_Bamberg_-_1_FC_N%C3%BCrnberg_1901.jpg", 9 | "descriptionurl": "https://de.wikipedia.org/wiki/Datei:1_FC_Bamberg_-_1_FC_N%C3%BCrnberg_1901.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | require( 'qunitjs' ); 4 | require( '../js/view_helpers' ); 5 | require( './app/Api.local.tests' ); 6 | require( './app/InputHandler.local.tests' ); 7 | require( './app/DialogueScreen.tests' ); 8 | require( './app/DialogueStep.tests' ); 9 | require( './app/Dialogue.tests' ); 10 | require( './app/AttributionDialogue.tests' ); 11 | require( './app/AttributionDialogueView.tests' ); 12 | require( './app/LicenceStore.tests' ); 13 | require( './app/DialogueEvaluation.tests' ); 14 | require( './app/ProgressBarView.tests' ); 15 | -------------------------------------------------------------------------------- /tests/fixtures/imageinfo/Cscr-featured.svg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 1112551, 3 | "ns": 6, 4 | "title": "File:Cscr-featured.svg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "thumburl": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/e7/Cscr-featured.svg/300px-Cscr-featured.svg.png", 9 | "thumbwidth": 300, 10 | "thumbheight": 284, 11 | "url": "https://upload.wikimedia.org/wikipedia/commons/e/e7/Cscr-featured.svg", 12 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Cscr-featured.svg" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/1871_Proclamation_of_the_German_Empire.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 358227, 3 | "ns": 6, 4 | "title": "File:1871 Proclamation of the German Empire.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/1/10/1871_Proclamation_of_the_German_Empire.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:1871_Proclamation_of_the_German_Empire.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/fixtures/metadata/Inisheer Gardens 2002 dry-stone walls.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 176181, 3 | "ns": 6, 4 | "title": "File:Inisheer Gardens 2002 dry-stone walls.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/e/ef/Inisheer_Gardens_2002_dry-stone_walls.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Inisheer_Gardens_2002_dry-stone_walls.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /js/view_helpers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var Handlebars = require( 'hbsfy/runtime' ), 4 | Messages = require( './app/Messages' ); 5 | 6 | Handlebars.registerHelper( 'translate', function( s ) { 7 | return Messages.t( s ); 8 | } ); 9 | 10 | Handlebars.registerHelper( 'removeTarget', function( s ) { 11 | return s.replace( /\s+target="_blank"/g, '' ); 12 | } ); 13 | 14 | Handlebars.registerPartial( 'dialogueBubble', require( './app/templates/Dialogue.handlebars' ) ); 15 | Handlebars.registerPartial( 'questionMark', require( './app/templates/QuestionMark.handlebars' ) ); 16 | -------------------------------------------------------------------------------- /tests/fixtures/imageinfo/Anime-Cosplay 14.JPG.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 14660210, 3 | "ns": 6, 4 | "title": "File:Anime-Cosplay 14.JPG", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "thumburl": "https://upload.wikimedia.org/wikipedia/commons/thumb/7/76/Anime-Cosplay_14.JPG/300px-Anime-Cosplay_14.JPG", 9 | "thumbwidth": 300, 10 | "thumbheight": 212, 11 | "url": "https://upload.wikimedia.org/wikipedia/commons/7/76/Anime-Cosplay_14.JPG", 12 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Anime-Cosplay_14.JPG" 13 | } 14 | ] 15 | } 16 | -------------------------------------------------------------------------------- /js/app/templates/CreatorStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 |
4 | {{translate 'dialogue.creator-headline'}} 5 | {{>questionMark target='qm-creator'}} 6 |
7 | 8 |
9 | {{translate 'dialogue.creator-question-mark'}} 10 |
11 | {{/inline}} 12 | 13 | {{#*inline 'content'}} 14 |
15 | 16 |
17 | {{/inline}} 18 | {{/dialogueBubble}} 19 | -------------------------------------------------------------------------------- /tests/fixtures/imageinfo/Germany location map.svg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 35392837, 3 | "ns": 6, 4 | "title": "File:Germany adm location map.svg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "thumburl": "https://upload.wikimedia.org/wikipedia/commons/thumb/e/ed/Germany_adm_location_map.svg/253px-Germany_adm_location_map.svg.png", 9 | "thumbwidth": 253, 10 | "thumbheight": 300, 11 | "url": "https://upload.wikimedia.org/wikipedia/commons/e/ed/Germany_adm_location_map.svg", 12 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Germany_adm_location_map.svg" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /backend/app.php: -------------------------------------------------------------------------------- 1 | register( new Silex\Provider\SwiftmailerServiceProvider() ); 10 | $app['swiftmailer.transport'] = $app['config']['swiftmailer.transport']; 11 | 12 | $app->get( '/', function() { 13 | return 'Hello.'; 14 | } ); 15 | 16 | $app->post( '/feedback', function() use( $app ) { 17 | return ( new AttributionGenerator\Actions\FeedbackAction( $app ) )->getResponse(); 18 | } ); 19 | 20 | return $app; 21 | -------------------------------------------------------------------------------- /js/app/templates/ChangeStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 |
4 | {{headline}} 5 | {{>questionMark target='qm-change'}} 6 |
7 | 8 |
9 | {{translate 'dialogue.change-question-mark'}} 10 |
11 | {{/inline}} 12 | 13 | {{#*inline 'content'}} 14 |
15 |
16 | 17 |
18 |
19 | {{/inline}} 20 | {{/dialogueBubble}} 21 | -------------------------------------------------------------------------------- /tests/fixtures/imageinfo/Baumeister-Königsberg.JPG.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 2157178, 3 | "ns": 6, 4 | "title": "File:Baumeister-K\u00f6nigsberg.JPG", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "thumburl": "https://upload.wikimedia.org/wikipedia/commons/thumb/b/b8/Baumeister-K%C3%B6nigsberg.JPG/225px-Baumeister-K%C3%B6nigsberg.JPG", 9 | "thumbwidth": 225, 10 | "thumbheight": 300, 11 | "url": "https://upload.wikimedia.org/wikipedia/commons/b/b8/Baumeister-K%C3%B6nigsberg.JPG", 12 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:Baumeister-K%C3%B6nigsberg.JPG" 13 | } 14 | ] 15 | } -------------------------------------------------------------------------------- /.jshintrc: -------------------------------------------------------------------------------- 1 | { 2 | // Enforcing options 3 | "bitwise": false, 4 | "curly": true, 5 | "eqeqeq": true, 6 | "forin": false, 7 | "freeze": true, 8 | "latedef": true, 9 | "noarg": true, 10 | "nonew": true, 11 | "strict": false, 12 | "undef": true, 13 | "node": true, 14 | "unused": "vars", 15 | 16 | // Relaxing options 17 | "laxbreak": true, 18 | "scripturl": true, 19 | "shadow": true, 20 | "sub": true, 21 | "supernew": true, 22 | 23 | // Environment 24 | "browser": true, 25 | "dojo": true, 26 | "qunit": true, 27 | "globals": { 28 | "TweenMax": false, 29 | "TimelineMax": false, 30 | "Linear": false 31 | } 32 | } 33 | -------------------------------------------------------------------------------- /backend/phpunit.xml.dist: -------------------------------------------------------------------------------- 1 | 2 | 13 | 14 | 15 | ./tests/ 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /tests/fixtures/images/Königsberg,_Bavaria.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 5933384, 3 | "ns": 0, 4 | "title": "K\u00f6nigsberg, Bavaria", 5 | "images": [ 6 | { 7 | "ns": 6, 8 | "title": "File:Germany location map.svg" 9 | }, 10 | { 11 | "ns": 6, 12 | "title": "File:K\u00f6nigsberg in Bayern in HAS.svg" 13 | }, 14 | { 15 | "ns": 6, 16 | "title": "File:Red pog.svg" 17 | }, 18 | { 19 | "ns": 6, 20 | "title": "File:Regiomontanus-Koenigsberg.JPG" 21 | }, 22 | { 23 | "ns": 6, 24 | "title": "File:Wappen Landkreis Ha\u00dfberge.svg" 25 | }, 26 | { 27 | "ns": 6, 28 | "title": "File:Wappen von K\u00f6nigsberg i.Bay.png" 29 | } 30 | ] 31 | } -------------------------------------------------------------------------------- /js/app/templates/TypeOfUseStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 | {{translate 'dialogue.type-of-use-headline'}} 4 | {{/inline}} 5 | 6 | {{#*inline 'content'}} 7 |
8 |
9 | 13 |
14 | 15 |
16 | 20 |
21 |
22 | {{/inline}} 23 | {{/dialogueBubble}} 24 | -------------------------------------------------------------------------------- /js/app/views/ChangeStepView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | template = require( '../templates/ChangeStep.handlebars' ), 5 | Messages = require( '../Messages' ); 6 | 7 | var ChangeStepView = function( licence ) { 8 | this._licence = licence; 9 | }; 10 | 11 | $.extend( ChangeStepView.prototype, { 12 | render: function() { 13 | var headline; 14 | if( !this._licence.isPublicDomain() ) { 15 | headline = Messages.t( 'dialogue.change-headline' ); 16 | } else { 17 | headline = Messages.t( 'dialogue.change-pd-headline' ); 18 | } 19 | return $( template( { 20 | headline: headline 21 | } ) ); 22 | } 23 | } ); 24 | 25 | module.exports = ChangeStepView; 26 | -------------------------------------------------------------------------------- /js/app/Spinner.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ); 4 | 5 | var Spinner = function( $node ) { 6 | this._$node = $node; 7 | }; 8 | 9 | $.extend( Spinner.prototype, { 10 | /** 11 | * @type {jQuery} 12 | */ 13 | _$node: null, 14 | 15 | /** 16 | * Adds a spinner to a node. 17 | */ 18 | add: function() { 19 | if( this._$node.find( '.ag-spinner' ).length !== 0 ) { 20 | return; 21 | } 22 | 23 | this._$node.prepend( 24 | '
' 25 | ); 26 | }, 27 | 28 | remove: function() { 29 | this._$node.find( '.ag-spinner' ).remove(); 30 | } 31 | } ); 32 | 33 | module.exports = Spinner; 34 | -------------------------------------------------------------------------------- /js/app/templates/ImagePreview.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 | 4 |
5 | 6 |
7 | 8 | 11 |
12 | {{translate 'dialogue.file-page-link'}} 13 |
14 |
15 | -------------------------------------------------------------------------------- /tests/fixtures/templates/1_FC_Bamberg_-_1_FC_Nürnberg_1901.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 6021018, 3 | "ns": 6, 4 | "title": "Datei:1 FC Bamberg - 1 FC Nürnberg 1901.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Vorlage:Bild-PD-alt-100" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Vorlage:Information" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Vorlage:Lizenzdesign2" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Vorlage:Lizenzdesign4" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Vorlage:NoCommons" 25 | } 26 | ] 27 | } -------------------------------------------------------------------------------- /js/app/Author.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author snater.com < wikimedia@snater.com > 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var $ = require( 'jquery' ); 9 | 10 | /** 11 | * Represents a Commons author. 12 | * 13 | * @param {jQuery} $author 14 | * @constructor 15 | */ 16 | var Author = function( $author ) { 17 | this._$author = $author; 18 | }; 19 | 20 | $.extend( Author.prototype, { 21 | /** 22 | * @type {jQuery} 23 | */ 24 | _$author: null, 25 | 26 | /** 27 | * @return {jQuery} 28 | */ 29 | getHtml: function() { 30 | return this._$author.clone(); 31 | }, 32 | 33 | /** 34 | * @return {string} 35 | */ 36 | getText: function() { 37 | return $.trim( this._$author.text() ); 38 | } 39 | 40 | } ); 41 | 42 | module.exports = Author; 43 | -------------------------------------------------------------------------------- /tests/array-find.js: -------------------------------------------------------------------------------- 1 | /* Array.prototype.find polyfill from https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/find */ 2 | if(!Array.prototype.find) { 3 | Array.prototype.find = function(predicate) { 4 | if(this === null) { 5 | throw new TypeError('Array.prototype.find called on null or undefined'); 6 | } 7 | if(typeof predicate !== 'function') { 8 | throw new TypeError('predicate must be a function'); 9 | } 10 | var list = Object(this); 11 | var length = list.length >>> 0; 12 | var thisArg = arguments[1]; 13 | var value; 14 | 15 | for (var i = 0; i < length; i++) { 16 | value = list[i]; 17 | if(predicate.call(thisArg, value, i, list)) { 18 | return value; 19 | } 20 | } 21 | return undefined; 22 | }; 23 | } 24 | -------------------------------------------------------------------------------- /js/app/LicenceStep.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | DialogueStep = require( './DialogueStep' ), 5 | LicenceStore = require( './LicenceStore' ), 6 | config = require( '../config.json' ), 7 | licences = new LicenceStore( require( './LICENCES' ), config.portedLicences ), 8 | LicenceStepView = require( './views/LicenceStepView' ); 9 | 10 | var LicenceStep = function( licence ) { 11 | this._name = 'licence'; 12 | if( licence.isInGroup( 'ported' ) && !licence.isInGroup( 'knownPorted' ) ) { 13 | licence = licences.getLicence( licence.getUnportedVersionId() ); 14 | } 15 | this._view = new LicenceStepView( licence, licences.findCompatibilities( licence.getId() ) ); 16 | }; 17 | 18 | $.extend( LicenceStep.prototype, DialogueStep.prototype ); 19 | 20 | module.exports = LicenceStep; 21 | -------------------------------------------------------------------------------- /tests/fixtures/metadata/03602 - Monti, Gaetano - Allegoria (1832) - Porta Venezia, Milano - Foto Giovanni Dall'Orto 23-Jun-2007.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 3010070, 3 | "ns": 6, 4 | "title": "File:03602 - Monti, Gaetano - Allegoria (1832) - Porta Venezia, Milano - Foto Giovanni Dall'Orto 23-Jun-2007.jpg", 5 | "imagerepository": "local", 6 | "imageinfo": [ 7 | { 8 | "url": "https://upload.wikimedia.org/wikipedia/commons/b/b8/03602_-_Monti%2C_Gaetano_-_Allegoria_%281832%29_-_Porta_Venezia%2C_Milano_-_Foto_Giovanni_Dall%27Orto_23-Jun-2007.jpg", 9 | "descriptionurl": "https://commons.wikimedia.org/wiki/File:03602_-_Monti,_Gaetano_-_Allegoria_(1832)_-_Porta_Venezia,_Milano_-_Foto_Giovanni_Dall%27Orto_23-Jun-2007.jpg", 10 | "mediatype": "BITMAP" 11 | } 12 | ] 13 | } -------------------------------------------------------------------------------- /tests/TestHelpers.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var LicenceStore = require( '../js/app/LicenceStore' ), 4 | Asset = require( '../js/app/Asset' ), 5 | AttributionDialogue = require( '../js/app/AttributionDialogue' ), 6 | AttributionDialogueView = require( '../js/app/views/AttributionDialogueView' ), 7 | licences = new LicenceStore( require( '../js/app/LICENCES' ) ); 8 | 9 | var TestHelpers = { 10 | newDefaultAttributionDialogue: function() { 11 | var dialogue = new AttributionDialogue( new Asset( '', '', licences.getLicence( 'cc-by-2.0' ), null, [] ) ); 12 | dialogue.init(); 13 | 14 | return dialogue; 15 | }, 16 | newDefaultAttributionDialogueView: function() { 17 | return new AttributionDialogueView( new Asset( '', '', licences.getLicence( 'cc' ), null, [] ) ); 18 | } 19 | }; 20 | 21 | module.exports = TestHelpers; 22 | -------------------------------------------------------------------------------- /.jscsrc: -------------------------------------------------------------------------------- 1 | { 2 | "preset": "wikimedia", 3 | 4 | "disallowSpaceAfterKeywords": [ 5 | "catch", 6 | "for", 7 | "if", 8 | "switch", 9 | "while" 10 | ], 11 | "requireSpaceAfterKeywords": [ 12 | "else" 13 | ], 14 | "disallowSpacesInFunctionExpression": { 15 | "beforeOpeningRoundBrace": true 16 | }, 17 | 18 | "disallowDanglingUnderscores": null, 19 | "requireSpacesInsideBrackets": null, 20 | "requireDotNotation": null, 21 | "disallowQuotedKeysInObjects": null, 22 | 23 | "requireMultipleVarDecl": null, // switch to onevar once fixed? 24 | "requireVarDeclFirst": null, // remove once fixed 25 | 26 | "jsDoc": { 27 | "checkTypes": "strictNativeCase" 28 | }, 29 | 30 | "excludeFiles": [ 31 | "**/node_modules/**", 32 | "lib/**", 33 | "**/*.min.js", 34 | "**/*.bundle.js", 35 | "tests/array-find.js" 36 | ] 37 | } 38 | -------------------------------------------------------------------------------- /js/app/templates/DosAndDonts.handlebars: -------------------------------------------------------------------------------- 1 |
2 |
3 |
4 |
5 | 6 |
7 | 8 | {{#each dos}} 9 |

{{translate this}}

10 | {{/each}} 11 |
12 |
13 | 14 |
15 |
16 |
17 | 18 |
19 | 20 | {{#each donts}} 21 |
22 |

23 | 24 | {{translate this.headline}} 25 |

26 | 29 |
30 | {{/each}} 31 |
32 |
33 |
34 | -------------------------------------------------------------------------------- /js/app/templates/CompilationStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 | {{translate 'dialogue.compilation-headline'}} 4 | {{/inline}} 5 | 6 | {{#*inline 'content'}} 7 |
8 |
9 | 13 | 14 | {{>questionMark target='qm-compilation'}} 15 |
16 | {{translate 'dialogue.compilation-question-mark'}} 17 |
18 |
19 | 20 |
21 | 25 |
26 |
27 | {{/inline}} 28 | {{/dialogueBubble}} 29 | -------------------------------------------------------------------------------- /js/app/templates/EditingStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 |
4 | {{translate 'dialogue.editing-headline'}} 5 | {{>questionMark target='qm-editing'}} 6 |
7 | 8 |
9 | {{translate 'dialogue.editing-question-mark'}} 10 |
11 | {{/inline}} 12 | 13 | {{#*inline 'content'}} 14 |
15 |
16 | 20 |
21 | 22 |
23 | 27 |
28 |
29 | {{/inline}} 30 | {{/dialogueBubble}} 31 | -------------------------------------------------------------------------------- /js/app/templates/AuthorStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 |
4 | {{translate 'dialogue.author-headline'}} 5 | {{>questionMark target='author-qm'}} 6 |
7 | 8 |
9 | {{translate 'dialogue.author-question-mark'}} 10 |
11 | {{/inline}} 12 | 13 | {{#*inline 'content'}} 14 |
15 |

{{translate 'dialogue.author-label'}}

16 | 17 |
18 | 19 |
20 | 21 |
22 | 26 |
27 |
28 | {{/inline}} 29 | {{/dialogueBubble}} 30 | -------------------------------------------------------------------------------- /js/app/Messages.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | // Load all i18n.json files available 4 | require( '../../i18n/**/i18n.json', { mode: 'expand' } ); 5 | 6 | var Polyglot = require( 'node-polyglot' ), 7 | i18n; 8 | 9 | var getParam = function getUrlParameter( sParam ) { 10 | var sPageURL = decodeURIComponent( window.location.search.substring( 1 ) ), 11 | sURLVariables = sPageURL.split( '&' ), 12 | sParameterName, 13 | i; 14 | 15 | for( i = 0; i < sURLVariables.length; i++ ) { 16 | sParameterName = sURLVariables[i].split( '=' ); 17 | 18 | if( sParameterName[0] === sParam ) { 19 | return sParameterName[1] === undefined ? true : sParameterName[1]; 20 | } 21 | } 22 | }; 23 | 24 | var lang = getParam( 'lang' ); 25 | if( lang === undefined ) { 26 | lang = 'de'; 27 | } 28 | 29 | try { 30 | i18n = require( '../../i18n/' + lang + '/i18n.json' ); 31 | } catch( e ) { 32 | i18n = require( '../../i18n/de/i18n.json' ); 33 | } 34 | 35 | module.exports = new Polyglot( { phrases: i18n } ); 36 | -------------------------------------------------------------------------------- /js/app/templates/Attribution.handlebars: -------------------------------------------------------------------------------- 1 |
2 |

{{title}}

3 |
4 |
5 | {{{attribution}}} 6 |
7 | 10 | 13 |
14 |
15 | {{#unless isPrint}} 16 | 17 | 18 | 19 | {{/unless}} 20 | 21 | 25 |
26 |
27 | -------------------------------------------------------------------------------- /js/app/ApplicationError.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author snater.com < wikimedia@snater.com > 4 | */ 5 | 'use strict'; 6 | 7 | var $ = require( 'jquery' ), 8 | Messages = require( './Messages' ); 9 | 10 | /** 11 | * Application Error 12 | * @constructor 13 | * 14 | * @param {string} code 15 | * 16 | * @throws {Error} if a required parameter is not defined properly. 17 | */ 18 | var ApplicationError = function( code ) { 19 | if( !code || typeof code !== 'string' ) { 20 | throw new Error( 'Required parameters are nor properly defined' ); 21 | } 22 | 23 | this._code = code; 24 | }; 25 | 26 | $.extend( ApplicationError.prototype, { 27 | /** 28 | * @param {string} 29 | */ 30 | _code: null, 31 | 32 | /** 33 | * Returns the error's localized message. 34 | * 35 | * @return {string} 36 | */ 37 | getMessage: function() { 38 | return Messages.t( 'error.' + this._code ); 39 | }, 40 | 41 | /** 42 | * Returns the error's code. 43 | * 44 | * @return {string} 45 | */ 46 | getCode: function() { 47 | return this._code; 48 | } 49 | 50 | } ); 51 | 52 | module.exports = ApplicationError; 53 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Helene Fischer 2010.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 15382769, 3 | "ns": 6, 4 | "title": "File:Helene Fischer 2010.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-sa-3.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-sa-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:De" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Description" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Dir" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:ISOdate" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Information" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Information/author processing" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Lang" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:License template tag" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Own" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Parse source" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Self" 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /js/app/templates/LicenceStep.handlebars: -------------------------------------------------------------------------------- 1 | {{#>dialogueBubble}} 2 | {{#*inline 'title'}} 3 |
4 | {{translate 'dialogue.licence-headline'}} 5 | {{>questionMark target='qm-licence'}} 6 |
7 | 8 |
9 | {{translate 'dialogue.licence-question-mark'}} 10 |
11 | {{/inline}} 12 | 13 | {{#*inline 'content'}} 14 |
15 |
16 | 22 |
23 | 24 | {{#each compatibles}} 25 |
26 | 30 |
31 | {{/each}} 32 |
33 | {{/inline}} 34 | {{/dialogueBubble}} 35 | -------------------------------------------------------------------------------- /tests/fixtures/templates/1950_Yankees.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 17475162, 3 | "ns": 6, 4 | "title": "File:1950 Yankees.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-1.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Description" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Dir" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:En" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:ISOdate" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Information" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Information/author processing" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:License template tag" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Parse source" 49 | } 50 | ] 51 | } -------------------------------------------------------------------------------- /js/app/BackToTopButton.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ); 4 | var Messages = require( './Messages' ); 5 | 6 | var BackToTopButton = function( content ) { 7 | }; 8 | 9 | $.extend( BackToTopButton.prototype, { 10 | /** 11 | * Renders information about the usage not requiring attributing the author, 12 | * if the asset has been licenced under appropriate licence, or starts the dialogue otherwise. 13 | * 14 | * @param {jQuery} $screen 15 | */ 16 | render: function( $screen ) { 17 | var $btn = $( '' 21 | ); 22 | $btn.bind( 'click', function() { 23 | $( ':input', '#file-form' ) 24 | .not( ':button, :submit, :reset, :hidden' ) 25 | .val( '' ) 26 | .removeAttr( 'checked' ) 27 | .removeAttr( 'selected' ); 28 | 29 | $( 'html, body' ).animate( { 30 | scrollTop: 0 31 | }, 500 ); 32 | setTimeout( function() { 33 | $( '#results-screen' ).hide(); 34 | $( '.dialogue-screen' ).remove(); 35 | }, 500 ); 36 | } ); 37 | $btn.addClass( 'float-right' ); 38 | return $btn; 39 | } 40 | } ); 41 | 42 | module.exports = BackToTopButton; 43 | -------------------------------------------------------------------------------- /images/wikimedia_icon_reload.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Icon Reload neu 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | -------------------------------------------------------------------------------- /js/app/views/LicenceStepView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | template = require( '../templates/LicenceStep.handlebars' ), 5 | LicenceStore = require( '../LicenceStore' ), 6 | config = require( '../../config.json' ), 7 | licences = new LicenceStore( require( '../LICENCES' ), config.portedLicences ), 8 | Messages = require( '../Messages' ); 9 | 10 | var LicenceStepView = function( original, compatibles ) { 11 | this._original = original; 12 | this._compatibles = compatibles; 13 | }; 14 | 15 | $.extend( LicenceStepView.prototype, { 16 | render: function() { 17 | var title, name, url, defaultId; 18 | if( this._original.isPublicDomain() ) { 19 | var cc0Licence = licences.getLicence( 'cc-zero' ); 20 | defaultId = cc0Licence.getId(); 21 | title = Messages.t( 'dialogue.mark-as-pd' ); 22 | name = cc0Licence.getName(); 23 | url = cc0Licence.getUrl(); 24 | } else { 25 | defaultId = 'original'; 26 | title = Messages.t( 'dialogue.same-licence' ); 27 | name = this._original.getName(); 28 | url = this._original.getUrl(); 29 | } 30 | 31 | return $( template( { 32 | defaultChoice: { title: title, name: name, url: url, id: defaultId }, 33 | compatibles: this._compatibles 34 | }, { 35 | allowedProtoMethods: { 36 | getName: true, 37 | getUrl: true, 38 | getId: true 39 | } 40 | } ) ); 41 | } 42 | } ); 43 | 44 | module.exports = LicenceStepView; 45 | -------------------------------------------------------------------------------- /js/app/views/InfoBoxView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | infoBox = require( '../templates/InfoBox.handlebars' ), 5 | cookie = require( 'cookie' ); 6 | 7 | var InfoBoxView = function( name, text, buttons ) { 8 | this._name = name; 9 | this._text = text; 10 | this._buttons = buttons; 11 | this._dismissed = cookie.parse( document.cookie )[ this._name ] === 'hide'; 12 | }; 13 | 14 | $.extend( InfoBoxView.prototype, { 15 | _name: '', 16 | _text: '', 17 | _buttons: '', 18 | _dimissed: false, 19 | 20 | _dontShowAgain: function() { 21 | document.cookie = cookie.serialize( 22 | this._name, 23 | 'hide', 24 | { expires: this._nextYear() } 25 | ); 26 | }, 27 | 28 | _nextYear: function() { 29 | var date = new Date(); 30 | date.setFullYear( date.getFullYear() + 1 ); 31 | return date; 32 | }, 33 | 34 | render: function() { 35 | if( this._dismissed ) { 36 | return ''; 37 | } 38 | 39 | var $box = $( infoBox( { content: this._text, buttons: this._buttons, noCloseButton: this._name === 'ported-licence' } ) ), 40 | self = this; 41 | 42 | $box.find( '.close-info' ).click( function( e ) { 43 | $( this ).parents( '.info-box' ).slideUp(); 44 | self._dismissed = true; 45 | e.preventDefault(); 46 | } ); 47 | $box.find( '.hide-forever' ).click( $.proxy( this._dontShowAgain, this ) ); 48 | 49 | return $box; 50 | } 51 | } ); 52 | 53 | module.exports = InfoBoxView; 54 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "attribution-generator", 3 | "version": "1.0.0", 4 | "description": "", 5 | "main": "js/main.js", 6 | "scripts": { 7 | "build": "browserify -t hbsfy -t require-globify js/main.js | uglifyjs -c > js/bundle.min.js", 8 | "build-test": "browserify -t hbsfy -t require-globify tests/tests.js > tests/tests.bundle.js", 9 | "watch": "watchify -t hbsfy -t require-globify js/main.js -o js/bundle.min.js", 10 | "watch-test": "node_modules/.bin/watchify -t hbsfy -t require-globify tests/tests.js -o tests/tests.bundle.js" 11 | }, 12 | "author": "", 13 | "license": "GPL-3.0", 14 | "browser": { 15 | "scrollmagic-gsap": "scrollmagic/scrollmagic/uncompressed/plugins/animation.gsap" 16 | }, 17 | "devDependencies": { 18 | "browserify": "^17.0.0", 19 | "hbsfy": "^2.4.1", 20 | "qunitjs": "^1.19.0", 21 | "uglify-js": "^2.4.24", 22 | "watchify": "^4.0.0" 23 | }, 24 | "dependencies": { 25 | "bootstrap": "^3.3.5", 26 | "clipboard": "^1.5.5", 27 | "cookie": "^0.2.3", 28 | "gsap": "^3.10.4", 29 | "handlebars": "^4.0.3", 30 | "jquery": "^3.0.0", 31 | "justifiedGallery": "git+https://github.com/miromannino/Justified-Gallery.git#60d253d6963750db2507571612ae0c2d7c2f970d", 32 | "node-polyglot": "^0.4.3", 33 | "piwik": "^1.0.4", 34 | "require-globify": "^1.3.0", 35 | "scrollmagic": "^2.0.5", 36 | "zeroclipboard": "^2.2.0" 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /js/app/DialogueStep.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | DialogueStepView = require( './views/DialogueStepView' ); 5 | 6 | /** 7 | * @param {string} name 8 | * @param {Handlebars} template 9 | * @param {boolean} isPublicDomain 10 | * @constructor 11 | */ 12 | var DialogueStep = function( name, template ) { 13 | this._name = name; 14 | this._view = new DialogueStepView( template ); 15 | }; 16 | 17 | $.extend( DialogueStep.prototype, { 18 | /** 19 | * @type {string} 20 | */ 21 | _name: null, 22 | 23 | /** 24 | * @type {Dialogue} 25 | */ 26 | _dialogue: null, 27 | 28 | /** 29 | * @type {Object} 30 | */ 31 | _data: null, 32 | 33 | /** 34 | * @type {DialogueStepView} 35 | */ 36 | _view: null, 37 | 38 | /** 39 | * @param {Dialogue} dialogue 40 | */ 41 | setDialogue: function( dialogue ) { 42 | this._dialogue = dialogue; 43 | }, 44 | 45 | getName: function() { 46 | return this._name; 47 | }, 48 | 49 | /** 50 | * @param {Object} data - data collected from the dialogue step's form 51 | */ 52 | complete: function( data ) { 53 | this._data = data; 54 | this._dialogue.completeStep( this ); 55 | }, 56 | 57 | /** 58 | * @returns {Object} 59 | */ 60 | getData: function() { 61 | return this._data; 62 | }, 63 | 64 | /** 65 | * @returns {jQuery} 66 | */ 67 | render: function() { 68 | return this._view.render(); 69 | } 70 | } ); 71 | 72 | module.exports = DialogueStep; 73 | -------------------------------------------------------------------------------- /backend/tests/FeedbackActionTest.php: -------------------------------------------------------------------------------- 1 | createClient(); 12 | 13 | $client->request( 14 | 'POST', 15 | '/feedback', 16 | $data 17 | ); 18 | 19 | return $client; 20 | } 21 | 22 | public function testSendFeedback() { 23 | $client = $this->sendWithData( [ 24 | 'name' => 'Alice', 25 | 'feedback' => 'Yay!', 26 | ] ); 27 | 28 | $this->assertTrue( $client->getResponse()->isOk() ); 29 | $this->assertContains( 'Vielen Dank für Dein Feedback', $client->getResponse()->getContent() ); 30 | } 31 | 32 | public function testFailsWithoutName() { 33 | $client = $this->sendWithData( [ 34 | 'name' => '', 35 | 'feedback' => 'Yay!', 36 | ] ); 37 | 38 | $this->assertFalse( $client->getResponse()->isOk() ); 39 | $this->assertContains( 'Alle Felder des Feedback-Formulars müssen ausgefüllt werden', $client->getResponse()->getContent() ); 40 | } 41 | 42 | public function testFailsWithoutFeedback() { 43 | $client = $this->sendWithData( [ 44 | 'name' => 'Bob', 45 | 'feedback' => '', 46 | ] ); 47 | 48 | $this->assertFalse( $client->getResponse()->isOk() ); 49 | $this->assertContains( 'Alle Felder des Feedback-Formulars müssen ausgefüllt werden', $client->getResponse()->getContent() ); 50 | } 51 | } 52 | -------------------------------------------------------------------------------- /tests/fixtures/templates/JapaneseToiletControlPanel.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 10391, 3 | "ns": 6, 4 | "title": "File:JapaneseToiletControlPanel.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-sa-3.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-sa-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Description" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Dir" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:En" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:GFDL-1.3" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:GFDL-1.3/layout" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:GNU-Layout" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:ISOdate" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Information" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Information/author processing" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:LangSwitch" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:License migration" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:License template tag" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Parse source" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:U" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:Unknown" 77 | } 78 | ] 79 | } -------------------------------------------------------------------------------- /i18n/pl/private-use.html: -------------------------------------------------------------------------------- 1 |

2 | Niniejsze narzędzie pomaga w wygenerowaniu odpowiedniej notki licencyjnej dla obrazów na wolnych 3 | licencjach. Informacja taka jest wymagana, kiedy chcesz ponownie opublikować lub wykorzystać 4 | grafikę w sposób, który wymaga (zgodnie z prawem autorskim) zgody od właściciela praw. W myśl prawa, 5 | publikacja zachodzi m.in. podczas publikowania zdjęć na blogu czy w mediach społecznościowych, 6 | ale również kiedy zostaną one rozprowadzone w drukowanej pracy. 7 |

8 |

9 | Jeżeli zamierzasz wykorzystać grafikę do celów prywatnych, wśród swojej rodziny lub znajomych, 10 | nie dotyczą Cię ograniczenia licencyjne. Z tego powodu notka nie jest wymagana. Mimo wszystko, 11 | zalecamy ją umieścić, ponieważ określenie granic użytku wyłącznie prywatnego może być trudne dla osób 12 | niebędących prawnikami. Przykładem użytku prywatnego jest przesłanie zdjęcia do kolegi, czy też 13 | wydrukowanie obrazu i powieszenie go w swoim domu w celach dekoracyjnych. 14 |

15 |

16 | Dodatkowe wyjątki od wymogu uzyskania zgody dysponenta praw autorskich dotyczą 18 | wykorzystania pracy w publikacjach naukowych i w cytatach. W takich przypadkach masz możliwość 19 | wybrania, czy będziesz przestrzegać wyłącznie wymogów ustawowych (jak np. podanie źródła cytatu), 20 | czy też również tych wynikających z warunków licencji Creative Commons. 21 |

22 | -------------------------------------------------------------------------------- /tests/app/DialogueStep.tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | QUnit.module( 'DialogueStep' ); 4 | 5 | var DialogueStep = require( '../../js/app/DialogueStep' ), 6 | Dialogue = require( '../../js/app/Dialogue' ), 7 | Handlebars = require( 'handlebars' ), 8 | $ = require( 'jquery' ); 9 | 10 | QUnit.test( 'should have a name', function( assert ) { 11 | assert.equal( new DialogueStep( 'typeOfUse', new Dialogue() ).getName(), 'typeOfUse' ); 12 | } ); 13 | 14 | QUnit.test( 'should contain data once completed', function( assert ) { 15 | var step = new DialogueStep( 'test' ); 16 | 17 | new Dialogue().addStep( step ); 18 | step.complete( { foo: 'bar' } ); 19 | assert.ok( step._data, '_data attribute contained data' ); 20 | } ); 21 | 22 | QUnit.test( 'should make data accessible', function( assert ) { 23 | var data = { foo: 'bar' }, 24 | step = new DialogueStep( 'test' ); 25 | 26 | new Dialogue().addStep( step ); 27 | step.complete( data ); 28 | assert.equal( data, step.getData() ); 29 | } ); 30 | 31 | QUnit.test( 'should push its data to its Dialogue on completion', function( assert ) { 32 | var dialogue = new Dialogue(), 33 | step = new DialogueStep( 'test', dialogue ); 34 | 35 | dialogue.addStep( step ); 36 | step.complete( { foo: 'bar' } ); 37 | assert.equal( step._data, dialogue._data[ step.getName() ] ); 38 | } ); 39 | 40 | QUnit.test( 'render should return a jQuery object', function( assert ) { 41 | var step = new DialogueStep( 'test', Handlebars.compile( 'hi' ) ); 42 | assert.ok( step.render() instanceof $ ); 43 | } ); 44 | -------------------------------------------------------------------------------- /images/wikimedia_icon_language.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Icon Sprache neu 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | -------------------------------------------------------------------------------- /i18n/en/private-use.html: -------------------------------------------------------------------------------- 1 |

This tool helps you to generate a correct license notice for freely licensed images. Such a 2 | license notice is needed in case you want to republish or reuse a freely licensed image in a way 3 | that requires, under copyright law, permission from the copyright holder. A publication in the 4 | legal sense happens e. g. when posting images on your blog or in social networks as well as 5 | using images in a printed work intended for public dissemination. If you intend to use the image 6 | in a purely private context amongst your family and friends you are not bound by any conditions 7 | imposed by license requirements. Thus, a license notice is not required. However, we would 8 | suggest to provide a license notice anyways as it can be very hard for non-lawyers to assess the 9 | boundaries of purely private use. Private use, in its common meaning, is for instance sending an 10 | image via email to your friends or using a printed image for decorational purposes in your own 11 | home.

12 |

Further legal exceptions to the strict requirement of obtaining permission 14 | from the copyright holder apply for the reuse within the scope of.scientific publications or as 15 | quotes. In such cases you are free to choose whether you want to comply only with the statutory 16 | requirements (e.g. standard requirement to name the source of a quote) or with the Creative 17 | Commons license conditions.

18 | -------------------------------------------------------------------------------- /i18n/pt/private-use.html: -------------------------------------------------------------------------------- 1 |

Esta ferramenta ajuda a gerar um aviso de licença correto para imagens licenciadas com licenças livres. Tal aviso de licença é necessário no caso de você querer republicar ou reutilizar uma imagem licenciada com uma licença livre de um modo que requer, de acordo com a legislação de direito de autor, a autorização do titular do direito de autor. Uma publicação em sentido jurídico ocorre, por exemplo, quando você publica imagens no seu blog ou nas redes sociais, bem como quando usa as imagens num trabalho impresso destinado a divulgação pública. Se você pretende usar a imagem num contexto puramente privado, entre a sua família e amigos, você não está sujeito a nenhuma das condições impostas pela licença. Portanto, um aviso de licença não é necessário. No entanto, sugerimos que forneça o aviso da licença de qualquer forma, já que pode ser muito difícil para os que não são advogados avaliar os limites do uso puramente privado. O uso privado, na sua acepção comum, é, por exemplo, enviar uma imagem por e-mail para os seus amigos ou usar uma imagem impressa para fins decorativos na sua própria casa.

2 |

Complementar as exceções legais com a condição estrita de obter autorização do titular do direito de autor aplica-se à reutilização no âmbito das publicações científicas ou como citações. Nestes casos, você é livre de escolher se deseja cumprir apenas os requisitos legais (p. ex., o requisito standard de nomear a fonte de uma citação) ou as condições da licença Creative Commons.

4 | -------------------------------------------------------------------------------- /i18n/uk/private-use.html: -------------------------------------------------------------------------------- 1 |

Цей інструмент допомогає створити правильне ліцензійне повідомлення для вільноліцензованих 2 | зображень. Таке ліцензійне повідомлення потрібне, якщо ви хочете повторно опублікувати чи 3 | використати зображення під вільною ліцензією у спосіб, який вимагає дозволу від правовласника, 4 | згідно з законодавством про авторські права. Публікація в юридичному сенсі стається, наприклад, 5 | під час розміщення зображень у своєму блозі чи в соціальних мережах, а також при використанні 6 | зображень у друкованих виданнях, що призначені для публічного розповсюдження. Якщо ви маєте 7 | намір використовувати зображення суто приватно, в колі друзів і сім'ї, ви не зв'язані жодними 8 | умовами ліцензійних угод, а значить, ліцензійне повідомлення не потрібне. Однак ми б радили 9 | все одно подавати ліцензійне повідомлення, оскільки не-юристам може бути складно розгледіти 10 | межу суто приватного використання. Приватне використання, у загальному розумінні, це, наприклад, 11 | надсилання зображення електронною поштою друзям або використання надрукованого зображення для 12 | декорації власного помешкання.

13 |

Інші юридичні винятки зі строгих вимог до отримання дозволу від правоволасника 15 | стосуються повторного використання в наукових публікаціях чи як цитат. У таких випадках, ви 16 | вільні обирати, чи хочете виконати лише встановлені вимоги (наприклад, стандарну вимогу про 17 | вказання джерела цитати), чи умови ліцензії Creative Commons.

18 | -------------------------------------------------------------------------------- /images/wikimedia_icon_cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | Icon Lizenz 5 | Created with Sketch. 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Commodore_Plus_4_Knurri.png.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 35393196, 3 | "ns": 6, 4 | "title": "File:Commodore Plus 4 Knurri.png", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-sa-4.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-sa-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Description" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Dir" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:En" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:ISOdate" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Information" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Information/author processing" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Lang" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:License template tag" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Own" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Parse source" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Self" 61 | } 62 | ] 63 | } -------------------------------------------------------------------------------- /i18n/es/private-use.html: -------------------------------------------------------------------------------- 1 |

Esta herramienta ayuda a generar un aviso de licencia correcto para las imágenes bajo licencia libre. Este aviso de licencia es necesario en el caso de que quieras re-publicar o reutilizar una imagen con licencia libre de manera que requiera, bajo la ley de propiedad intelectual, el permiso del titular de los derechos de autor. Una publicación (en el sentido legal) ocurre, por ejemplo, cuando publicas imágenes en tu blog o en redes sociales, de así como al utilizar las imágenes en un trabajo impreso con el objetivo de su divulgación pública. Si tu intención es utilizar la imagen en un contexto puramente privado, entre tu familia o amigos, no estás sujeto a ninguna de las condiciones impuestas por la licencia. Por lo tanto, utilizar un aviso de licencia no es necesario. Sin embargo, nosotros sugerimos adjuntar el aviso de licencia de todas formas, ya que puede ser muy complicado para quienes no sean abogados evaluar los límites del uso puramente privado. El uso privado, en su significado común, es, por ejemplo, enviar una imagen por correo electrónico a tus amigos o utilizar una imagen impresa con propósitos decorativos en tu propia casa.

2 |

Promover las excepciones legales al requisito estricto de obtener permiso del titular de los derechos de autor se aplica a su reutilización dentro del alcance de las publicaciones científicas o de las citas. En estos casos, eres libre de elegir si deseas cumplir solamente con los requisitos legales (p. ej. el requisito estandar de nombrar la fuente de una cita) o con las condiciones de la licencia de Creative Commons.

4 | -------------------------------------------------------------------------------- /js/app/Dialogue.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | Tracking = require( '../tracking.js' ); 5 | 6 | var Dialogue = function() { 7 | this._steps = []; 8 | this._data = {}; 9 | this._currentStep = 0; 10 | this._tracking = new Tracking(); 11 | }; 12 | 13 | $.extend( Dialogue.prototype, { 14 | /** 15 | * @type {DialogueStep[]} 16 | */ 17 | _steps: null, 18 | 19 | /** 20 | * @type {Object} 21 | */ 22 | _data: null, 23 | 24 | /** 25 | * @type {int} 26 | */ 27 | _currentStep: null, 28 | 29 | /** 30 | * @param {DialogueStep} step 31 | */ 32 | addStep: function( step ) { 33 | step.setDialogue( this ); 34 | this._steps.push( step ); 35 | }, 36 | 37 | /** 38 | * @param {int} n 39 | */ 40 | setStep: function( n ) { 41 | this._currentStep = n; 42 | }, 43 | 44 | /** 45 | * @param {DialogueStep} step 46 | */ 47 | completeStep: function( step ) { 48 | var self = this; 49 | 50 | this._data[ step.getName() ] = step.getData(); 51 | this._currentStep++; 52 | 53 | self._tracking.trackEvent( 'Progress', 'Step', step.getName() ); 54 | if( !self.currentStep() ) { 55 | self._tracking.trackEvent( 'Progress', 'Done' ); 56 | } 57 | }, 58 | 59 | /** 60 | * @returns {Object} 61 | */ 62 | getData: function() { 63 | return this._data; 64 | }, 65 | 66 | /** 67 | * @returns {DialogueStep} 68 | */ 69 | currentStep: function() { 70 | return this._steps[ this._currentStep ]; 71 | }, 72 | 73 | /** 74 | * @returns {int} 75 | */ 76 | currentStepIndex: function() { 77 | return this._currentStep; 78 | }, 79 | 80 | getSteps: function() { 81 | return this._steps; 82 | } 83 | } ); 84 | 85 | module.exports = Dialogue; 86 | -------------------------------------------------------------------------------- /tests/fixtures/templates/03602 - Monti, Gaetano - Allegoria (1832) - Porta Venezia, Milano - Foto Giovanni Dall'Orto 23-Jun-2007.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 3010070, 3 | "ns": 6, 4 | "title": "File:03602 - Monti, Gaetano - Allegoria (1832) - Porta Venezia, Milano - Foto Giovanni Dall'Orto 23-Jun-2007.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:Attribution" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Copyrighted-Layout" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Description" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Dir" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:En" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:ISOdate" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Iffile" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Ifimage" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Information" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Information/author processing" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:It" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:License template tag" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Parse source" 57 | } 58 | ] 59 | } -------------------------------------------------------------------------------- /js/scrolling_effects.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | ScrollMagic = require( 'scrollmagic' ); 5 | require( 'gsap' ); 6 | require( 'scrollmagic-gsap' ); 7 | 8 | var controller = new ScrollMagic.Controller(); 9 | 10 | var fadeHeadingUp = TweenMax.fromTo( 11 | '.top-wrapper', 12 | 1, 13 | { opacity: 0, top: '15%' }, 14 | { opacity: 1, top: 0 } 15 | ); 16 | var moveTextboxUp = TweenMax.fromTo( 17 | '#file-form', 18 | 1, 19 | { top: 0 }, 20 | { top: '60%', ease: Linear.easeNone } 21 | ); 22 | 23 | var upTweens = new TimelineMax(); 24 | upTweens.add( [ fadeHeadingUp, moveTextboxUp ] ); 25 | 26 | var upSceneOffset = function() { 27 | return $( '#landing-screen' ).height() / 5; 28 | }; 29 | 30 | var up = new ScrollMagic.Scene( { 31 | triggerElement: '#landing-screen', 32 | triggerHook: 'onEnter', 33 | offset: upSceneOffset(), 34 | duration: '80%' 35 | } ) 36 | .setTween( upTweens ); 37 | 38 | $( window ).resize( function() { 39 | up.offset( upSceneOffset() ); 40 | } ); 41 | 42 | var moveTextboxDown = TweenMax.to( 43 | '#file-form', 44 | 1, 45 | { top: '100%', marginTop: '-82px' } 46 | ); 47 | var fadeHeadingDown = TweenMax.to( 48 | '.top-wrapper', 49 | 1, 50 | { marginTop: '20vh', opacity: 0 } 51 | ); 52 | var fadeAttributionDown = TweenMax.to( 53 | '.attribution', 54 | 1, 55 | { bottom: '20%', opacity: 0 } 56 | ); 57 | 58 | var downTweens = new TimelineMax(); 59 | downTweens.add( [ fadeHeadingDown, moveTextboxDown, fadeAttributionDown ] ); 60 | 61 | var down = new ScrollMagic.Scene( { 62 | triggerElement: '#landing-screen', 63 | triggerHook: 'onLeave', 64 | duration: '80%' 65 | } ) 66 | .setTween( downTweens ); 67 | 68 | controller.addScene( [ up, down ] ); 69 | -------------------------------------------------------------------------------- /tests/app/DialogueScreen.tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | QUnit.module( 'DialogueScreen' ); 4 | 5 | var Asset = require( '../../js/app/Asset' ), 6 | DialogueScreen = require( '../../js/app/views/DialogueScreen' ), 7 | ImageInfo = require( '../../js/app/ImageInfo' ), 8 | LicenceStore = require( '../../js/app/LicenceStore' ), 9 | licences = new LicenceStore( require( '../../js/app/LICENCES' ) ), 10 | Messages = require( '../../js/app/Messages' ), 11 | $ = require( 'jquery' ); 12 | 13 | function newDialogueScreenForLicence( licenceId ) { 14 | return new DialogueScreen( 15 | new ImageInfo( 'foo', 'bar', 1337, { url: 'baz', width: 1337, height: 1337 } ), 16 | new Asset( '', '', licences.getLicence( licenceId ), null, [] ) 17 | ); 18 | } 19 | 20 | function dialogueHeaderContains( $dialogue, text ) { 21 | return $dialogue.find( '.dialogue-header' ).text().indexOf( Messages.t( text ) ) > -1; 22 | } 23 | 24 | QUnit.test( 'Given Public Domain asset, no atribution obligation information is displayed', function( assert ) { 25 | var $dialogue = $( '
' ); 26 | newDialogueScreenForLicence( 'PD' ).render( $dialogue ); 27 | assert.ok( dialogueHeaderContains( $dialogue, 'dialogue.no-attribution-needed' ) ); 28 | } ); 29 | 30 | QUnit.test( 'Given CC0 asset, no atribution obligation information is displayed', function( assert ) { 31 | var $dialogue = $( '
' ); 32 | newDialogueScreenForLicence( 'cc-zero' ).render( $dialogue ); 33 | assert.ok( dialogueHeaderContains( $dialogue, 'dialogue.no-attribution-needed' ) ); 34 | } ); 35 | 36 | QUnit.test( 'Given asset licenced under CC-BY-SA-4.0, the dialogue is displayed', function( assert ) { 37 | var $dialogue = $( '
' ); 38 | newDialogueScreenForLicence( 'cc-by-sa-4.0' ).render( $dialogue ); 39 | assert.ok( dialogueHeaderContains( $dialogue, 'dialogue.adjust-attribution-for-usage' ) ); 40 | } ); 41 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Brandenburg gate sunset quadriga.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 24379, 3 | "ns": 6, 4 | "title": "File:Brandenburg gate sunset quadriga.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-sa-2.5,2.0,1.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-sa-3.0-migrated" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Cc-by-sa-layout" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:De" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Description" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Dir" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:En" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:GFDL" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:GNU-Layout" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Lang" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:License migration" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:License migration is redundant" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:License migration is redundant multiple" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:License template tag" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Self" 69 | } 70 | ] 71 | } -------------------------------------------------------------------------------- /i18n/pl/legal.html: -------------------------------------------------------------------------------- 1 |

2 | Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. 3 |
Tempelhofer Ufer 23/24 4 |
10963 Berlin 5 |
E-mail: info@wikimedia.de 6 |
WWW: https://wikimedia.de 7 |
Telefon: +49 (0)30-577 11 62-0 8 |
Fax: +49 (0)30-577 11 62-99 9 |

10 |

11 | Dyrektor wykonawczy: Franziska Heine 12 |
Zapisane w rejestrze stowarzyszeń sądu rejonowego Berlin-Charlottenburg, VR 23855. 13 | Osoba odpowiedzialna za treść, zgodnie z § 18 Abs. 2 MStV: Franziska Heine (adres powyżej). 14 |

15 |

16 | Kompletny kod źródłowy Generatora Atrybucji jest dostępny na licencji GNU General Public Licence 17 | (GPL v3). Kod źródłowy 18 | znajduje się na GitHubie, 19 | gdzie można go wyświetlić, pobrać oraz modyfikować. Treść objęta jest licencją Creative 21 | Commons Attribution - ShareAlike 4.0 International i może być modyfikowana i wykorzystywana 22 | lub publikowana ponownie zgodnie z jej warunkami. 23 |

24 |

25 | Polityka prywatności 26 |

27 |

28 | Na wikimedia.de znajdziesz informacje, 29 | co dzieje się z twoimi danymi osobowymi, kiedy odwiedzasz tę lub inne strony Wikimedia Deutschland. 30 |

31 |

32 | Możesz zdecydować, czy niniejsze narzędzie ma tworzyć w Twojej przeglądarce plik cookie, służący 33 | do analizy różnych danych dotyczących Twojej wizyty na tej stronie. Jeśli się nie zgadzasz, kliknij 34 | na poniższe pole, by stworzyć w przeglądarce ciasteczko dezaktywujące ten mechanizm. 35 |

36 | -------------------------------------------------------------------------------- /i18n/de/private-use.html: -------------------------------------------------------------------------------- 1 |

Diese Anwendung hilft Ihnen dabei, korrekte Lizenzhinweise für frei lizenzierte Bilder zu 2 | erstellen. Sie benötigen einen solchen Lizenzhinweis, wenn Sie ein frei lizenziertes Bild selbst 3 | erneut veröffentlichen oder anderweitig in einer Weise nachnutzen möchten, die nach dem 4 | Urheberrechtsgesetz eine Erlaubnis des Urhebers voraussetzt. Unter einer Veröffentlichung 5 | versteht man z.B. das Posten eines Bildes auf Ihrem Blog, in sozialen Netzwerken oder die 6 | Abbildung in einem zum Vertrieb bestimmten Druckerzeugnis. Möchten Sie das gewählte Bild in 7 | einem rein privaten 8 | Kontext verwenden, der nur Freunden und Familie zugänglich ist, brauchen Sie sich nicht 9 | an irgendwelche Lizenzbedingungen zu halten und somit auch keinen Lizenzhinweis anzubringen. Wir 10 | möchten Ihnen dies trotzdem empfehlen, weil es mitunter für juristische Laien schwierig sein 11 | kann, die genauen Grenzen der rein privaten Verwendung zu ermitteln. Unter einer privaten 12 | Nutzung versteht man z.B. das Versenden an Freunde per E-Mail oder den Druck eines Bildes für 13 | die eigenen Wohnräume.

14 |

Weitere gesetzliche Ausnahmen von der strengen Anforderung, eine Erlaubnis des Urhebers 15 | einzuholen, gelten für die Nachnutzung im Rahmen wissenschaftlicher Publikationen oder als Zitat. 19 | In diesen Fällen können Sie wählen, ob Sie nur die gesetzlichen Vorgaben (beim Zitat z.B. 20 | normale Quellenangabe) oder stattdessen die Lizenzbedingungen der Creative-Commons-Lizenz 21 | einhalten möchten.

-------------------------------------------------------------------------------- /i18n/pt/legal.html: -------------------------------------------------------------------------------- 1 |

2 | Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. 3 |
Tempelhofer Ufer 23/24 4 |
10963 Berlim 5 |
Correio electrónico: info@wikimedia.de 6 |
Sítio Web: https://wikimedia.de https://wikimedia.de 7 |
Telefone: +49 (0)30-577 11 62-0 8 |
Fax: +49 (0)30-577 11 62-99 9 |

10 |

11 | Diretor executivo: Franziska Heine 12 |
Registado no registo de associações do tribunal distrital de Berlim-Charlotteburg, VR 23855. Pessoa responsável pelo conteúdo, de acordo com o artigo § 18 Abs. 2 MStV: Franziska Heine (veja o endereço acima). 13 |

14 |

15 | O código-fonte completo do Gerador de Atribuição está disponível sob a ( Licença Pública Geral GNU). O código-fonte está disponível no GitHub, onde pode ser visto, descarregado, modificado e republicado. Todos os textos desta ferramenta estão disponíveis sob uma licença 16 | Creative Commons Atribuição - CompartilhaIgual 4.0 Internacional e pode ser reutilizado, modificado e republicado, de acordo com as condições desta licença. 17 |

18 |

19 | Política de Privacidade 20 |

21 |

22 | Em wikimedia.de encontrará todas as informações sobre o que acontece com seus dados pessoais quando visita este ou outros sites da Wikimedia Deutschland. 23 |

24 |

25 | Aqui você pode decidir se esta ferramenta tem permissão para criar um cookie de análise da Web no seu navegador, o qual pode ajudar-nos a avaliar e analisar diferentes dados da sua visita à página. Se você é contra isto, clique no link para criar um cookie que desabilita o Piwik no seu navegador. 26 |

27 | -------------------------------------------------------------------------------- /i18n/es/legal.html: -------------------------------------------------------------------------------- 1 |

2 | Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. 3 |
Tempelhofer Ufer 23/24 4 |
10963 Berlin 5 |
Correo electrónico: info@wikimedia.de 6 |
Sitio web: https://wikimedia.de 7 |
Teléfono: +49 (0)30-577 11 62-0 8 |
Fax: +49 (0)30-577 11 62-99 9 |

10 |

11 | Director ejecutivo: Franziska Heine 12 |
Registrada en el registro de asociaciones del tribunal del distrito de Berlin-Charlotteburg, VR 23855. Persona responsable del contenido conforme al artículo § 18 Abs. 2 MStV: Franziska Heine (véase la dirección arriba). 13 |

14 |

15 | El código fuente completo del Generador de Atribución está disponible bajo la GNU General Public License (GPL v3). El código fuente está disponible en GitHub, 16 | donde puede ser visualizado, descargado, modificado y republicado. Todos los textos de esta herramienta están disponibles bajo la 17 | licencia Creative Commons Atribución - CompartirIgual 4.0 Internacional y pueden ser reutilizados, modificados y republicados sujetos a las condiciones de esta licencia. 18 |

19 |

20 | Política de privacidad 21 |

22 |

23 | En wikimedia.de encontrará toda la información sobre lo que sucede con sus datos personales cuando visita este u otros sitios web de Wikimedia Deutschland. 24 |

25 |

26 | Aquí puedes decidir si permites que esta herramienta cree una cookie de análisis web en tu navegador, que podría ayudarnos a evaluar y analizar diferentes datos de tu visita a la página. Si estás en contra de esto, por favor, haz clic en el enlace para crear una cookie de desactivación de Piwik en tu navegador. 27 |

28 | -------------------------------------------------------------------------------- /tests/app/Dialogue.tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | QUnit.module( 'Dialogue' ); 4 | 5 | var Dialogue = require( '../../js/app/Dialogue' ), 6 | DialogueStep = require( '../../js/app/DialogueStep' ); 7 | 8 | QUnit.test( 'can contain steps', function( assert ) { 9 | var dialogue = new Dialogue, 10 | step1 = new DialogueStep( 'test1' ), 11 | step2 = new DialogueStep( 'test2' ); 12 | 13 | dialogue.addStep( step1 ); 14 | dialogue.addStep( step2 ); 15 | 16 | assert.equal( dialogue._steps.length, 2 ); 17 | } ); 18 | 19 | QUnit.test( 'addStep connects step and dialogue', function( assert ) { 20 | var dialogue = new Dialogue, 21 | step = new DialogueStep( 'test1' ); 22 | 23 | assert.notOk( step._dialogue ); 24 | dialogue.addStep( step ); 25 | assert.ok( step._dialogue ); 26 | } ); 27 | 28 | QUnit.test( 'getData should return data from all completed steps', function( assert ) { 29 | var dialogue = new Dialogue, 30 | step1 = new DialogueStep( 'test1' ), 31 | step2 = new DialogueStep( 'test2' ), 32 | step1Data = { foo: 'bar' }, 33 | step2Data = { omg: 'bbq' }; 34 | dialogue.addStep( step1 ); 35 | dialogue.addStep( step2 ); 36 | step1.complete( step1Data ); 37 | step2.complete( step2Data ); 38 | 39 | var data = dialogue.getData(); 40 | assert.equal( step1Data, data[ step1.getName() ] ); 41 | assert.equal( step2Data, data[ step2.getName() ] ); 42 | } ); 43 | 44 | QUnit.test( 'completing a step should increment the current step pointer', function( assert ) { 45 | var dialogue = new Dialogue, 46 | step1 = new DialogueStep( 'first' ), 47 | step2 = new DialogueStep( 'second' ); 48 | 49 | dialogue.addStep( step1 ); 50 | dialogue.addStep( step2 ); 51 | 52 | assert.equal( dialogue.currentStep().getName(), 'first' ); 53 | step1.complete( {} ); 54 | assert.equal( dialogue.currentStep().getName(), 'second' ); 55 | } ); 56 | 57 | QUnit.test( 'setStep sets current step pointer', function( assert ) { 58 | var dialogue = new Dialogue(); 59 | dialogue.setStep( 3 ); 60 | 61 | assert.equal( dialogue._currentStep, 3 ); 62 | } ); 63 | -------------------------------------------------------------------------------- /i18n/en/legal.html: -------------------------------------------------------------------------------- 1 |

2 | Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. 3 |
Tempelhofer Ufer 23/24 4 |
10963 Berlin 5 |
E-Mail: info@wikimedia.de 6 |
Website: https://wikimedia.de 7 |
Telephone: +49 (0)30-577 11 62-0 8 |
Fax: +49 (0)30-577 11 62-99 9 |

10 |

11 | Executive Director: Franziska Heine 12 |
Listed in the associations register of the district court of Berlin-Charlottenburg, VR 13 | 23855. Person responsible for content pursuant to § 18 Abs. 2 MStV: Franziska Heine (Address 14 | see above). 15 |

16 |

17 | The complete source code of the Attribution Generator is available under the GNU General Public 18 | Licence (GPL v3). The 19 | source code is available on GitHub, where it can be viewed, downloaded, 21 | modified and republished. All texts of this tool are available under the Creative 23 | Commons Attribution - ShareAlike 4.0 International license and can be reused, modified and 24 | republished subject to the conditions of that license. 25 |

26 |

27 | Privacy Policy 28 |

29 |

30 | On wikimedia.de you will find all 31 | information about what happens to your personal data when you visit this or other Wikimedia 32 | Deutschland websites. 33 |

34 | 40 | -------------------------------------------------------------------------------- /i18n/uk/legal.html: -------------------------------------------------------------------------------- 1 |

2 | Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. 3 |
Tempelhofer Ufer 23/24 4 |
10963 Berlin 5 |
Ел. пошта: info@wikimedia.de 6 |
Веб-сайт: https://wikimedia.de 7 |
Телефон: +49 (0)30-577 11 62-0 8 |
Факс: +49 (0)30-577 11 62-99 9 |

10 |

11 | Виконавчий директор: Franziska Heine 12 |
Знаходиться в реєстрі асоціацій району Берлін-Шарлоттенбург, VR 23855. 13 | Відповідальна особа, відповідно до § 18 абз. 2 MStV: Franziska Heine (адресу див. вище). 14 |

15 |

16 | Повний вихідний код Генератора атрибуції доступний на умовах ліцензії GNU General Public 17 | Licence (GPL v3). 18 | Вихідний код також доступний у GitHub, де його можна переглядати, завантажувати, модифікувати та повторно 20 | публікувати. Усі тексти цього інструменту доступні на умовах ліцензії Creative 22 | Commons із зазначенням авторства — поширення на тих самих умовах 4.0 міжнародна, і можуть 23 | бути повторно використані, модифіковані й повторно опубліковані згідно з умовами цієї 24 | ліцензії. 25 |

26 |

27 | Політика приватності 28 |

29 |

30 | На wikimedia.de ви знайдете всю 31 | інформацію про те, що відбувається з вашими персональними даними під час відвідування цього чи 32 | інших сайтів Wikimedia Deutschland. 33 |

34 |

35 | Тут ви можете вирішити, чи дозволяти цьому інструменту створювати куки веб-аналізу у вашому 36 | браузері, що допоможе нам оцінювати та аналізувати різні дані про ваше відвідування сторінки. 37 | Якщо ви не згодні з цим, будь ласка, перейдіть за посиланням, що створити куки деактивації 38 | Piwik у вашому браузері. 39 |

40 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Cox_and_box.pdf.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 25600734, 3 | "ns": 6, 4 | "title": "File:Cox and box.pdf", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:Autotranslate" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-pd-mark-footer" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Description" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Dir" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:En" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:ISOdate" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Information" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Information/author processing" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Lang" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:License template tag" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Max" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:PD-Layout" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:PD-US" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:PD-US/en" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:PD-US/layout" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:PD-old" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:PD-old/en" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:PD-old/layout" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:Parse source" 81 | } 82 | ] 83 | } -------------------------------------------------------------------------------- /i18n/de/legal.html: -------------------------------------------------------------------------------- 1 |

2 | Wikimedia Deutschland – Gesellschaft zur Förderung Freien Wissens e. V. 3 |
Tempelhofer Ufer 23/24 4 |
10963 Berlin 5 |
E-Mail: info@wikimedia.de 6 |
Webseite: https://wikimedia.de 7 |
Telefon: +49 (0)30-577 11 62-0 8 |
Fax: +49 (0)30-577 11 62-99 9 |

10 |

11 | Geschäftsführende Vorständin: Franziska Heine 12 |
Eingetragen im Vereinsregister des Amtsgerichts Charlottenburg, VR 23855. Inhaltlich 13 | Verantwortliche gemäß § 18 Abs. 2 MStV: Franziska Heine (Anschrift wie oben). 14 |

15 |

16 | Der gesamte Quellcode des Lizenzhinweisgenerators wird unter der GNU General Public Licence (GPL v3) veröffentlicht. 18 | Der Code kann auf GitHub 19 | eingesehen, heruntergeladen und anschließend verändert und neu veröffentlicht werden. Alle Texte 20 | der Anwendung stehen unter der Lizenz Creative 22 | Commons Namensnennung - Weitergabe unter gleichen Bedingungen 4.0 International und können 23 | unter den in der Lizenz genannten Bedingungen auch weitergenutzt, verändert und veröffentlicht 24 | werden. 25 |

26 |

27 | Datenschutzhinweis 28 |

29 |

30 | Auf wikimedia.de finden Sie alle 31 | Hinweise darüber, was mit Ihren personenbezogenen Daten passiert, wenn Sie diese oder andere Websites 32 | von Wikimedia Deutschland besuchen. 33 |

34 | 41 | -------------------------------------------------------------------------------- /index.php: -------------------------------------------------------------------------------- 1 | $string ) { 25 | $html = str_replace( '{{i18n.index.' . $key . '}}', $string, $html ); 26 | } 27 | } 28 | 29 | // Iterate over the i18n subdirectories (ISO 639-1 codes) to construct a 30 | //
  • element representation for the dropdown options 31 | $langDirs = array_filter( 32 | array_filter( glob( $i18nDir . '/*'), 'is_dir'), 33 | function ( $langDir ) { return pathinfo($langDir)['basename'] !== 'uk'; } 34 | ); 35 | $languageOptions = ''; 36 | foreach ( $langDirs as $langDir ) { 37 | $isoLang = pathinfo($langDir)['basename']; 38 | $languageOptions .= '
  • ' . $isoLang . '
  • '; 39 | } 40 | // ... and insert that string into the template 41 | $html = str_replace( '{{ languageOptions }}', $languageOptions, $html); 42 | 43 | // Also replace html snippets 44 | $htmlFiles = [ 45 | 'about', 46 | 'feedback', 47 | 'legal', 48 | 'private-use', 49 | ]; 50 | foreach( $htmlFiles as $file ) { 51 | $path = __DIR__ . '/i18n/' . $lang . '/' . $file . '.html'; 52 | if( !file_exists( $path ) ) { 53 | $path = __DIR__ . '/i18n/de/' . $file . '.html'; 54 | } 55 | $html = str_replace( '{{i18n.html.' . $file . '}}', file_get_contents( $path ), $html ); 56 | } 57 | 58 | // Output the html 59 | echo $html; 60 | -------------------------------------------------------------------------------- /tests/fixtures/templates/NatMonumFengegKapell.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 16084837, 3 | "ns": 6, 4 | "title": "File:NatMonumFengegKapell.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-3.0-lu" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Cc-country-flags" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Description" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Dir" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:ISOdate" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Infobar-Layout" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Information" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Information/author processing" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:IsNum" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:LangSwitch" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Lb" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:License template tag" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:Object location" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Original description page" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:Original upload log" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:Own" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:Parse source" 81 | } 82 | ] 83 | } -------------------------------------------------------------------------------- /tests/fixtures/templates/05 Air from Suite in C minor.ogg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 11995203, 3 | "ns": 6, 4 | "title": "File:05 Air from Suite in C minor.ogg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-sa-3.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-sa-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Description" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Dir" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:En" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:GFDL" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:GNU-Layout" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:ISOdate" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Information" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Information/author processing" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Lang" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:License migration" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:License migration is redundant" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:License migration is redundant multiple" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:License template tag" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:Own" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:Parse source" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:Self" 81 | } 82 | ] 83 | } -------------------------------------------------------------------------------- /js/app/AttributionDialogue.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | Dialogue = require( './Dialogue' ), 5 | DialogueStep = require( './DialogueStep' ), 6 | ChangeStep = require( './ChangeStep' ), 7 | LicenceStep = require( './LicenceStep' ); 8 | 9 | /** 10 | * @param {string|null} author 11 | * @constructor 12 | */ 13 | var AttributionDialogue = function( asset ) { 14 | Dialogue.call( this ); 15 | this._asset = asset; 16 | }; 17 | 18 | $.extend( AttributionDialogue.prototype, Dialogue.prototype, { 19 | /** 20 | * @type {Asset} 21 | */ 22 | _asset: null, 23 | 24 | getAsset: function() { 25 | return this._asset; 26 | }, 27 | 28 | setStep: function( n ) { 29 | Dialogue.prototype.setStep.call( this, n ); 30 | if( this._hasAuthor() && n < 4 || n < 3 ) { 31 | this._removeEditingSteps(); 32 | } 33 | }, 34 | 35 | _hasAuthor: function() { 36 | return this._asset.getAuthors().length === 0; 37 | }, 38 | 39 | init: function() { 40 | this.addStep( new DialogueStep( 'typeOfUse', require( './templates/TypeOfUseStep.handlebars' ) ) ); 41 | if( this._hasAuthor() ) { 42 | this.addStep( new DialogueStep( 'author', require( './templates/AuthorStep.handlebars' ) ) ); 43 | } 44 | this.addStep( new DialogueStep( 'compilation', require( './templates/CompilationStep.handlebars' ) ) ); 45 | this.addStep( new DialogueStep( 'editing', require( './templates/EditingStep.handlebars' ) ) ); 46 | }, 47 | 48 | completeStep: function( step ) { 49 | Dialogue.prototype.completeStep.call( this, step ); 50 | 51 | var data = step.getData(); 52 | if( step.getName() === 'editing' && data[ 'edited' ] === 'true' ) { 53 | this._addEditingSteps(); 54 | } 55 | }, 56 | 57 | _removeEditingSteps: function() { 58 | if( this._steps.length > 4 ) { 59 | this._steps.pop(); 60 | this._steps.pop(); 61 | this._steps.pop(); 62 | } 63 | }, 64 | 65 | _addEditingSteps: function() { 66 | var licence = this._asset.getLicence(); 67 | this.addStep( new ChangeStep( licence ) ); 68 | this.addStep( new DialogueStep( 'creator', require( './templates/CreatorStep.handlebars' ) ) ); 69 | this.addStep( new LicenceStep( licence ) ); 70 | } 71 | } ); 72 | 73 | module.exports = AttributionDialogue; 74 | -------------------------------------------------------------------------------- /js/app/views/PublicDomainDialogueView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | publicDomainTemplate = require( '../templates/PublicDomain.handlebars' ), 5 | Messages = require( '../Messages' ), 6 | // buttonTemplate = require( '../templates/SmallButton.handlebars' ), 7 | moreInfomationTemplate = require( '../templates/MoreInformation.handlebars' ), 8 | BackToTopButton = require( '../BackToTopButton' ); 9 | 10 | var PublicDomainDialogueView = function( parentDialogue ) { 11 | this._parentDialogue = parentDialogue; 12 | }; 13 | 14 | $.extend( PublicDomainDialogueView.prototype, { 15 | _renderPublicLicenceDialogue: function() { 16 | return publicDomainTemplate(); 17 | }, 18 | 19 | _showPublicDomainInformation: function() { 20 | var $bottomBar = $( '
    ' ); 21 | $bottomBar.append( moreInfomationTemplate( { 22 | content: Messages.t( 'dialogue.more-information' ), 23 | target: 'https://wiki.creativecommons.org/wiki/Public_domain' 24 | } ) ); 25 | $bottomBar.append( new BackToTopButton().render() ); 26 | 27 | return $bottomBar; 28 | }, 29 | _showForceAttribution: function() { 30 | var $forceAttributionBox = $( '
    ' ); 31 | 32 | var parentDialogue = this._parentDialogue; 33 | 34 | $forceAttributionBox.bind( 'click', function() { 35 | // Remove children from current dialogue screen element 36 | var $dialogueScreen = $( '.dialogue-screen' ); 37 | $dialogueScreen.empty(); 38 | // render parent dialogue again with forceAttribution set to true 39 | parentDialogue.render( $dialogueScreen, true ); 40 | } ); 41 | 42 | $forceAttributionBox.append( Messages.t( 'dialogue.force-pd-attribution' ) ); 43 | return $forceAttributionBox; 44 | }, 45 | 46 | /** 47 | * Renders information about Public Domain Licence if the picture was under PD or starts the dialogue 48 | * 49 | * @param {jQuery} $dialogue 50 | */ 51 | render: function( $dialogue ) { 52 | var $publicLicenceDialogue = $( this._renderPublicLicenceDialogue() ); 53 | $publicLicenceDialogue.append( this._showForceAttribution() ); 54 | $dialogue.html( $publicLicenceDialogue ) 55 | .append( '
    ' ) 56 | .append( this._showPublicDomainInformation() ); 57 | } 58 | } ); 59 | 60 | module.exports = PublicDomainDialogueView; 61 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Attribution Generator 2 | 3 | Using and sharing works licenced under Creative Commons requires specifying an attribution as defined by the respective licence. This application helps generating a legally correct attribution with images from Wikipedia and Wikimedia Commons. 4 | A questionnaire leads through the process of collecting information needed when publishing images from Wikipedia and Commons to create a legally sufficient attribution line. 5 | 6 | [![Build Status](https://travis-ci.org/wmde/Lizenzhinweisgenerator.svg?branch=master)](https://travis-ci.org/wmde/Lizenzhinweisgenerator 7 | ) 8 | 9 | ## Official version 10 | 11 | https://lizenzhinweisgenerator.de 12 | 13 | ## Technical documentation 14 | 15 | ### Licence support 16 | 17 | The licences supported by the application are defined in js/app/LICENCES.js. 18 | 19 | ### Coding conventions 20 | 21 | Coding style adheres to the [Wikibase coding conventions](http://www.mediawiki.org/wiki/Wikibase/Coding_conventions). 22 | 23 | ### Building the code 24 | 25 | Run `npm install`to pull any new dependencies. 26 | 27 | Browserify is used to build and minify the JS code. 28 | 29 | * `npm run build` builds a production version 30 | * `npm run watch` builds a development version of the code that is not minified and will listen for updates on all JS files 31 | * `npm run build-test` builds the test code 32 | * `npm run watch-test` builds the test code unminified and listens for changes on test files 33 | 34 | ### Testing 35 | 36 | QUnit tests are located in the tests directory. Before merging changes, tests should be run by accessing /tests/index.html in a browser after executing `npm run build-test` or from command line using [qunit-phantomjs-runner](https://github.com/jonkemp/qunit-phantomjs-runner): 37 | ```bash 38 | npm run build-test && phantomjs path/to/runner.js ./tests/index.html 39 | ``` 40 | 41 | ### Backend 42 | 43 | The backend code for the feedback form can be found in the `/backend` directory. Its dependencies are installed via `composer install` and tests can be run by executing `phpunit`. 44 | 45 | ### Reporting Issues 46 | 47 | Please file all new bug reports and feature requests on [Phabricator](https://phabricator.wikimedia.org/maniphest/task/create/?projects=tcb-team,attribution-generator&title=%5BAG%5D) or use the "Feedback" link on https://lizenzhinweisgenerator.de. 48 | -------------------------------------------------------------------------------- /js/app/WikiAsset.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author snater.com < wikimedia@snater.com > 4 | */ 5 | /* jshint strict: false */ 6 | 7 | var $ = require( 'jquery' ), 8 | Asset = require( './Asset' ); 9 | 10 | /** 11 | * Represents an asset. 12 | * @constructor 13 | * 14 | * @param {string} url 15 | * @param {string} mediaType 16 | * @param {Licence|null} [licence] 17 | * @param {string|null} [title] 18 | * @param {Author[]|null} [authors] 19 | * @param {string} [url] 20 | * @param {jQuery|null} [$attribution] 21 | * @param {Api|null} [api] 22 | * @param {string} [wikiUrl] 23 | * 24 | * @throws {Error} if a required parameter is not defined. 25 | */ 26 | var WikiAsset = function( filename, 27 | mediaType, 28 | licence, 29 | title, 30 | authors, 31 | url, 32 | $attribution, 33 | api, 34 | wikiUrl ) { 35 | Asset.call( this, filename, mediaType, licence, title, authors, url, $attribution, api ); 36 | this._wikiUrl = wikiUrl || null; 37 | }; 38 | 39 | $.extend( WikiAsset.prototype, Asset.prototype, { 40 | 41 | /** 42 | * @type {string} 43 | */ 44 | _wikiUrl: null, 45 | 46 | /** 47 | * @see Asset.getFilename 48 | * 49 | * @return {string} 50 | */ 51 | getFilename: function() { 52 | return this._filename.replace( /^[^:]+:/, '' ); 53 | }, 54 | 55 | /** 56 | * @return {string} 57 | */ 58 | getWikiUrl: function() { 59 | return this._wikiUrl; 60 | }, 61 | 62 | /** 63 | * @see Asset.getUrl 64 | * 65 | * @return {string} 66 | */ 67 | getUrl: function() { 68 | var url = ( this._wikiUrl || this._api.getDefaultUrl() ) + 'wiki/' + this._filename; 69 | return url.indexOf( 'http' ) === 0 ? url : 'https://' + url; 70 | }, 71 | 72 | /** 73 | * @see Asset.equals 74 | * 75 | * @param {Asset} asset 76 | * @return {boolean} 77 | */ 78 | equals: function( asset ) { 79 | return this.inherited( arguments ) && asset.getWikiUrl() === this.getWikiUrl(); 80 | }, 81 | 82 | /** 83 | * Clones the asset. 84 | * 85 | * @return {WikiAsset} 86 | */ 87 | clone: function() { 88 | return new WikiAsset( 89 | this._filename, 90 | this._mediaType, 91 | this._licence, 92 | this._title, 93 | this._authors, 94 | this._url, 95 | this._$attribution, 96 | this._api, 97 | this._wikiUrl 98 | ); 99 | } 100 | } ); 101 | 102 | module.exports = WikiAsset; 103 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Gerardus_t'_Hooft_at_Harvard.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 118613, 3 | "ns": 6, 4 | "title": "File:Gerardus t' Hooft at Harvard.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-3.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Description" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Dir" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:En" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Fallback" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:ISOdate" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Information" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Information/author processing" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:LangSwitch" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Language" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:License template tag" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Original description page" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:Original upload log" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Own work by original uploader" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:Parse source" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:Projectname" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:Projectname/en" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:User at project" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:User at project/core" 89 | } 90 | ] 91 | } -------------------------------------------------------------------------------- /js/app/views/DialogueScreen.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | template = require( '../templates/DialogueScreen.handlebars' ), 5 | imagePreviewTemplate = require( '../templates/ImagePreview.handlebars' ), 6 | PublicDomainDialogueView = require( './PublicDomainDialogueView' ), 7 | AttributionDialogueView = require( './AttributionDialogueView' ), 8 | Messages = require( '../Messages' ); 9 | 10 | var DialogueView = function( imageInfo, asset ) { 11 | this._imageInfo = imageInfo; 12 | this._asset = asset; 13 | }; 14 | 15 | $.extend( DialogueView.prototype, { 16 | /** 17 | * @type {ImageInfo} 18 | */ 19 | _imageInfo: null, 20 | 21 | /** 22 | * @type {Asset} 23 | */ 24 | _asset: null, 25 | 26 | _renderImagePreview: function() { 27 | return imagePreviewTemplate( { 28 | url: this._imageInfo.getUrl(), 29 | size: this._imageInfo.getPrettySize(), 30 | thumbUrl: this._imageInfo.getThumbnail().url, 31 | imageWidth: this._imageInfo.getThumbnail().width, 32 | filePageUrl: this._asset.getUrl() 33 | } ); 34 | }, 35 | 36 | /** 37 | * Renders information about the usage not requiring attributing the author, 38 | * if the asset has been licenced under appropriate licence, or starts the dialogue otherwise. 39 | * 40 | * @param {jQuery} $screen 41 | * @param {boolean} $forceAttribution 42 | */ 43 | render: function( $screen, forceAttribution ) { 44 | var title, dialogue; 45 | 46 | if( !forceAttribution && this._noAttributionNeeded( this._asset.getLicence() ) ) { 47 | title = Messages.t( 'dialogue.no-attribution-needed' ); 48 | dialogue = new PublicDomainDialogueView( this ); 49 | } else { 50 | if( this._asset.getLicence().isPublicDomain() ) { 51 | title = Messages.t( 'dialogue.adjust-legal-notice-for-usage' ); 52 | } else { 53 | title = Messages.t( 'dialogue.adjust-attribution-for-usage' ); 54 | } 55 | dialogue = new AttributionDialogueView( this._asset ); 56 | } 57 | 58 | $screen.html( template( { 59 | title: title, 60 | imagePreview: this._renderImagePreview() 61 | } ) ); 62 | dialogue.render( $screen.find( '.dialogue' ) ); 63 | }, 64 | 65 | /** 66 | * Checks if the licence does not oblige to provide the attribution 67 | * 68 | * @param {Licence} licence 69 | */ 70 | _noAttributionNeeded: function( licence ) { 71 | return licence.isInGroup( 'pd' ) || licence.isInGroup( 'cc0' ); 72 | } 73 | 74 | } ); 75 | 76 | module.exports = DialogueView; 77 | -------------------------------------------------------------------------------- /js/app/views/ProgressBarView.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var $ = require( 'jquery' ), 4 | template = require( '../templates/ProgressBar.handlebars' ); 5 | 6 | var ProgressBarView = function( dialogue, dialogueView ) { 7 | this._dialogue = dialogue; 8 | this._dialogueView = dialogueView; 9 | this._initialized = false; 10 | }; 11 | 12 | $.extend( ProgressBarView.prototype, { 13 | /** 14 | * @type {AttributionDialogue} 15 | */ 16 | _dialogue: null, 17 | 18 | /** 19 | * @type {AttributionDialogueView} 20 | */ 21 | _dialogueView: null, 22 | 23 | /** 24 | * @type {boolean} 25 | */ 26 | _initialized: false, 27 | 28 | _backBuffer: false, 29 | 30 | _setBackBuffer: function() { 31 | this._backBuffer = true; 32 | window.history.pushState( 'step-back', '', '' ); 33 | }, 34 | 35 | /** 36 | * @param {int} n 37 | * @private 38 | */ 39 | _backToStep: function( n ) { 40 | if( n < 0 || n >= this._dialogue.currentStepIndex() ) { 41 | return; 42 | } 43 | 44 | this._dialogue.setStep( n ); 45 | this._dialogueView.updateContent(); 46 | }, 47 | 48 | render: function() { 49 | var steps = this._dialogue.getSteps() 50 | .concat( [ { 51 | getName: function() { 52 | return 'done'; 53 | } 54 | } ] ), 55 | activeStep = steps.indexOf( this._dialogue.currentStep() ), 56 | $html = $( template( { 57 | steps: steps.map( function( step, i, allSteps ) { 58 | var lastStepIndex = allSteps.length - 1; 59 | activeStep = activeStep === -1 ? lastStepIndex : activeStep; 60 | 61 | return { 62 | name: 'dialogue.' + step.getName(), 63 | isSubstep: i !== lastStepIndex && allSteps.length > 5 && i >= lastStepIndex - 3, 64 | isActive: i === activeStep, 65 | isCompleted: i < activeStep 66 | }; 67 | } ) 68 | } ) ), 69 | self = this; 70 | 71 | $html.find( 'li a' ).click( function( e ) { 72 | self._backToStep( $html.find( 'li a' ).index( $( this ) ) ); 73 | e.preventDefault(); 74 | } ); 75 | 76 | if( window.history && this._dialogue.currentStepIndex() > 0 ) { 77 | if( !this._backBuffer ) { 78 | this._setBackBuffer(); 79 | } 80 | 81 | if( !this._initialized ) { 82 | this._initialized = true; 83 | 84 | $( window ).on( 'popstate', function() { 85 | self._backBuffer = false; 86 | self._backToStep( self._dialogue.currentStepIndex() - 1 ); 87 | } ); 88 | } 89 | } 90 | 91 | return $html; 92 | } 93 | } ); 94 | 95 | module.exports = ProgressBarView; 96 | -------------------------------------------------------------------------------- /css/justifiedGallery.min.css: -------------------------------------------------------------------------------- 1 | /*! 2 | * Justified Gallery - v3.6.1 3 | * http://miromannino.github.io/Justified-Gallery/ 4 | * Copyright (c) 2015 Miro Mannino 5 | * Licensed under the MIT license. 6 | */ 7 | @-webkit-keyframes justified-gallery-show-caption-animation{from{opacity:0}to{opacity:.7}}@-moz-keyframes justified-gallery-show-caption-animation{from{opacity:0}to{opacity:.7}}@-o-keyframes justified-gallery-show-caption-animation{from{opacity:0}to{opacity:.7}}@keyframes justified-gallery-show-caption-animation{from{opacity:0}to{opacity:.7}}@-webkit-keyframes justified-gallery-show-entry-animation{from{opacity:0}to{opacity:1}}@-moz-keyframes justified-gallery-show-entry-animation{from{opacity:0}to{opacity:1}}@-o-keyframes justified-gallery-show-entry-animation{from{opacity:0}to{opacity:1}}@keyframes justified-gallery-show-entry-animation{from{opacity:0}to{opacity:1}}.justified-gallery{width:100%;position:relative;overflow:hidden}.justified-gallery>a,.justified-gallery>div{position:absolute;display:inline-block;overflow:hidden;opacity:0;filter:alpha(opacity=0)}.justified-gallery>a>img,.justified-gallery>div>img,.justified-gallery>a>a>img,.justified-gallery>div>a>img{position:absolute;top:50%;left:50%;margin:0;padding:0;border:0}.justified-gallery>a>.caption,.justified-gallery>div>.caption{display:none;position:absolute;bottom:0;padding:5px;background-color:#000;left:0;right:0;margin:0;color:#fff;font-size:12px;font-weight:300;font-family:sans-serif}.justified-gallery>a>.caption.caption-visible,.justified-gallery>div>.caption.caption-visible{display:initial;opacity:.7;filter:"alpha(opacity=70)";-webkit-animation:justified-gallery-show-caption-animation 500ms 0 ease;-moz-animation:justified-gallery-show-caption-animation 500ms 0 ease;-ms-animation:justified-gallery-show-caption-animation 500ms 0 ease}.justified-gallery>.entry-visible{opacity:1;filter:alpha(opacity=100);-webkit-animation:justified-gallery-show-entry-animation 500ms 0 ease;-moz-animation:justified-gallery-show-entry-animation 500ms 0 ease;-ms-animation:justified-gallery-show-entry-animation 500ms 0 ease}.justified-gallery>.jg-filtered{display:none}.justified-gallery>.spinner{position:absolute;bottom:0;margin-left:-24px;padding:10px 0;left:50%;opacity:initial;filter:initial;overflow:initial}.justified-gallery>.spinner>span{display:inline-block;opacity:0;filter:alpha(opacity=0);width:8px;height:8px;margin:0 4px;background-color:#000;border-top-left-radius:6px;border-top-right-radius:6px;border-bottom-right-radius:6px;border-bottom-left-radius:6px} -------------------------------------------------------------------------------- /tests/fixtures/templates/The_Little_Princess_(1939)_full.ogv.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 31180014, 3 | "ns": 6, 4 | "title": "File:The Little Princess (1939) full.ogv", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:Autotranslate" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cite journal" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Custom" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Custom license marker" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Description" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Dir" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Edit" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:En" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:ISOdate" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Iffile" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Ifimage" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Information" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Information/author processing" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Lang" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:License template tag" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Max" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:PD-Layout" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:PD-US-not renewed" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:PD-US-not renewed/en" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:PD-US-not renewed/lang" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:PD-US-not renewed/layout" 89 | }, 90 | { 91 | "ns": 10, 92 | "title": "Template:Parse source" 93 | } 94 | ] 95 | } -------------------------------------------------------------------------------- /backend/src/Actions/FeedbackAction.php: -------------------------------------------------------------------------------- 1 | app = $app; 13 | $request = $app['request']; 14 | 15 | $lang = !empty( $request->get( 'lang' ) ) ? $request->get( 'lang' ) : 'de'; 16 | $langFile = __DIR__ . '/../../../i18n/' . $lang . '/i18n.json'; 17 | if( !file_exists( $langFile ) ) { 18 | $langFile = __DIR__ . '/../../../i18n/de/i18n.json'; 19 | } 20 | $this->i18n = json_decode( file_get_contents( $langFile ), true ); 21 | 22 | if ( $this->requestValid( $request ) ) { 23 | $this->sendMail( 24 | $request->get( 'name' ), 25 | $request->get( 'feedback' ), 26 | $request->get( 'responseEmail' ) 27 | ); 28 | } 29 | } 30 | 31 | private function requestValid( \Symfony\Component\HttpFoundation\Request $request ) { 32 | if ( empty( $request->get( 'name' ) ) || empty( $request->get( 'feedback' ) ) ) { 33 | $this->errors[] = $this->i18n['error']['feedback-blank-fields']; 34 | return false; 35 | } 36 | 37 | return true; 38 | } 39 | 40 | private function sendMail( $sender, $text, $responseEmail ) { 41 | if (!isset($responseEmail) || empty($responseEmail) ) { 42 | $fromEmail = 'noreply@attribution-generator.dev'; 43 | } else { 44 | if (!filter_var($responseEmail, FILTER_VALIDATE_EMAIL)) { 45 | $this->errors[] = $this->i18n['error']['invalid-email-format']; 46 | return; 47 | } 48 | $fromEmail = $responseEmail; 49 | } 50 | 51 | $message = \Swift_Message::newInstance() 52 | ->setSubject( '[AttributionGenerator] Feedback from ' . $sender ) 53 | ->setFrom( [ $fromEmail ] ) 54 | ->setTo( [ $this->app['config']['feedback_email'] ] ) 55 | ->setBody( $text ); 56 | 57 | try { 58 | $this->app['mailer']->send( $message ); 59 | } catch ( Exception $e ) { 60 | $this->errors[] = $this->i18n['error']['feedback-generic']; 61 | } 62 | } 63 | 64 | private function success() { 65 | return [ 'message' => $this->i18n['index']['feedback-thanks'] ]; 66 | } 67 | 68 | public function getResponse() { 69 | if ( empty( $this->errors ) ) { 70 | return json_encode( $this->success(), JSON_UNESCAPED_UNICODE ); 71 | } else { 72 | return new Response( 73 | json_encode( 74 | [ 'errors' => $this->errors ], 75 | JSON_UNESCAPED_UNICODE 76 | ), 77 | 400 78 | ); 79 | } 80 | } 81 | } 82 | -------------------------------------------------------------------------------- /js/app/ImageInfo.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author snater.com < wikimedia@snater.com > 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var $ = require( 'jquery' ); 9 | 10 | /** 11 | * Standardized container for image information. 12 | * @constructor 13 | * 14 | * @param {string} url 15 | * @param {string} descriptionUrl 16 | * @param {int} size The image's size in bytes 17 | * @param {Object} [thumbnail] 18 | */ 19 | var ImageInfo = function( url, descriptionUrl, size, thumbnail ) { 20 | if( !url || !descriptionUrl ) { 21 | throw new Error( 'Required parameters are not specified correctly' ); 22 | } 23 | this._url = url; 24 | this._descriptionUrl = descriptionUrl; 25 | this._size = size; 26 | this._thumbnail = thumbnail || null; 27 | }; 28 | 29 | $.extend( ImageInfo.prototype, { 30 | /** 31 | * @type {string} 32 | */ 33 | _url: null, 34 | 35 | /** 36 | * @type {string} 37 | */ 38 | _descriptionUrl: null, 39 | 40 | /** 41 | * The image's size in bytes 42 | * @type {int} 43 | */ 44 | _size: null, 45 | 46 | /** 47 | * @type {Object|null} 48 | */ 49 | _thumbnail: null, 50 | 51 | /** 52 | * @return {string} 53 | */ 54 | getUrl: function() { 55 | return this._url; 56 | }, 57 | 58 | /** 59 | * @return {int} 60 | */ 61 | getSize: function() { 62 | return this._size; 63 | }, 64 | 65 | /** 66 | * @return {string} 67 | */ 68 | getPrettySize: function() { 69 | var sizeOf = function( a,b,c,d,e ) { 70 | return ( b = Math, c = b.log, d = 1024, e = c( a ) / c( d ) | 0, a / b.pow( d, e ) ).toFixed( 2 ) 71 | + ' ' + ( e ? 'KMGTPEZY'[--e] + 'B' : 'Bytes' ); 72 | }; 73 | return sizeOf( this._size ); 74 | }, 75 | 76 | /** 77 | * @return {string} 78 | */ 79 | getDescriptionUrl: function() { 80 | return this._descriptionUrl; 81 | }, 82 | 83 | /** 84 | * @return {Object|null} 85 | */ 86 | getThumbnail: function() { 87 | return this._thumbnail; 88 | } 89 | } ); 90 | 91 | /** 92 | * Instantiates a new ImageInfo object using the "imageinfo" JSON object returned by the MediaWiki 93 | * API. 94 | * 95 | * @param {Object} imageinfo 96 | * @return {ImageInfo} 97 | */ 98 | ImageInfo.newFromMediaWikiImageInfoJson = function( imageinfo ) { 99 | return new ImageInfo( 100 | imageinfo.url, 101 | imageinfo.descriptionurl, 102 | imageinfo.size, 103 | { 104 | url: imageinfo.thumburl || null, 105 | width: imageinfo.thumbwidth || null, 106 | height: imageinfo.thumbheight || null 107 | } 108 | ); 109 | }; 110 | 111 | module.exports = ImageInfo; 112 | -------------------------------------------------------------------------------- /images/cc.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /tests/fixtures/templates/Inisheer Gardens 2002 dry-stone walls.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 176181, 3 | "ns": 6, 4 | "title": "File:Inisheer Gardens 2002 dry-stone walls.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-2.0-de" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-2.5" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Cc-by-layout" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Cc-by-sa-3.0-migrated" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Cc-country-flags" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Description" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Dir" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:En" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:GFDL" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:GNU-Layout" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:ISOdate" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Information" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Information/author processing" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:Lang" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:License migration" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:License migration complete" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:License migration is redundant multiple" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:License template tag" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:Other date" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:Own" 89 | }, 90 | { 91 | "ns": 10, 92 | "title": "Template:Parse source" 93 | }, 94 | { 95 | "ns": 10, 96 | "title": "Template:Self" 97 | } 98 | ] 99 | } -------------------------------------------------------------------------------- /tests/fixtures/images/Königsberg_in_Bayern.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 21330, 3 | "ns": 0, 4 | "title": "K\u00f6nigsberg in Bayern", 5 | "images": [ 6 | { 7 | "ns": 6, 8 | "title": "Datei:Baumeister-K\u00f6nigsberg.JPG" 9 | }, 10 | { 11 | "ns": 6, 12 | "title": "Datei:Commons-logo.svg" 13 | }, 14 | { 15 | "ns": 6, 16 | "title": "Datei:DEU K\u00f6nigsberg COA.svg" 17 | }, 18 | { 19 | "ns": 6, 20 | "title": "Datei:Germany adm location map.svg" 21 | }, 22 | { 23 | "ns": 6, 24 | "title": "Datei:Konigsberg Altstadt-1.jpg" 25 | }, 26 | { 27 | "ns": 6, 28 | "title": "Datei:Konigsberg Altstadt-2.jpg" 29 | }, 30 | { 31 | "ns": 6, 32 | "title": "Datei:K\u00f6nigsberg Altershausen.jpg" 33 | }, 34 | { 35 | "ns": 6, 36 | "title": "Datei:K\u00f6nigsberg B\u00fchl.jpg" 37 | }, 38 | { 39 | "ns": 6, 40 | "title": "Datei:K\u00f6nigsberg D\u00f6rflis.jpg" 41 | }, 42 | { 43 | "ns": 6, 44 | "title": "Datei:K\u00f6nigsberg Hellingen.jpg" 45 | }, 46 | { 47 | "ns": 6, 48 | "title": "Datei:K\u00f6nigsberg Hofstetten.jpg" 49 | }, 50 | { 51 | "ns": 6, 52 | "title": "Datei:K\u00f6nigsberg Junkersdorf.jpg" 53 | }, 54 | { 55 | "ns": 6, 56 | "title": "Datei:K\u00f6nigsberg Kottenbrunn.jpg" 57 | }, 58 | { 59 | "ns": 6, 60 | "title": "Datei:K\u00f6nigsberg K\u00f6slau.jpg" 61 | }, 62 | { 63 | "ns": 6, 64 | "title": "Datei:K\u00f6nigsberg R\u00f6mershofen.jpg" 65 | }, 66 | { 67 | "ns": 6, 68 | "title": "Datei:K\u00f6nigsberg Unfinden.jpg" 69 | }, 70 | { 71 | "ns": 6, 72 | "title": "Datei:K\u00f6nigsberg in Bayern in HAS.svg" 73 | }, 74 | { 75 | "ns": 6, 76 | "title": "Datei:Luftbild-koenigsberg-bayern.jpg" 77 | }, 78 | { 79 | "ns": 6, 80 | "title": "Datei:Luftkurort K\u00f6nigsberg.jpg" 81 | }, 82 | { 83 | "ns": 6, 84 | "title": "Datei:Marienkirche-waechterturm-koenigsberg.jpg" 85 | }, 86 | { 87 | "ns": 6, 88 | "title": "Datei:Marienstrasse.jpg" 89 | }, 90 | { 91 | "ns": 6, 92 | "title": "Datei:Marktbrunnen-koenigsberg.jpg" 93 | }, 94 | { 95 | "ns": 6, 96 | "title": "Datei:Reddot.svg" 97 | }, 98 | { 99 | "ns": 6, 100 | "title": "Datei:Regiomontanus-Koenigsberg.JPG" 101 | }, 102 | { 103 | "ns": 6, 104 | "title": "Datei:Roland-Koenigsberg.JPG" 105 | }, 106 | { 107 | "ns": 6, 108 | "title": "Datei:Seckendorff-Tafel.JPG" 109 | }, 110 | { 111 | "ns": 6, 112 | "title": "Datei:Wappen Landkreis Ha\u00dfberge.svg" 113 | }, 114 | { 115 | "ns": 6, 116 | "title": "Datei:Westansicht-schlossberg-koenigsberg.jpg" 117 | }, 118 | { 119 | "ns": 6, 120 | "title": "Datei:Wikisource-logo.svg" 121 | } 122 | ] 123 | } -------------------------------------------------------------------------------- /tests/app/Api.local.tests.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author Leszek Manicki < leszek.manicki@wikimedia.de > 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var LocalApi = require( '../LocalApi' ), 9 | $ = require( 'jquery' ), 10 | testAssets = require( '../assets' ), 11 | WikiAsset = require( '../../js/app/WikiAsset' ); 12 | 13 | QUnit.module( 'Api local' ); 14 | 15 | var api = new LocalApi( 'fixtures' ); 16 | 17 | /** 18 | * Returns a nodes HTML as plain text. 19 | * 20 | * @param {jQuery|null} $node 21 | * @return {string|null} 22 | */ 23 | function getHtmlText( $node ) { 24 | return $node ? $( '
    ' ).append( $node ).html() : null; 25 | } 26 | 27 | QUnit.test( 'Check scraped asset', function( assert ) { 28 | 29 | $.each( testAssets, function( filename, testAsset ) { 30 | if( !( testAsset instanceof WikiAsset ) ) { 31 | return true; 32 | } 33 | 34 | QUnit.stop(); 35 | 36 | api.getAsset( 'File:' + filename, testAsset.getWikiUrl() ) 37 | .done( function( asset ) { 38 | 39 | assert.equal( 40 | asset.getFilename(), 41 | testAsset.getFilename(), 42 | 'Filename "' + asset.getFilename() + '" matches.' 43 | ); 44 | 45 | assert.equal( 46 | asset.getTitle(), 47 | testAsset.getTitle(), 48 | 'Title "' + asset.getTitle() + '" matches.' 49 | ); 50 | 51 | $.each( asset.getAuthors(), function( i, author ) { 52 | 53 | assert.equal( 54 | author.getText(), 55 | testAsset.getAuthors()[ i ].getText(), 56 | '"' + testAsset.getFilename() + '": Author text "' + author.getText() 57 | + '" matches.' 58 | ); 59 | 60 | var authorHtml = getHtmlText( author.getHtml() ); 61 | 62 | assert.equal( 63 | authorHtml, 64 | getHtmlText( testAsset.getAuthors()[ i ].getHtml() ), 65 | '"' + testAsset.getFilename() + '": Author html "' + authorHtml 66 | + '" matches.' 67 | ); 68 | 69 | } ); 70 | 71 | if( asset.getLicence() === null ) { 72 | assert.strictEqual( 73 | asset.getLicence(), 74 | testAsset.getLicence(), 75 | 'No supported licence.' 76 | ); 77 | } else { 78 | assert.equal( 79 | asset.getLicence().getId(), 80 | testAsset.getLicence().getId(), 81 | 'Licence "' + asset.getLicence().getId() + '" matches.' 82 | ); 83 | } 84 | 85 | assert.equal( 86 | getHtmlText( asset.getAttribution() ), 87 | getHtmlText( testAsset.getAttribution() ), 88 | 'Dedicated attribution of "' + testAsset.getFilename() + '" matches.' 89 | ); 90 | 91 | } ) 92 | .fail( function() { 93 | assert.ok( 94 | false, 95 | 'API call failed.' 96 | ); 97 | } ) 98 | .always( function() { 99 | QUnit.start(); 100 | } ); 101 | 102 | } ); 103 | } ); 104 | -------------------------------------------------------------------------------- /tests/app/AttributionDialogue.tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | QUnit.module( 'AttributionDialogue' ); 4 | 5 | var $ = require( 'jquery' ), 6 | AttributionDialogue = require( '../../js/app/AttributionDialogue' ), 7 | Messages = require( '../../js/app/Messages' ), 8 | Author = require( '../../js/app/Author' ), 9 | Asset = require( '../../js/app/Asset' ), 10 | Helpers = require( '../TestHelpers' ); 11 | require( '../array-find' ); 12 | 13 | QUnit.test( 'should have 4 steps by default', function( assert ) { 14 | var dialogue = Helpers.newDefaultAttributionDialogue(); 15 | assert.equal( dialogue._steps.length, 4 ); 16 | } ); 17 | 18 | QUnit.test( 'should have only 3 steps if the author is known', function( assert ) { 19 | var asset = new Asset( '', '', null, null, [ new Author( $( 'Meh' ) ) ] ), 20 | dialogue = new AttributionDialogue( asset ); 21 | dialogue.init(); 22 | assert.equal( 3, dialogue._steps.length ); 23 | } ); 24 | 25 | function completeEditingStep( dialogue, data ) { 26 | var editingStep = dialogue._steps.find( function( step ) { 27 | return step.getName() === 'editing'; 28 | } ); 29 | editingStep.complete( data ); 30 | } 31 | 32 | QUnit.test( 'should add 3 more steps for editing', function( assert ) { 33 | var dialogue = Helpers.newDefaultAttributionDialogue(); 34 | dialogue.init(); 35 | var initialNumber = dialogue._steps.length; 36 | completeEditingStep( dialogue, { edited: 'true' } ); 37 | assert.equal( dialogue._steps.length, initialNumber + 3 ); 38 | } ); 39 | 40 | QUnit.test( 'should not add 3 more steps when not editing', function( assert ) { 41 | var dialogue = Helpers.newDefaultAttributionDialogue(); 42 | dialogue.init(); 43 | var initialNumber = dialogue._steps.length; 44 | completeEditingStep( dialogue, { edited: 'false' } ); 45 | assert.equal( dialogue._steps.length, initialNumber ); 46 | } ); 47 | 48 | function currentStepContains( dialogue, message ) { 49 | return dialogue 50 | .currentStep() 51 | .render() 52 | .text() 53 | .indexOf( Messages.t( message ) ) > -1; 54 | } 55 | 56 | QUnit.test( 'Steps content', function( assert ) { 57 | var dialogue = Helpers.newDefaultAttributionDialogue(); 58 | 59 | assert.ok( currentStepContains( dialogue, 'dialogue.type-of-use-headline' ) ); 60 | dialogue.currentStep().complete(); 61 | 62 | assert.ok( currentStepContains( dialogue, 'dialogue.author-headline' ) ); 63 | dialogue.currentStep().complete(); 64 | 65 | assert.ok( currentStepContains( dialogue, 'dialogue.compilation-headline' ) ); 66 | dialogue.currentStep().complete(); 67 | 68 | assert.ok( currentStepContains( dialogue, 'dialogue.editing-headline' ) ); 69 | dialogue.currentStep().complete( { edited: 'true' } ); 70 | 71 | assert.ok( currentStepContains( dialogue, 'dialogue.change-headline' ) ); 72 | dialogue.currentStep().complete(); 73 | 74 | assert.ok( currentStepContains( dialogue, 'dialogue.creator-headline' ) ); 75 | dialogue.currentStep().complete(); 76 | 77 | assert.ok( currentStepContains( dialogue, 'dialogue.licence-headline' ) ); 78 | dialogue.currentStep().complete(); 79 | } ); 80 | -------------------------------------------------------------------------------- /tests/fixtures/templates/CardinalMarkE.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 30058, 3 | "ns": 6, 4 | "title": "File:CardinalMarkE.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:CC-Layout" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Cc-by-4.0" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-layout" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:City" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Conj" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:CountryAdjective" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:CountryAdjective/en" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Creator" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Creator template no image" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:De" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Description" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Dir" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:En" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Fallback" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:ISOdate" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:ISOyear" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:IfNum" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:Iffile" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:Ifimage" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:Infobox template tag" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:Information" 89 | }, 90 | { 91 | "ns": 10, 92 | "title": "Template:Information/author processing" 93 | }, 94 | { 95 | "ns": 10, 96 | "title": "Template:Lang" 97 | }, 98 | { 99 | "ns": 10, 100 | "title": "Template:LangSwitch" 101 | }, 102 | { 103 | "ns": 10, 104 | "title": "Template:License template tag" 105 | }, 106 | { 107 | "ns": 10, 108 | "title": "Template:NationAndOccupation" 109 | }, 110 | { 111 | "ns": 10, 112 | "title": "Template:NationAndOccupation/default" 113 | }, 114 | { 115 | "ns": 10, 116 | "title": "Template:Nationality" 117 | }, 118 | { 119 | "ns": 10, 120 | "title": "Template:NoImageNotes" 121 | }, 122 | { 123 | "ns": 10, 124 | "title": "Template:Occupation" 125 | }, 126 | { 127 | "ns": 10, 128 | "title": "Template:Occupation/en" 129 | }, 130 | { 131 | "ns": 10, 132 | "title": "Template:Own" 133 | }, 134 | { 135 | "ns": 10, 136 | "title": "Template:Parse source" 137 | }, 138 | { 139 | "ns": 10, 140 | "title": "Template:Self" 141 | }, 142 | { 143 | "ns": 10, 144 | "title": "Template:Str left" 145 | }, 146 | { 147 | "ns": 10, 148 | "title": "Template:Str \u2264 len" 149 | }, 150 | { 151 | "ns": 10, 152 | "title": "Template:Years since" 153 | } 154 | ] 155 | } -------------------------------------------------------------------------------- /tests/fixtures/templates/Wien Karlsplatz3.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 180102, 3 | "ns": 6, 4 | "title": "File:Wien Karlsplatz3.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:Autotranslate" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:CC-Layout" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Cc-by-2.0-de" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Cc-by-layout" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Cc-country-flags" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:De" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Denkmalgeschütztes Objekt Österreich" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Denkmalgeschütztes Objekt Österreich/en" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Denkmalgeschütztes Objekt Österreich/layout" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Description" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Dir" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:En" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Fr" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:ISOdate" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:Infobar-Layout" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Information" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:Information/author processing" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:IsNum" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:Lang" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:License template tag" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:Object location" 89 | }, 90 | { 91 | "ns": 10, 92 | "title": "Template:Object location dec" 93 | }, 94 | { 95 | "ns": 10, 96 | "title": "Template:Own" 97 | }, 98 | { 99 | "ns": 10, 100 | "title": "Template:Parse source" 101 | }, 102 | { 103 | "ns": 10, 104 | "title": "Template:Pl" 105 | }, 106 | { 107 | "ns": 10, 108 | "title": "Template:Ru" 109 | }, 110 | { 111 | "ns": 10, 112 | "title": "Template:Self" 113 | }, 114 | { 115 | "ns": 10, 116 | "title": "Template:Str left" 117 | } 118 | ] 119 | } -------------------------------------------------------------------------------- /tests/fixtures/templates/LRO_Tycho_Central_Peak.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 15728898, 3 | "ns": 6, 4 | "title": "File:LRO Tycho Central Peak.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:Assessments" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Assessments/Blank" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Assessments/category" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Assessments/commons" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Assessments/commons/featured" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Assessments/images" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Assessments/images/left" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Assessments/images/right" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Assessments/translate/en" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Assessments/translate/lang" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Assessments/wikipedia" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:Assessments/wmf" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Autotranslate" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Boolean" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:Description" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Dir" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:Edit" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:En" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:FNO" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:FPC/" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:File namespace only" 89 | }, 90 | { 91 | "ns": 10, 92 | "title": "Template:ISOdate" 93 | }, 94 | { 95 | "ns": 10, 96 | "title": "Template:Infobar-Layout" 97 | }, 98 | { 99 | "ns": 10, 100 | "title": "Template:Information" 101 | }, 102 | { 103 | "ns": 10, 104 | "title": "Template:Information/author processing" 105 | }, 106 | { 107 | "ns": 10, 108 | "title": "Template:Lang" 109 | }, 110 | { 111 | "ns": 10, 112 | "title": "Template:LargeImage" 113 | }, 114 | { 115 | "ns": 10, 116 | "title": "Template:LargeImage/en" 117 | }, 118 | { 119 | "ns": 10, 120 | "title": "Template:LargeImage/layout" 121 | }, 122 | { 123 | "ns": 10, 124 | "title": "Template:Layout" 125 | }, 126 | { 127 | "ns": 10, 128 | "title": "Template:License template tag" 129 | }, 130 | { 131 | "ns": 10, 132 | "title": "Template:Namespace only" 133 | }, 134 | { 135 | "ns": 10, 136 | "title": "Template:PD-Layout" 137 | }, 138 | { 139 | "ns": 10, 140 | "title": "Template:PD-USGov-NASA" 141 | }, 142 | { 143 | "ns": 10, 144 | "title": "Template:PD-USGov-NASA/en" 145 | }, 146 | { 147 | "ns": 10, 148 | "title": "Template:PD-USGov-NASA/layout" 149 | }, 150 | { 151 | "ns": 10, 152 | "title": "Template:Parse source" 153 | }, 154 | { 155 | "ns": 10, 156 | "title": "Template:Tl" 157 | }, 158 | { 159 | "ns": 10, 160 | "title": "Template:TooLarge/layout" 161 | } 162 | ] 163 | } -------------------------------------------------------------------------------- /i18n/de/about.html: -------------------------------------------------------------------------------- 1 |

    Diese Anwendung soll Ihnen dabei helfen, Bilder aus Wikipedia und dem freien Medienarchiv 2 | Wikimedia Commons einfach und rechtssicher nachzunutzen.

    3 |

    Die Bilder, die auf Wikipedia im freien Medienarchiv Wikimedia Commons veröffentlicht werden, 4 | sind in vielen Fällen urheberrechtlich geschützt. Sie sind durch ihre Urheber aber zumeist unter 5 | so genannten freien Lizenzen zur Nutzung freigegeben worden, vor allem unter 6 | Creative-Commons-Lizenzen. Ein gewisser Anteil ist sogar komplett rechtefrei (public domain). 7 | Freie Lizenzen erlauben eine unkomplizierte Nachnutzung ohne viel Nachfragen, solange die 8 | jeweiligen Lizenzbedingungen eingehalten werden. Eine zusätzliche Erlaubnis der Urheber braucht 9 | es dann nicht. Diese Anwendung soll dabei helfen, die Lizenzbedingungen bei der Nachnutzung 10 | einzuhalten, und sie soll Hilfe bei der Verwendung frei lizenzierter Inhalte bieten. Dies 11 | funktioniert, indem die Anwendung alle Informationen anzeigt, die zusammen als so genannter 12 | Lizenzhinweis möglichst unmittelbar beim genutzten Bild abgedruckt bzw. angezeigt werden müssen 13 | (je nach Publikationsart kann auch eine übliche andere Stelle ausreichend sein für den Hinweis, 14 | bei einem Buch etwa eine zentrale Bildnachweisseite, bei einem Video etwa der Vor- oder 15 | Abspann). Die Anwendung geleitet Sie durch einen kurzen Dialog und erfährt dadurch die für den 16 | Lizenzhinweis entscheidenden Einzelheiten Ihrer individuellen Nachnutzung. Nach Beantwortung 17 | dieser wenigen Fragen können Sie schnell und einfach den entsprechenden Lizenzhinweis auf 18 | verschiedene Arten kopieren und in Ihre Publikation einfügen. Bisher deckt die Anwendung die 19 | Nachnutzung in digitalen und gedruckten Medien ab, da dies die häufigsten Nutzungsformen sind. 20 | Andere Nutzungen (z.B. Ausstellungen, Sendungen, Live-Darbietungen) bleiben vorerst 21 | unberücksichtigt.

    22 |

    Wir bedanken uns herzlich für die Unterstützung des Fachanwalts für Urheber- und Medienrecht Dr. 23 | Till Jaeger, JBB Rechtsanwälte in Berlin.

    24 |

    Welche Lizenzen werden unterstützt?

    25 |

    26 | Diese Anwendung unterstützt Bilder von Wikipedia und Wikimedia Commons, die unter 27 | Creative-Commons-Lizenzen freigegeben wurden. Folgende Lizenzen einschließlich portierter 28 | Varianten werden unterstützt: 29 |

    30 |
      31 |
    • CC 0
    • 32 |
    • CC BY 2.0 DE
    • 33 |
    • CC BY 3.0 DE
    • 34 |
    • CC BY 3.0 Unported
    • 35 |
    • CC BY 4.0 International
    • 36 |
    • CC BY-SA 1.0 (generic)
    • 37 |
    • CC BY-SA 2.0 DE
    • 38 |
    • CC BY-SA 3.0 DE
    • 39 |
    • CC BY-SA 3.0 Unported
    • 40 |
    • CC BY-SA 4.0 International
    • 41 |
    • CC BY 1.0 (generic)
    • 42 |
    • CC BY 2.0 (generic)
    • 43 |
    • CC BY 2.5 (generic)
    • 44 |
    • CC BY-SA 2.0 (generic)
    • 45 |
    • CC BY-SA 2.5 (generic)
    • 46 |
    47 |

    48 | Diese Anwendung soll die lizenzkonforme Nachnutzung von bestimmten urheberrechtlich geschützten 49 | Bildern vereinfachen. Sie kann niemals alle möglichen Anwendungsfälle und Besonderheiten 50 | abdecken und ersetzt in keinem Fall die qualifizierte juristische Beratung durch einen Anwalt. 51 |

    52 | -------------------------------------------------------------------------------- /i18n/en/about.html: -------------------------------------------------------------------------------- 1 |

    This tool makes it easy to reuse images from Wikipedia and the free media archive Wikimedia 2 | Commons.

    3 |

    Please note: The current English version of the Attribution Generator is based on a near-verbatim 4 | translation of the initial German text snippets, which were drafted with the copyright law of 5 | Germany in mind. Especially the parts explaining legal concepts might thus differ from the 6 | copyright law situation of other countries.

    7 |

    In many cases images on Wikipedia and the free media archive Wikimedia Commons are protected by 8 | copyright. However most of them have been released under free licenses by their rights holders, 9 | especially under Creative Commons licenses. Some are even free of any rights, in the public 10 | domain. Free licenses facilitate an easy re-use as long as the respective license requirements 11 | are honoured. An additional permission from rights holders is then not necessary. This tool is 12 | designed to help comply with the license conditions and simplify the use of freely licensed 13 | content. The tool automatically compiles all relevant license information in to a 14 | so-called license notice that has to be published or displayed as closely to the image as 15 | reasonably possible (depending on the publication type the license notice can also be placed at 16 | another common position e.g. within picture credits in a book or in the opening or final credits of a 17 | video). The tool leads you through a short dialogue and compiles all the information that is 18 | relevant for generating a correct license notice for your individual use case. After having 19 | answered these few questions you can quickly and easily copy the license notice in various 20 | formats and paste it into your publication. Currently, the tool covers the re-use in digital and 21 | printed works, being the most frequent forms of use. Other uses (e.g. exhibitions, broadcasts, 22 | live performances) remain unconsidered for the time being.

    23 |

    We would like to thank Dr. Till Jaeger, specialist lawyer for copyright and media law (JBB 24 | Rechtsanwälte in Berlin) for his generous support.

    25 |

    Which licenses are supported?

    26 |

    27 | The tool supports images from Wikipedia and the free media archive Wikimedia Commons that are 28 | released under Creative Commons licenses. The following licenses, including their ported versions, 29 | are supported: 30 |

    31 |
      32 |
    • CC 0
    • 33 |
    • CC BY 2.0 DE
    • 34 |
    • CC BY 3.0 DE
    • 35 |
    • CC BY 3.0 Unported
    • 36 |
    • CC BY 4.0 International
    • 37 |
    • CC BY-SA 1.0 (generic)
    • 38 |
    • CC BY-SA 2.0 DE
    • 39 |
    • CC BY-SA 3.0 DE
    • 40 |
    • CC BY-SA 3.0 Unported
    • 41 |
    • CC BY-SA 4.0 International
    • 42 |
    • CC BY 1.0 (generic)
    • 43 |
    • CC BY 2.0 (generic)
    • 44 |
    • CC BY 2.5 (generic)
    • 45 |
    • CC BY-SA 2.0 (generic)
    • 46 |
    • CC BY-SA 2.5 (generic)
    • 47 |
    48 |

    49 | This tool is designed to facilitate the compliant re-use of certain copyright-protected images. 50 | However, it can never cover all use cases and characteristics, and thus cannot replace qualified 51 | legal advice by a lawyer. 52 |

    53 | -------------------------------------------------------------------------------- /i18n/pl/about.html: -------------------------------------------------------------------------------- 1 |

    2 | To narzędzie pozwala w łatwy sposób wykorzystywać zdjęcia z Wikipedii i wolnej biblioteki 3 | multimediów Wikimedia Commons. 4 |

    5 |

    6 | Uwaga: Polska wersja Generatora Atrybucji powstała jako tłumaczenie angielskiej, która z kolei 7 | jest tłumaczeniem oryginalnej, niemieckiej, wersji. Z tego powodu, pewne wyjaśnienia mogą 8 | dotyczyć sytuacji prawnej w Niemczech, być może odbiegającej od prawodawstwa innych krajów. 9 |

    10 |

    11 | W wielu przypadkach grafiki na Wikipedii i w wolnej bibliotece Wikimedia Commons są chronione 12 | prawem autorskim. Mimo to, większość z nich została udostępniona przez ich autorów na wolnych 13 | licencjach, w szczególności licencjach Creative Commons. Niektóre nawet nie podlegają żadnej 14 | ochronie – znajdują się w domenie publicznej. Wolne licencje pozwalają w prosty sposób wykorzystywać 15 | zasoby, pod warunkiem że spełnione zostaną odpowiednie wymagania. Nie jest wymagana natomiast 16 | żadna dodatkowa zgoda od właściciela praw autorskich. 17 |

    18 |

    19 | To narzędzie zostało zaprojektowane, by pomóc w spełnieniu warunków licencyjnych oraz uprościć 20 | wykorzystanie zawartości na wolnej licencji. Pobiera ono i łączy wszystkie istotne informacje, 21 | aby stworzyć tzw. notkę licencyjną, która powinna zostać umieszczona tak blisko zdjęcia jak 22 | to jest możliwe (ale w sposób rozsądny; w zależności od rodzaju dzieła, taka informacja możliwe 23 | również znaleźć się w innym typowym miejscu, jak np. planszy ze źródłami ilustracji na końcu wideo). 24 |

    25 |

    26 | Narzędzie przeprowadzi Cię przez krótkie okno dialogowe i zbierze dane potrzebne do wygenerowania 27 | poprawnej informacji o licencji. Po odpowiedzeniu na te pytania, ukaże się gotowa do skopiowania 28 | formułka w różnych formatach. W tej chwili, obsługiwane jest tworzenie komunikatów w przypadku 29 | wykorzystania multimediów w pracach cyfrowych i drukowanych, czyli tych najpopularniejszych formach. 30 | Inne zastosowania (jak np. wystawy, transmisje, wystąpienia na żywo) nie są w tej chwili rozważane. 31 |

    32 |

    33 | Podziękowania należą się Dr. Tillowi Jaegerowi, prawnikowi specjalizującemu się w prawie autorskim 34 | i medialnym (JBB Rechtsanwälte w Berlinie) za jego hojne wsparcie. 35 |

    36 |

    Jakie licencje są obsługiwane?

    37 |

    38 | Niniejsze narzędzie działa z grafikami z Wikipedii i wolnej biblioteki Wikimedia Commons, które 39 | zostały udostępnione na licencjach Creative Commons. Wspierane są następujące licencje (łącznie 40 | z ich wersjami lokalizowanymi – „ported”): 41 |

    42 |
      43 |
    • CC 0
    • 44 |
    • CC BY 2.0 DE
    • 45 |
    • CC BY 3.0 DE
    • 46 |
    • CC BY 3.0 Unported
    • 47 |
    • CC BY 4.0 International
    • 48 |
    • CC BY-SA 1.0 (generic)
    • 49 |
    • CC BY-SA 2.0 DE
    • 50 |
    • CC BY-SA 3.0 DE
    • 51 |
    • CC BY-SA 3.0 Unported
    • 52 |
    • CC BY-SA 4.0 International
    • 53 |
    • CC BY 1.0 (generyczna)
    • 54 |
    • CC BY 2.0 (generyczna)
    • 55 |
    • CC BY 2.5 (generyczna)
    • 56 |
    • CC BY-SA 2.0 (generyczna)
    • 57 |
    • CC BY-SA 2.5 (generyczna)
    • 58 |
    59 |

    60 | Narzędzie to zostało zaprojektowane, aby ułatwić prawidłowe wykorzystanie pewnych obrazów 61 | chronionych prawem autorskim. Mimo to, nie ma gwarancji, że sprawdzi się we wszystkich sytuacjach, 62 | dlatego nie może zastąpić pomocy udzielonej przez prawnika. 63 |

    -------------------------------------------------------------------------------- /i18n/es/about.html: -------------------------------------------------------------------------------- 1 |

    Esta herramienta facilita la reutilización de imágenes de Wikipedia y de la mediateca libre Wikimedia 2 | Commons.

    3 |

    Ten en cuenta: la versión actual en inglés del Generador de Atribución está basada en una traducción casi literal de la traducción inicial de los fragmentos de texto en alemán, que fueron redactados teniendo en cuenta la ley de derechos de autor de Alemania. Las partes que explican los conceptos legales podrían diferir de la ley de derechos de autor de otros países.

    4 |

    En muchos casos, las imágenes almacenadas en Wikipedia y en la mediateca libre Wikimedia Commons están protegidas por derechos de autor. Sin embargo, la mayoría han sido liberadas bajo licencias libres por los titulares de sus derechos, especialmente bajo las licencias Creative Commons. Incluso algunas están libres de cualquier derecho, es decir, en el dominio público. Las licencias libres facilitan una reutilización sencilla siempre y cuando se respeten los requisitos respectivos de las mismas. No es necesario ningún permiso adicional de los titulares de derechos. Esta herramienta está diseñada para ayudar a cumplir con las condiciones de la licencia y simplificar el uso de contenidos con licencia libre. La herramienta compila automáticamente toda la información relevante de la licencia en un aviso de licencia que tiene que ser publicado o mostrado lo más cerca posible, razonablemente, de la imagen (dependiendo del tipo de publicación, la licencia también se puede colocarse en otro lugar habitual, p. ej. con los créditos de imágenes en un libro o en los créditos iniciales o finales de un vídeo). La herramienta te guía a través de un breve diálogo y compila toda la información relevante para generar la licencia correcta para tu caso de uso específico. Después de contestar todas las preguntas, podrás copiar rápida y fácilmente el aviso de licencia en diferentes formatos y pegarlo en tu publicación. Actualmente, la herramienta cubre la reutilización en trabajos digitales e impresos, que son las formas de uso más frecuentes. Existen otros usos (p. ej. exposiciones, programas de televisión y representaciones en directo) que aún no han sido considerados.

    5 |

    Nos gustaría agradecer al Dr. Till Jaeger, abogado especialista en la ley de medios de comunicación y derechos de autor (JBB Rechtsanwälte en Berlín) por su generoso apoyo. La traducción del Generador de Atribución en español no hubiera sido posible sin el aporte de Iván Hernandez Cazorla y Malcolm Bain. Por lo mismo deseamos expresarles nuestros más profundos agradecimientos.

    6 |

    ¿Qué licencias son compatibles?

    7 |

    8 | La herramienta soporta imágenes de Wikipedia y de la mediateca libre Wikimedia Commons que han sido liberadas bajo licencias Creative Commons. Las siguientes licencias, incluyendo sus versiones transpuestas (ported), son soportados: 9 |

    10 |
      11 |
    • CC 0
    • 12 |
    • CC BY 2.0 ES
    • 13 |
    • CC BY 3.0 ES
    • 14 |
    • CC BY 3.0 Unported
    • 15 |
    • CC BY 4.0 Internacional
    • 16 |
    • CC BY-SA 1.0 (generica)
    • 17 |
    • CC BY-SA 2.0 ES
    • 18 |
    • CC BY-SA 3.0 ES
    • 19 |
    • CC BY-SA 3.0 Unported
    • 20 |
    • CC BY-SA 4.0 Internacional
    • 21 |
    • CC BY 1.0 (generica)
    • 22 |
    • CC BY 2.0 (generica)
    • 23 |
    • CC BY 2.5 (generica)
    • 24 |
    • CC BY-SA 2.0 (generica)
    • 25 |
    • CC BY-SA 2.5 (generica)
    • 26 |
    27 |

    28 | Esta herramienta está diseñada para facilitar la reutilización conforme de determinadas imágenes protegidas por derechos de autor. Sin embargo, nunca podrá cubrirse todos los casos de uso y características, por lo que no puede sustituir el asesoramiento legal realizado por un abogado colegiado. 29 |

    30 | -------------------------------------------------------------------------------- /i18n/pt/about.html: -------------------------------------------------------------------------------- 1 |

    Esta ferramenta facilita a reutilização de imagens da Wikipédia e do repositório livre Wikimedia Commons.

    2 |

    Por favor note que a atual versão inglesa do Gerador de Atribuição é baseada numa tradução quase literal dos fragmentos iniciais de texto em alemão, que foram elaborados tendo em vista a legislação de direito de autor da Alemanha. Especificamente as partes que explicam os conceitos legais podem diferir de acordo com a legislação de direito de autor de outros países.

    3 |

    Em muitos casos, as imagens armazenadas na Wikipédia e no repositório livre Wikimedia Commons estão protegidas por direito de autor. No entanto, a maioria dessas imagens tem sido divulgada sob licenças livres pelos detentores dos seus direitos, especialmente sob licenças Creative Commons. Algumas até estão livres de quaisquer direitos, estando no domínio público. As licenças livres facilitam uma reutilização mais simples desde que os respectivos requisitos das licenças sejam respeitados. Uma autorização adicional por parte dos titulares dos direitos não é, pois, necessária. Esta ferramenta está desenhada para ajudar a cumprir com as condições da licença e simplificar o uso de conteúdo licenciado com licenças livres. Esta ferramenta compila automaticamente toda a informação relevante da licença num denominado aviso de licença que tem de ser publicado ou exibido o mais perto que seja razoavelmente possível da imagem (dependendo do tipo de publicação, a licença também pode ser colocada noutra posição habitual, p. ex. juntamente com os créditos de imagem de um livro ou nos créditos iniciais ou finais de um vídeo). A ferramenta guia-o através de um breve diálogo e compila toda a informação que seja relevante para gerar o correto aviso de licença para o seu caso específico de utilização. Depois de responder a estas poucas perguntas, você poderá copiar rápida e facilmente o aviso de licença em diferentes formatos e colá-lo na sua publicação. Atualmente, a ferramenta abrange a reutilização em trabalhos digitais e impressos, que são as formas de utilização mais frequentes. Existem outras utilizações (p. ex. exposições, programas de televisão e representações em direto) que, por enquanto, ainda não foram tidas em consideração.

    4 |

    Gostaríamos de agradecer ao Dr. Till Jaeger, advogado especialista em direito de autor e direito da comunicação social (JBB Rechtsanwälte em Berlim), pelo seu generoso apoio. A tradução do Gerador de Atribuição em Português não teria sido possível sem a contribuição de Santamarcanda e Teresa Nobre. Por isso, queremos expressar a nossa mais profunda gratidão. Obrigado!

    5 |

    Quais são as licenças suportadas?

    6 |

    7 | A ferramenta suporta imagens da Wikipédia e do repositório livre Wikimedia Commons que sejam divulgadas sob licenças Creative Commons. As seguintes licenças, incluindo as suas versões adaptadas, são suportadas: 8 |

    9 |
      10 |
    • CC 0
    • 11 |
    • CC BY 2.5 PT
    • 12 |
    • CC BY 3.0 PT
    • 13 |
    • CC BY 3.0 Não Adaptada
    • 14 |
    • CC BY 4.0 Internacional
    • 15 |
    • CC BY-SA 1.0 Genérica
    • 16 |
    • CC BY-SA 2.5 PT
    • 17 |
    • CC BY-SA 3.0 PT
    • 18 |
    • CC BY-SA 3.0 Não Adaptada
    • 19 |
    • CC BY-SA 4.0 Internacional
    • 20 |
    • CC BY 1.0 Genérica
    • 21 |
    • CC BY 2.0 Genérica
    • 22 |
    • CC BY 2.5 Genérica
    • 23 |
    • CC BY-SA 2.0 Genérica
    • 24 |
    • CC BY-SA 2.5 Genérica
    • 25 |
    26 |

    27 | Esta ferramenta foi desenhada para facilitar a reutilização correta de determinadas imagens protegidas por direito de autor. No entanto, nunca pode abranger todos os casos de utilização e todas as características, por isso não pode substituir o aconselhamento jurídico qualificado fornecido por um advogado. 28 |

    29 | -------------------------------------------------------------------------------- /tests/app/Api.tests.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author snater.com < wikimedia@snater.com > 4 | */ 5 | 6 | 'use strict'; 7 | 8 | var $ = require( 'jquery' ), 9 | Api = require( '../../js/app/Api' ), 10 | testAssets = require( '../assets' ), 11 | WikiAsset = require( '../../js/app/WikiAsset' ); 12 | 13 | QUnit.module( 'Api' ); 14 | 15 | var api = new Api( 'https://commons.wikimedia.org/' ); 16 | 17 | /** 18 | * Returns a nodes HTML as plain text. 19 | * 20 | * @param {jQuery|null} $node 21 | * @return {string|null} 22 | */ 23 | function getHtmlText( $node ) { 24 | return $node ? $( '
    ' ).append( $node ).html() : null; 25 | } 26 | 27 | QUnit.test( 'Check scraped asset', function( assert ) { 28 | 29 | $.each( testAssets, function( filename, testAsset ) { 30 | 31 | if( !( testAsset instanceof WikiAsset ) ) { 32 | return true; 33 | } 34 | 35 | QUnit.stop(); 36 | 37 | api.getAsset( 'File:' + filename, testAsset.getWikiUrl() ) 38 | .done( function( asset ) { 39 | 40 | assert.equal( 41 | asset.getFilename(), 42 | testAsset.getFilename(), 43 | 'Filename "' + asset.getFilename() + '" matches.' 44 | ); 45 | 46 | assert.equal( 47 | asset.getTitle(), 48 | testAsset.getTitle(), 49 | 'Title "' + asset.getTitle() + '" matches.' 50 | ); 51 | 52 | $.each( asset.getAuthors(), function( i, author ) { 53 | 54 | assert.equal( 55 | author.getText(), 56 | testAsset.getAuthors()[ i ].getText(), 57 | '"' + testAsset.getFilename() + '": Author text "' + author.getText() 58 | + '" matches.' 59 | ); 60 | 61 | var authorHtml = getHtmlText( author.getHtml() ); 62 | 63 | assert.equal( 64 | authorHtml, 65 | getHtmlText( testAsset.getAuthors()[ i ].getHtml() ), 66 | '"' + testAsset.getFilename() + '": Author html "' + authorHtml 67 | + '" matches.' 68 | ); 69 | 70 | } ); 71 | 72 | if( asset.getLicence() === null ) { 73 | assert.strictEqual( 74 | asset.getLicence(), 75 | testAsset.getLicence(), 76 | 'No supported licence.' 77 | ); 78 | } else { 79 | assert.equal( 80 | asset.getLicence().getId(), 81 | testAsset.getLicence().getId(), 82 | 'Licence "' + asset.getLicence().getId() + '" matches.' 83 | ); 84 | } 85 | 86 | assert.equal( 87 | getHtmlText( asset.getAttribution() ), 88 | getHtmlText( testAsset.getAttribution() ), 89 | 'Dedicated attribution of "' + testAsset.getFilename() + '" matches.' 90 | ); 91 | 92 | } ) 93 | .fail( function() { 94 | assert.ok( 95 | false, 96 | 'API call failed.' 97 | ); 98 | } ) 99 | .always( function() { 100 | QUnit.start(); 101 | } ); 102 | 103 | } ); 104 | 105 | } ); 106 | 107 | QUnit.test( 'getAsset() error handling', function( assert ) { 108 | var negativeTestCases = [ 109 | 'string that is not supposed to be the name of an existing image', 110 | '{invalid input}', 111 | // Not in "File:" namespace: 112 | 'TimedText:Elephants_Dream.ogg.ca.srt' 113 | ]; 114 | 115 | /** 116 | * @param {string} input 117 | */ 118 | function testAssetErrorHandling( input ) { 119 | QUnit.stop(); 120 | 121 | api.getAsset( 'File:' + input ) 122 | .done( function( parsedFilename ) { 123 | assert.ok( 124 | false, 125 | 'Unexpected result: "' + parsedFilename + '".' 126 | ); 127 | } ).fail( function( message ) { 128 | assert.ok( 129 | true, 130 | 'Rejected input "' + input + '" with error message "' + message + '".' 131 | ); 132 | } ) 133 | .always( function() { 134 | QUnit.start(); 135 | } ); 136 | } 137 | 138 | for( var i = 0; i < negativeTestCases.length; i++ ) { 139 | testAssetErrorHandling( negativeTestCases[ i ] ); 140 | } 141 | } ); 142 | -------------------------------------------------------------------------------- /tests/fixtures/templates/John_Flamsteed.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 72909, 3 | "ns": 6, 4 | "title": "File:John Flamsteed.jpg", 5 | "templates": [ 6 | { 7 | "ns": 10, 8 | "title": "Template:Authority control" 9 | }, 10 | { 11 | "ns": 10, 12 | "title": "Template:Authority control/BNF" 13 | }, 14 | { 15 | "ns": 10, 16 | "title": "Template:Authority control/GND" 17 | }, 18 | { 19 | "ns": 10, 20 | "title": "Template:Authority control/ISNI" 21 | }, 22 | { 23 | "ns": 10, 24 | "title": "Template:Authority control/LCCN" 25 | }, 26 | { 27 | "ns": 10, 28 | "title": "Template:Authority control/ULAN" 29 | }, 30 | { 31 | "ns": 10, 32 | "title": "Template:Authority control/VIAF" 33 | }, 34 | { 35 | "ns": 10, 36 | "title": "Template:Authority control/WorldCat" 37 | }, 38 | { 39 | "ns": 10, 40 | "title": "Template:Authority control tag" 41 | }, 42 | { 43 | "ns": 10, 44 | "title": "Template:Authority control tag: bare" 45 | }, 46 | { 47 | "ns": 10, 48 | "title": "Template:Between" 49 | }, 50 | { 51 | "ns": 10, 52 | "title": "Template:CC-Layout" 53 | }, 54 | { 55 | "ns": 10, 56 | "title": "Template:Cc-by-4.0" 57 | }, 58 | { 59 | "ns": 10, 60 | "title": "Template:Cc-by-layout" 61 | }, 62 | { 63 | "ns": 10, 64 | "title": "Template:City" 65 | }, 66 | { 67 | "ns": 10, 68 | "title": "Template:Conj" 69 | }, 70 | { 71 | "ns": 10, 72 | "title": "Template:CountryAdjective" 73 | }, 74 | { 75 | "ns": 10, 76 | "title": "Template:CountryAdjective/en" 77 | }, 78 | { 79 | "ns": 10, 80 | "title": "Template:CountryAdjective/en2iso" 81 | }, 82 | { 83 | "ns": 10, 84 | "title": "Template:Creator" 85 | }, 86 | { 87 | "ns": 10, 88 | "title": "Template:Creator template no image" 89 | }, 90 | { 91 | "ns": 10, 92 | "title": "Template:Dir" 93 | }, 94 | { 95 | "ns": 10, 96 | "title": "Template:Fallback" 97 | }, 98 | { 99 | "ns": 10, 100 | "title": "Template:GND" 101 | }, 102 | { 103 | "ns": 10, 104 | "title": "Template:ISOdate" 105 | }, 106 | { 107 | "ns": 10, 108 | "title": "Template:ISOyear" 109 | }, 110 | { 111 | "ns": 10, 112 | "title": "Template:IfNum" 113 | }, 114 | { 115 | "ns": 10, 116 | "title": "Template:Iffile" 117 | }, 118 | { 119 | "ns": 10, 120 | "title": "Template:Ifimage" 121 | }, 122 | { 123 | "ns": 10, 124 | "title": "Template:Infobox template tag" 125 | }, 126 | { 127 | "ns": 10, 128 | "title": "Template:Information" 129 | }, 130 | { 131 | "ns": 10, 132 | "title": "Template:Information/author processing" 133 | }, 134 | { 135 | "ns": 10, 136 | "title": "Template:IsNum" 137 | }, 138 | { 139 | "ns": 10, 140 | "title": "Template:LCCN" 141 | }, 142 | { 143 | "ns": 10, 144 | "title": "Template:LangSwitch" 145 | }, 146 | { 147 | "ns": 10, 148 | "title": "Template:License template tag" 149 | }, 150 | { 151 | "ns": 10, 152 | "title": "Template:London" 153 | }, 154 | { 155 | "ns": 10, 156 | "title": "Template:NationAndOccupation" 157 | }, 158 | { 159 | "ns": 10, 160 | "title": "Template:NationAndOccupation/default" 161 | }, 162 | { 163 | "ns": 10, 164 | "title": "Template:Nationality" 165 | }, 166 | { 167 | "ns": 10, 168 | "title": "Template:Nationality/en" 169 | }, 170 | { 171 | "ns": 10, 172 | "title": "Template:NoImageNotes" 173 | }, 174 | { 175 | "ns": 10, 176 | "title": "Template:Occupation" 177 | }, 178 | { 179 | "ns": 10, 180 | "title": "Template:Occupation/en" 181 | }, 182 | { 183 | "ns": 10, 184 | "title": "Template:Other date" 185 | }, 186 | { 187 | "ns": 10, 188 | "title": "Template:ParmPart" 189 | }, 190 | { 191 | "ns": 10, 192 | "title": "Template:Parse source" 193 | }, 194 | { 195 | "ns": 10, 196 | "title": "Template:Str left" 197 | }, 198 | { 199 | "ns": 10, 200 | "title": "Template:Str \u2264 len" 201 | }, 202 | { 203 | "ns": 10, 204 | "title": "Template:VIAF" 205 | }, 206 | { 207 | "ns": 10, 208 | "title": "Template:Works of authors who died more than 100 years ago" 209 | }, 210 | { 211 | "ns": 10, 212 | "title": "Template:Years since" 213 | } 214 | ] 215 | } -------------------------------------------------------------------------------- /tests/fixtures/revisions/Fiesta-Zuschauer Z1.jpeg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 7948879, 3 | "ns": 6, 4 | "title": "Datei:Fiesta-Zuschauer Z1.jpeg", 5 | "revisions": [ 6 | { 7 | "*": "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n
    Beschreibung\n\n

    Zuschauer bei einer lokalen Fiesta/Nordspanien\n

    \n
    Quelle\n\n

    eigene Aufnahme\n

    \n
    Urheber bzw.
    Nutzungsrechtinhaber\n
    \n

    Ziegler175\n

    \n
    Datum\n\n

    1988-08\n

    \n
    Genehmigung\n\n
    \n\n\n\n
    Sie können diese Datei ohne Bedingungen weiterverwenden:
    \n

    Die Datei wurde unter der Lizenz
    \nCreative Commons Zero
    in Version 1.0 (abgekürzt „CC-0 1.0“) veröffentlicht.\n

    \n
    \"CC-Zero\"1.0\n
    \n
    \n
    \n

    Den rechtsverbindlichen Lizenzvertrag finden Sie unter http://creativecommons.org/publicdomain/zero/1.0/legalcode.

    \n

    Es folgt eine vereinfachte Zusammenfassung des Vertrags in allgemeinverständlicher Sprache ohne juristische Wirkung.

    \n
    \n
    \n

    Es ist Ihnen gestattet,\n

    \n
    \"Weiterverwendung
     das Werk zu vervielfältigen, zu verbreiten, öffentlich zugänglich zu machen oder anders zu verwerten sowie
    \n
    \"Bearbeitung
     Abwandlungen und Bearbeitungen des Werkes anzufertigen und diese zu verwerten.
    \n

    Der Urheber oder Rechteinhaber knüpft daran keine Bedingungen.\n

    \n
    \n

    Bitte beachten Sie, dass andere Rechte die Weiterverwendung einschränken können.\n

    \n
    \n

    false\nfalse\nhttp://creativecommons.org/publicdomain/zero/1.0/\n

    \n
    \n
    \n" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /images/how_it_works-3.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 6 | 7 | 8 | 9 | 16 | 17 | 18 | 23 | 24 | 25 | 35 | 36 | 37 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /tests/fixtures/revisions/1950_Yankees.jpg.json: -------------------------------------------------------------------------------- 1 | { 2 | "pageid": 17475162, 3 | "ns": 6, 4 | "title": "File:1950 Yankees.jpg", 5 | "revisions": [ 6 | { 7 | "*": "
    \n\n\n\n\n\n\n\n \n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n \n\n
    Description1950 Yankees.jpg\n
    English: The 1950 New York Yankees being honored at 2010 Old-Timers' Day
    \n
    Date
    Sourcehttp://www.flickr.com/photos/jcasabona/4804366301/in/photostream/
    Authorjcasabona
    Permission
    (Reusing this file)
    \n\n\n\n\n\n\n\n\n
    \"w:en:Creative
    \"attribution\"\n
    This file is licensed under the Creative Commons Attribution 1.0 Generic license.\n\n
    \n
    \n
    You are free:\n
    • to share – to copy, distribute and transmit the work
    • \n
    • to remix – to adapt the work
    \n
    Under the following conditions:\n
    • attribution – You must attribute the work in the manner specified by the author or licensor (but not in any way that suggests that they endorse you or your use of the work).
    \n

    http://creativecommons.org/licenses/by/1.0\nCC BY 1.0 \nCreative Commons Attribution 1.0 \ntruetrue\n

    \n
    \n
    \n
    \n" 8 | } 9 | ] 10 | } -------------------------------------------------------------------------------- /tests/LocalApi.js: -------------------------------------------------------------------------------- 1 | /** 2 | * @licence GNU GPL v3 3 | * @author Leszek Manicki < leszek.manicki@wikimedia.de > 4 | */ 5 | 'use strict'; 6 | 7 | var $ = require( 'jquery' ), 8 | Api = require( '../js/app/Api' ), 9 | ApplicationError = require( '../js/app/ApplicationError' ); 10 | 11 | /** 12 | * A mock of Commons API handler (@see Api). 13 | * Provides locally stored API response data. 14 | * @constructor 15 | * 16 | * @param {string} dataDirectory Directory containing API response data 17 | */ 18 | var LocalApi = function( dataDirectory ) { 19 | this._dataDirectory = dataDirectory; 20 | }; 21 | 22 | $.extend( LocalApi.prototype, Api.prototype, { 23 | /** 24 | * @type {string} 25 | */ 26 | _dataDirectory: null, 27 | 28 | /** 29 | * Simulates a call to the API by reading API response data from local file 30 | * 31 | * @param {string|string[]} title Page title(s) 32 | * @param {string} property 33 | * @param {string} [wikiUrl] 34 | * @param {Object} [params] API request parameter overwrites or additional parameters. 35 | * @return {Object} jQuery Promise 36 | * Resolved parameters: 37 | * - {Object[]} 38 | * Rejected parameters: 39 | * - {ApplicationError} 40 | */ 41 | _getResultsFromApi: function( title, property, wikiUrl, params ) { 42 | return this._readFile( this._getLocalFilename( title, property, params ) ); 43 | }, 44 | 45 | /** 46 | * Simulates a call to the API by reading API response data from local file 47 | * 48 | * @param {string} pageId 49 | * @param {string} [wikiUrl] 50 | * @returns {Object} jQuery Promise 51 | * Resolved parameters: 52 | * - {string} 53 | * Rejected parameters: 54 | * - {ApplicationError} 55 | */ 56 | getTitleFromPageId: function( pageId, wikiUrl ) { 57 | return this._readFile( this._getLocalFilename( pageId, null ) ); 58 | }, 59 | 60 | /** 61 | * Returns filename of file containing API response data 62 | * for the given page (title or ID) and given API query property and params. 63 | * 64 | * @param title 65 | * @param {string} property 66 | * @param {Object} params 67 | * @return {string} 68 | */ 69 | _getLocalFilename: function( title, property, params ) { 70 | var subdirectory; 71 | 72 | if( $.isArray( title ) ) { 73 | return this._getLocalFilename( title[ 0 ], property, params ); 74 | } 75 | 76 | title = this._escapeUrlCharacters( title ); 77 | 78 | subdirectory = this._getSubdirectory( property, params ); 79 | return this._dataDirectory + '/' + subdirectory + '/' + this._removeNamespace( title ) + '.json'; 80 | }, 81 | 82 | /** 83 | * Removes a namespace prefix from title. 84 | * 85 | * @param title 86 | * @return {string} 87 | */ 88 | _removeNamespace: function( title ) { 89 | return title.replace( /^[^:]+:/, '' ); 90 | }, 91 | 92 | /** 93 | * Replaces characters having special meaning in URLs to their "safe" equivalents, so pages with titles 94 | * containing these characters could be loaded properly. 95 | * 96 | * @param {string} title 97 | * @return {string} 98 | */ 99 | _escapeUrlCharacters: function( title ) { 100 | return title.replace( '?', '%3F' ); 101 | }, 102 | 103 | /** 104 | * Returns subdirectory under which JSON files respective for the given query property 105 | * and parameters are located. 106 | * 107 | * @param {string} property 108 | * @param {Object} params 109 | * @return {string} 110 | */ 111 | _getSubdirectory: function( property, params ) { 112 | if( property === null ) { 113 | return 'titles'; 114 | } 115 | 116 | if( property === 'imageinfo' ) { 117 | if( params.iiprop === 'mediatype|url' ) { 118 | return 'metadata'; 119 | } 120 | if( params.iiurlwidth === 300 || params.iiurlheight === 300 ) { 121 | return 'imageinfo'; 122 | } 123 | } 124 | 125 | if( property === 'templates' || property === 'revisions' || property === 'images' ) { 126 | return property; 127 | } 128 | }, 129 | 130 | /** 131 | * Reads API response data from local file. 132 | * 133 | * @param {string} filename 134 | * @return {Object} jQuery Promise 135 | * Resolved parameters: 136 | * - {Object[]} 137 | * Rejected parameters: 138 | * - {ApplicationError} 139 | */ 140 | _readFile: function( filename ) { 141 | var deferred = $.Deferred(); 142 | 143 | $.getJSON( filename ) 144 | .done( function( data ) { 145 | deferred.resolve( data ); 146 | } ) 147 | .fail( function() { 148 | deferred.reject( new ApplicationError( 'file-not-exist', {} ) ); 149 | } ); 150 | 151 | return deferred.promise(); 152 | } 153 | } ); 154 | 155 | module.exports = LocalApi; 156 | -------------------------------------------------------------------------------- /tests/app/ProgressBarView.tests.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | QUnit.module( 'Progress Bar UI' ); 4 | 5 | var ProgressBarView = require( '../../js/app/views/ProgressBarView' ), 6 | Asset = require( '../../js/app/Asset' ), 7 | Author = require( '../../js/app/Author' ), 8 | AttributionDialogue = require( '../../js/app/AttributionDialogue' ), 9 | $ = require( 'jquery' ), 10 | Helpers = require( '../TestHelpers' ); 11 | 12 | QUnit.test( 'should have 5 steps by default', function( assert ) { 13 | assert.equal( new ProgressBarView( Helpers.newDefaultAttributionDialogue() ).render().find( 'li' ).length, 5 ); 14 | } ); 15 | 16 | QUnit.test( 'should initially not have any substeps', function( assert ) { 17 | assert.equal( new ProgressBarView( Helpers.newDefaultAttributionDialogue() ).render().find( '.sub' ).length, 0 ); 18 | } ); 19 | 20 | QUnit.test( 'should have only 4 steps if the author is known', function( assert ) { 21 | var asset = new Asset( '', '', null, null, [ new Author( $( 'Meh' ) ) ] ), 22 | dialogue = new AttributionDialogue( asset ), 23 | pb = new ProgressBarView( dialogue ); 24 | dialogue.init(); 25 | 26 | assert.equal( pb.render().find( 'li' ).length, 4 ); 27 | } ); 28 | 29 | QUnit.test( 'should add 3 substeps for editing', function( assert ) { 30 | var dialogue = Helpers.newDefaultAttributionDialogue(), 31 | pb = new ProgressBarView( dialogue ); 32 | 33 | dialogue.currentStep().complete( {} ); 34 | dialogue.currentStep().complete( {} ); 35 | dialogue.currentStep().complete( {} ); 36 | dialogue.currentStep().complete( { edited: 'true' } ); 37 | 38 | assert.equal( pb.render().find( 'li' ).length, 8 ); 39 | assert.equal( pb.render().find( 'li.sub' ).length, 3 ); 40 | } ); 41 | 42 | QUnit.test( 'should mark first step as active at the start', function( assert ) { 43 | assert.equal( new ProgressBarView( Helpers.newDefaultAttributionDialogue() ).render().find( 'li.active' ).length, 1 ); 44 | } ); 45 | 46 | QUnit.test( 'should mark step < current step as completed and current step as active', function( assert ) { 47 | var dialogue = Helpers.newDefaultAttributionDialogue(), 48 | pb = new ProgressBarView( dialogue ); 49 | 50 | assert.equal( pb.render().find( 'li.active' ).length, 1 ); 51 | assert.equal( pb.render().find( 'li.completed' ).length, 0 ); 52 | 53 | dialogue.currentStep().complete( {} ); 54 | assert.equal( pb.render().find( 'li.active' ).length, 1 ); 55 | assert.equal( pb.render().find( 'li.completed' ).length, 1 ); 56 | 57 | dialogue.currentStep().complete( {} ); 58 | assert.equal( pb.render().find( 'li.active' ).length, 1 ); 59 | assert.equal( pb.render().find( 'li.completed' ).length, 2 ); 60 | } ); 61 | 62 | QUnit.test( 'should mark all steps completed when the attribution is shown', function( assert ) { 63 | var dialogue = Helpers.newDefaultAttributionDialogue(), 64 | pb = new ProgressBarView( dialogue ); 65 | dialogue.currentStep().complete( {} ); 66 | dialogue.currentStep().complete( {} ); 67 | dialogue.currentStep().complete( {} ); 68 | dialogue.currentStep().complete( {} ); 69 | 70 | assert.equal( pb.render().find( 'li.active' ).length, 1 ); 71 | assert.equal( pb.render().find( 'li.completed' ).length, 4 ); 72 | } ); 73 | 74 | QUnit.test( 'go back using by clicking on a progress bar item', function( assert ) { 75 | var dialogueView = Helpers.newDefaultAttributionDialogueView(), 76 | dialogue = dialogueView._dialogue, 77 | pb = new ProgressBarView( dialogue, dialogueView ), 78 | initialStep = dialogue.currentStep(); 79 | 80 | dialogue.currentStep().complete( {} ); 81 | $( pb.render().find( 'li a' ) [ 0 ] ).click(); 82 | assert.equal( dialogue.currentStep(), initialStep ); 83 | } ); 84 | 85 | QUnit.test( 'going to steps that were not previously completed should not be possible', function( assert ) { 86 | var dialogueView = Helpers.newDefaultAttributionDialogueView(), 87 | dialogue = dialogueView._dialogue, 88 | pb = new ProgressBarView( dialogue, dialogueView ), 89 | initialStep = dialogue.currentStep(); 90 | 91 | $( pb.render().find( 'li a' )[ 2 ] ).click(); 92 | assert.equal( dialogue.currentStep(), initialStep ); 93 | } ); 94 | 95 | QUnit.test( 'should remove 3 editing substeps when going back further than editing', function( assert ) { 96 | var dialogueView = Helpers.newDefaultAttributionDialogueView(), 97 | dialogue = dialogueView._dialogue, 98 | pb = new ProgressBarView( dialogue, dialogueView ); 99 | 100 | dialogue.currentStep().complete( {} ); 101 | dialogue.currentStep().complete( {} ); 102 | dialogue.currentStep().complete( {} ); 103 | dialogue.currentStep().complete( { edited: 'true' } ); 104 | 105 | assert.equal( dialogue.getSteps().length, 7 ); 106 | $( pb.render().find( 'li a' )[ 2 ] ).click(); 107 | assert.equal( dialogue.getSteps().length, 4 ); 108 | } ); 109 | --------------------------------------------------------------------------------