Full Code of ippontech/tatami for AI

master 90fdbfc474dc cached
1921 files
12.9 MB
3.5M tokens
1 requests
Copy disabled (too large) Download .txt
Showing preview only (14,137K chars total). Download the full file to get everything.
Repository: ippontech/tatami
Branch: master
Commit: 90fdbfc474dc
Files: 1921
Total size: 12.9 MB

Directory structure:
gitextract_2urwtjut/

├── .gitignore
├── CONTRIBUTING.md
├── README.md
├── etc/
│   └── installation/
│       └── ubuntu/
│           ├── files/
│           │   └── maven/
│           │       └── settings.xml
│           ├── install.sh
│           ├── uninstall.sh
│           └── update.sh
├── jenkinsScripts/
│   ├── insertGoogleAuthKeys.sh
│   ├── restoreDatabase.sh
│   ├── saveDatabase.sh
│   ├── startTatami.sh
│   └── stopTatami.sh
├── mobile/
│   ├── .bowerrc
│   ├── .editorconfig
│   ├── .gitignore
│   ├── README.md
│   ├── bower.json
│   ├── config.xml
│   ├── gulpfile.js
│   ├── hooks/
│   │   ├── README.md
│   │   └── after_prepare/
│   │       └── 010_add_platform_class.js
│   ├── ionic.project
│   ├── karma.ci.conf.js
│   ├── package.json
│   ├── pom.xml
│   ├── resources/
│   │   ├── icon.psd
│   │   └── splash.psd
│   ├── scss/
│   │   └── ionic.app.scss
│   └── www/
│       ├── app/
│       │   ├── components/
│       │   │   ├── follow/
│       │   │   │   ├── follow.html
│       │   │   │   ├── follow.js
│       │   │   │   ├── follower/
│       │   │   │   │   ├── follower.controller.js
│       │   │   │   │   ├── follower.html
│       │   │   │   │   └── follower.js
│       │   │   │   ├── following/
│       │   │   │   │   ├── following.controller.js
│       │   │   │   │   ├── following.html
│       │   │   │   │   └── following.js
│       │   │   │   └── suggested/
│       │   │   │       ├── suggested.controller.js
│       │   │   │       ├── suggested.html
│       │   │   │       └── suggested.js
│       │   │   ├── home/
│       │   │   │   ├── favorites/
│       │   │   │   │   ├── favorites.controller.js
│       │   │   │   │   ├── favorites.html
│       │   │   │   │   └── favorites.js
│       │   │   │   ├── home.html
│       │   │   │   ├── home.js
│       │   │   │   ├── mentions/
│       │   │   │   │   ├── mentions.controller.js
│       │   │   │   │   ├── mentions.html
│       │   │   │   │   └── mentions.js
│       │   │   │   ├── more/
│       │   │   │   │   ├── all_users/
│       │   │   │   │   │   ├── all.users.controller.js
│       │   │   │   │   │   ├── all.users.html
│       │   │   │   │   │   └── all.users.js
│       │   │   │   │   ├── blocked_users/
│       │   │   │   │   │   ├── blocked.users.controller.js
│       │   │   │   │   │   ├── blocked.users.html
│       │   │   │   │   │   └── blocked.users.js
│       │   │   │   │   ├── company/
│       │   │   │   │   │   ├── company-timeline.html
│       │   │   │   │   │   ├── company.timeline.controller.js
│       │   │   │   │   │   └── company.timeline.js
│       │   │   │   │   ├── more.controller.js
│       │   │   │   │   ├── more.html
│       │   │   │   │   ├── more.js
│       │   │   │   │   ├── reportedStatus/
│       │   │   │   │   │   ├── reportedStatus.controller.js
│       │   │   │   │   │   ├── reportedStatus.html
│       │   │   │   │   │   └── reportedStatus.js
│       │   │   │   │   └── settings/
│       │   │   │   │       ├── settings.controller.js
│       │   │   │   │       ├── settings.html
│       │   │   │   │       └── settings.js
│       │   │   │   └── timeline/
│       │   │   │       ├── timeline.controller.js
│       │   │   │       ├── timeline.html
│       │   │   │       └── timeline.js
│       │   │   ├── login/
│       │   │   │   ├── login.controller.js
│       │   │   │   ├── login.html
│       │   │   │   ├── login.js
│       │   │   │   └── server/
│       │   │   │       ├── server.controller.js
│       │   │   │       ├── server.html
│       │   │   │       └── server.js
│       │   │   └── post/
│       │   │       ├── post.controller.js
│       │   │       ├── post.html
│       │   │       ├── post.js
│       │   │       └── postbar.directive.js
│       │   ├── shared/
│       │   │   ├── config/
│       │   │   │   ├── marked.config.js
│       │   │   │   ├── marked.filter.js
│       │   │   │   └── tatami.marked.js
│       │   │   ├── interceptor/
│       │   │   │   └── auth.interceptor.js
│       │   │   ├── providers/
│       │   │   │   ├── provider.js
│       │   │   │   └── tatami.state.provider.js
│       │   │   ├── services/
│       │   │   │   ├── HomeService.js
│       │   │   │   ├── ProfileService.js
│       │   │   │   ├── StatusService.js
│       │   │   │   ├── UserService.js
│       │   │   │   ├── account.service.js
│       │   │   │   ├── block.service.js
│       │   │   │   ├── localStorage.service.js
│       │   │   │   ├── path.service.js
│       │   │   │   ├── report.service.js
│       │   │   │   ├── service.js
│       │   │   │   ├── tag.service.js
│       │   │   │   └── toast.service.js
│       │   │   ├── state/
│       │   │   │   ├── conversation/
│       │   │   │   │   ├── conversation.controller.js
│       │   │   │   │   └── conversation.html
│       │   │   │   ├── profile/
│       │   │   │   │   ├── profile.controller.js
│       │   │   │   │   ├── profile.html
│       │   │   │   │   └── userOptionsMenu.html
│       │   │   │   └── tag/
│       │   │   │       ├── tag.controller.js
│       │   │   │       └── tag.html
│       │   │   ├── status/
│       │   │   │   ├── blockUserMenu.html
│       │   │   │   ├── list/
│       │   │   │   │   ├── status-list.html
│       │   │   │   │   └── status.list.directive.js
│       │   │   │   ├── status.directive.js
│       │   │   │   ├── status.html
│       │   │   │   └── status.refresher.service.js
│       │   │   └── user/
│       │   │       ├── user-detail.html
│       │   │       ├── user.detail.directive.js
│       │   │       ├── user.directive.js
│       │   │       ├── user.html
│       │   │       ├── user.refresher.service.js
│       │   │       ├── users.directive.js
│       │   │       └── users.html
│       │   ├── tatami.controller.js
│       │   ├── tatami.endpoint.js
│       │   ├── tatami.html
│       │   └── tatamiApp.js
│       ├── css/
│       │   ├── ionic.app.css
│       │   └── style.css
│       ├── i18n/
│       │   ├── en/
│       │   │   ├── conversation.json
│       │   │   ├── follow.json
│       │   │   ├── home.json
│       │   │   ├── login.json
│       │   │   ├── more.json
│       │   │   ├── post.json
│       │   │   ├── server.json
│       │   │   ├── status.json
│       │   │   └── user.json
│       │   └── fr/
│       │       ├── conversation.json
│       │       ├── follow.json
│       │       ├── home.json
│       │       ├── login.json
│       │       ├── more.json
│       │       ├── post.json
│       │       ├── server.json
│       │       ├── status.json
│       │       └── user.json
│       ├── index.html
│       └── test/
│           └── javascript/
│               └── components/
│                   └── profile/
│                       └── profile.controller.spec.js
├── pom.xml
├── scripts/
│   └── insertBuildVersion.sh
├── services/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   ├── fr/
│       │   │   │   └── ippon/
│       │   │   │       └── tatami/
│       │   │   │           ├── config/
│       │   │   │           │   ├── ApplicationConfiguration.java
│       │   │   │           │   ├── AsyncConfiguration.java
│       │   │   │           │   ├── CacheConfiguration.java
│       │   │   │           │   ├── CassandraConfiguration.java
│       │   │   │           │   ├── ColumnFamilyKeys.java
│       │   │   │           │   ├── Constants.java
│       │   │   │           │   ├── DispatcherServletConfig.java
│       │   │   │           │   ├── GroupRoles.java
│       │   │   │           │   ├── MailConfiguration.java
│       │   │   │           │   ├── MetricsConfiguration.java
│       │   │   │           │   ├── SearchConfiguration.java
│       │   │   │           │   └── metrics/
│       │   │   │           │       ├── CassandraHealthCheck.java
│       │   │   │           │       └── JavaMailHealthCheck.java
│       │   │   │           ├── domain/
│       │   │   │           │   ├── Attachment.java
│       │   │   │           │   ├── Avatar.java
│       │   │   │           │   ├── DigestType.java
│       │   │   │           │   ├── Domain.java
│       │   │   │           │   ├── DomainConfiguration.java
│       │   │   │           │   ├── Group.java
│       │   │   │           │   ├── User.java
│       │   │   │           │   ├── UserStatusStat.java
│       │   │   │           │   ├── status/
│       │   │   │           │   │   ├── AbstractStatus.java
│       │   │   │           │   │   ├── Announcement.java
│       │   │   │           │   │   ├── MentionFriend.java
│       │   │   │           │   │   ├── MentionShare.java
│       │   │   │           │   │   ├── Share.java
│       │   │   │           │   │   ├── Status.java
│       │   │   │           │   │   ├── StatusDetails.java
│       │   │   │           │   │   └── StatusType.java
│       │   │   │           │   └── validation/
│       │   │   │           │       ├── ContraintsAttachmentCreation.java
│       │   │   │           │       └── ContraintsUserCreation.java
│       │   │   │           ├── repository/
│       │   │   │           │   ├── AppleDeviceRepository.java
│       │   │   │           │   ├── AppleDeviceUserRepository.java
│       │   │   │           │   ├── AttachmentRepository.java
│       │   │   │           │   ├── AvatarRepository.java
│       │   │   │           │   ├── BlockRepository.java
│       │   │   │           │   ├── CounterRepository.java
│       │   │   │           │   ├── DaylineRepository.java
│       │   │   │           │   ├── DiscussionRepository.java
│       │   │   │           │   ├── DomainConfigurationRepository.java
│       │   │   │           │   ├── DomainRepository.java
│       │   │   │           │   ├── DomainlineRepository.java
│       │   │   │           │   ├── FavoritelineRepository.java
│       │   │   │           │   ├── FollowerRepository.java
│       │   │   │           │   ├── FriendRepository.java
│       │   │   │           │   ├── GroupCounterRepository.java
│       │   │   │           │   ├── GroupDetailsRepository.java
│       │   │   │           │   ├── GroupMembersRepository.java
│       │   │   │           │   ├── GroupRepository.java
│       │   │   │           │   ├── GrouplineRepository.java
│       │   │   │           │   ├── IdempotentRepository.java
│       │   │   │           │   ├── MailDigestRepository.java
│       │   │   │           │   ├── MentionlineRepository.java
│       │   │   │           │   ├── RegistrationRepository.java
│       │   │   │           │   ├── ResolvedReportRepository.java
│       │   │   │           │   ├── RssUidRepository.java
│       │   │   │           │   ├── SharesRepository.java
│       │   │   │           │   ├── StatusAttachmentRepository.java
│       │   │   │           │   ├── StatusReportRepository.java
│       │   │   │           │   ├── StatusRepository.java
│       │   │   │           │   ├── TagCounterRepository.java
│       │   │   │           │   ├── TagFollowerRepository.java
│       │   │   │           │   ├── TaglineRepository.java
│       │   │   │           │   ├── TimelineRepository.java
│       │   │   │           │   ├── TrendRepository.java
│       │   │   │           │   ├── UserAttachmentRepository.java
│       │   │   │           │   ├── UserGroupRepository.java
│       │   │   │           │   ├── UserRepository.java
│       │   │   │           │   ├── UserTagRepository.java
│       │   │   │           │   ├── UserTrendRepository.java
│       │   │   │           │   ├── UserlineRepository.java
│       │   │   │           │   └── cassandra/
│       │   │   │           │       ├── AbstractCassandraFollowerRepository.java
│       │   │   │           │       ├── AbstractCassandraFriendRepository.java
│       │   │   │           │       ├── AbstractCassandraLineRepository.java
│       │   │   │           │       ├── CassandraAppleDeviceRepository.java
│       │   │   │           │       ├── CassandraAppleDeviceUserRepository.java
│       │   │   │           │       ├── CassandraAttachmentRepository.java
│       │   │   │           │       ├── CassandraAvatarRepository.java
│       │   │   │           │       ├── CassandraBlockRepository.java
│       │   │   │           │       ├── CassandraCounterRepository.java
│       │   │   │           │       ├── CassandraDaylineRepository.java
│       │   │   │           │       ├── CassandraDiscussionRepository.java
│       │   │   │           │       ├── CassandraDomainConfigurationRepository.java
│       │   │   │           │       ├── CassandraDomainRepository.java
│       │   │   │           │       ├── CassandraDomainlineRepository.java
│       │   │   │           │       ├── CassandraFavoritelineRepository.java
│       │   │   │           │       ├── CassandraFollowerRepository.java
│       │   │   │           │       ├── CassandraFriendRepository.java
│       │   │   │           │       ├── CassandraGroupCounterRepository.java
│       │   │   │           │       ├── CassandraGroupDetailsRepository.java
│       │   │   │           │       ├── CassandraGroupMembersRepository.java
│       │   │   │           │       ├── CassandraGroupRepository.java
│       │   │   │           │       ├── CassandraGrouplineRepository.java
│       │   │   │           │       ├── CassandraIdempotentRepository.java
│       │   │   │           │       ├── CassandraMailDigestRepository.java
│       │   │   │           │       ├── CassandraMentionlineRepository.java
│       │   │   │           │       ├── CassandraRegistrationRepository.java
│       │   │   │           │       ├── CassandraRssUidRepository.java
│       │   │   │           │       ├── CassandraSharesRepository.java
│       │   │   │           │       ├── CassandraStatusAttachmentRepository.java
│       │   │   │           │       ├── CassandraStatusReportRepository.java
│       │   │   │           │       ├── CassandraStatusRepository.java
│       │   │   │           │       ├── CassandraTagCounterRepository.java
│       │   │   │           │       ├── CassandraTagFollowerRepository.java
│       │   │   │           │       ├── CassandraTaglineRepository.java
│       │   │   │           │       ├── CassandraTimelineRepository.java
│       │   │   │           │       ├── CassandraTrendRepository.java
│       │   │   │           │       ├── CassandraUserAttachmentRepository.java
│       │   │   │           │       ├── CassandraUserGroupRepository.java
│       │   │   │           │       ├── CassandraUserRepository.java
│       │   │   │           │       ├── CassandraUserTagRepository.java
│       │   │   │           │       ├── CassandraUserTrendRepository.java
│       │   │   │           │       └── CassandraUserlineRepository.java
│       │   │   │           ├── security/
│       │   │   │           │   ├── AjaxAuthenticationFailureHandler.java
│       │   │   │           │   ├── AjaxAuthenticationSuccessHandler.java
│       │   │   │           │   ├── AjaxLogoutSuccessHandler.java
│       │   │   │           │   ├── AuthenticationService.java
│       │   │   │           │   ├── DomainViolationException.java
│       │   │   │           │   ├── GoogleApiAuthenticationProvider.java
│       │   │   │           │   ├── GoogleAuthenticationProvider.java
│       │   │   │           │   ├── GoogleAuthenticationToken.java
│       │   │   │           │   ├── GoogleAutoRegisteringUserDetailsService.java
│       │   │   │           │   ├── Http401UnauthorizedEntryPoint.java
│       │   │   │           │   ├── OpenIdAutoRegisteringUserDetailsService.java
│       │   │   │           │   ├── TatamiAuthenticationSuccessHandler.java
│       │   │   │           │   ├── TatamiLdapAuthenticationProvider.java
│       │   │   │           │   ├── TatamiUserDetailsService.java
│       │   │   │           │   └── xauth/
│       │   │   │           │       ├── Token.java
│       │   │   │           │       ├── TokenProvider.java
│       │   │   │           │       └── XAuthTokenFilter.java
│       │   │   │           ├── service/
│       │   │   │           │   ├── AdminService.java
│       │   │   │           │   ├── ApplePushService.java
│       │   │   │           │   ├── AtmosphereService.java
│       │   │   │           │   ├── AttachmentService.java
│       │   │   │           │   ├── AvatarService.java
│       │   │   │           │   ├── BlockService.java
│       │   │   │           │   ├── CounterService.java
│       │   │   │           │   ├── FriendshipService.java
│       │   │   │           │   ├── GroupService.java
│       │   │   │           │   ├── MailDigestService.java
│       │   │   │           │   ├── MailService.java
│       │   │   │           │   ├── MentionService.java
│       │   │   │           │   ├── SearchService.java
│       │   │   │           │   ├── StatsService.java
│       │   │   │           │   ├── StatusUpdateService.java
│       │   │   │           │   ├── SuggestionService.java
│       │   │   │           │   ├── TagMembershipService.java
│       │   │   │           │   ├── TimelineService.java
│       │   │   │           │   ├── TrendService.java
│       │   │   │           │   ├── UserService.java
│       │   │   │           │   ├── dto/
│       │   │   │           │   │   ├── StatusDTO.java
│       │   │   │           │   │   ├── UserDTO.java
│       │   │   │           │   │   └── UserGroupDTO.java
│       │   │   │           │   ├── elasticsearch/
│       │   │   │           │   │   ├── ElasticsearchEngine.java
│       │   │   │           │   │   ├── ElasticsearchSearchService.java
│       │   │   │           │   │   ├── EmbeddedElasticsearchEngine.java
│       │   │   │           │   │   └── RemoteElasticsearchEngine.java
│       │   │   │           │   ├── exception/
│       │   │   │           │   │   ├── ArchivedGroupException.java
│       │   │   │           │   │   ├── ReplyStatusException.java
│       │   │   │           │   │   └── StorageSizeException.java
│       │   │   │           │   └── util/
│       │   │   │           │       ├── AnalysisUtil.java
│       │   │   │           │       ├── DomainUtil.java
│       │   │   │           │       ├── RandomUtil.java
│       │   │   │           │       └── ValueComparator.java
│       │   │   │           └── web/
│       │   │   │               ├── atmosphere/
│       │   │   │               │   └── TatamiNotification.java
│       │   │   │               ├── rest/
│       │   │   │               │   └── dto/
│       │   │   │               │       ├── ActionStatus.java
│       │   │   │               │       ├── EmailAndUsername.java
│       │   │   │               │       ├── Preferences.java
│       │   │   │               │       ├── Reply.java
│       │   │   │               │       ├── SearchResults.java
│       │   │   │               │       ├── Tag.java
│       │   │   │               │       ├── Trend.java
│       │   │   │               │       ├── UserActionStatus.java
│       │   │   │               │       └── UserPassword.java
│       │   │   │               └── syndic/
│       │   │   │                   ├── SyndicTimelineController.java
│       │   │   │                   ├── SyndicView.java
│       │   │   │                   └── UnknownRssChannelException.java
│       │   │   └── me/
│       │   │       └── prettyprint/
│       │   │           └── hom/
│       │   │               └── CassandraPersistenceProvider.java
│       │   ├── resources/
│       │   │   ├── META-INF/
│       │   │   │   ├── elasticsearch/
│       │   │   │   │   ├── elasticsearch-embedded.yml
│       │   │   │   │   ├── index/
│       │   │   │   │   │   ├── group.json
│       │   │   │   │   │   ├── status.json
│       │   │   │   │   │   └── user.json
│       │   │   │   │   └── logging.yml
│       │   │   │   ├── spring/
│       │   │   │   │   ├── applicationContext-metrics.xml
│       │   │   │   │   └── applicationContext-security.xml
│       │   │   │   └── tatami/
│       │   │   │       ├── customization.properties
│       │   │   │       ├── mails/
│       │   │   │       │   ├── common
│       │   │   │       │   ├── dailyDigestEmail
│       │   │   │       │   ├── deactivatedUserEmail
│       │   │   │       │   ├── invitationMessageEmail
│       │   │   │       │   ├── lostPasswordEmail
│       │   │   │       │   ├── messages/
│       │   │   │       │   │   ├── messages_en.properties
│       │   │   │       │   │   └── messages_fr.properties
│       │   │   │       │   ├── passwordReinitializedEmail
│       │   │   │       │   ├── registrationEmail
│       │   │   │       │   ├── reportedStatusEmail
│       │   │   │       │   ├── userMentionEmail
│       │   │   │       │   ├── userPrivateMessageEmail
│       │   │   │       │   ├── validationEmail
│       │   │   │       │   └── weeklyDigestEmail
│       │   │   │       └── tatami.properties
│       │   │   ├── ehcache.xml
│       │   │   └── logback.xml
│       │   └── webapp/
│       │       └── app/
│       │           └── shared/
│       │               └── services/
│       │                   ├── AuthenticationService.js
│       │                   ├── GeolocService.js
│       │                   ├── GroupService.js
│       │                   ├── HomeService.js
│       │                   ├── ProfileService.js
│       │                   ├── SearchService.js
│       │                   ├── StatusService.js
│       │                   ├── TagService.js
│       │                   ├── TopPostersService.js
│       │                   ├── UserService.js
│       │                   └── UserSession.js
│       └── test/
│           ├── java/
│           │   └── fr/
│           │       └── ippon/
│           │           └── tatami/
│           │               ├── AbstractCassandraTatamiTest.java
│           │               ├── repository/
│           │               │   ├── MailDigestRepositoryTest.java
│           │               │   ├── StatusReportRepositoryTest.java
│           │               │   ├── StatusRepositoryTest.java
│           │               │   ├── TagFollowerRepositoryTest.java
│           │               │   └── UserRepositoryTest.java
│           │               ├── service/
│           │               │   ├── FriendshipServiceTest.java
│           │               │   ├── GroupServiceTest.java
│           │               │   ├── MailDigestServiceTest.java
│           │               │   ├── StatsServiceTest.java
│           │               │   ├── StatusDeletionTest.java
│           │               │   ├── StatusUpdateServiceTest.java
│           │               │   ├── TagMembershipServiceTest.java
│           │               │   ├── TimelineServiceTest.java
│           │               │   ├── TrendServiceTest.java
│           │               │   ├── UserServiceTest.java
│           │               │   └── elasticsearch/
│           │               │       └── ElasticsearchSearchServiceTest.java
│           │               ├── test/
│           │               │   ├── MockUtils.java
│           │               │   └── application/
│           │               │       ├── ApplicationTestConfiguration.java
│           │               │       └── WebApplicationTestConfiguration.java
│           │               └── web/
│           │                   └── syndic/
│           │                       └── SyndicTimelineControllerTest.java
│           ├── jmeter/
│           │   ├── tatami-create-users.jmx
│           │   └── tatami-stress-test.jmx
│           └── resources/
│               ├── dataset/
│               │   └── dataset.json
│               ├── logback.xml
│               └── tatami/
│                   └── tatami-test.properties
├── src/
│   ├── integration/
│   │   ├── java/
│   │   │   ├── fr/
│   │   │   │   └── ippon/
│   │   │   │       └── tatami/
│   │   │   │           ├── test/
│   │   │   │           │   └── support/
│   │   │   │           │       ├── LdapTestServer.java
│   │   │   │           │       └── LdapTestServerJunitLauncher.java
│   │   │   │           └── uitest/
│   │   │   │               ├── AuthenticationSpec.groovy
│   │   │   │               ├── NewRegistrationSpec.groovy
│   │   │   │               └── support/
│   │   │   │                   ├── AccountUtils.groovy
│   │   │   │                   ├── CassandraAccessUtils.groovy
│   │   │   │                   ├── RegistrationUtils.groovy
│   │   │   │                   └── TatamiBaseGebSpec.groovy
│   │   │   └── pages/
│   │   │       ├── EmailVerifiedPage.groovy
│   │   │       ├── HomePage.groovy
│   │   │       ├── LoginPage.groovy
│   │   │       ├── TatamiBasePage.groovy
│   │   │       └── google/
│   │   │           ├── GoogleAuthenticationPage.groovy
│   │   │           └── GoogleOpenIdPage.groovy
│   │   └── resources/
│   │       ├── GebConfig.groovy
│   │       └── fr/
│   │           └── ippon/
│   │               └── tatami/
│   │                   └── test/
│   │                       └── support/
│   │                           └── ipponTestLdapExport.ldif
│   └── main/
│       └── cql/
│           ├── install.cql
│           └── upgrade/
│               ├── upgrade_from_1.0.27_to_2.0.0.cql
│               ├── upgrade_from_2.0.0_to_2.1.0.cql
│               ├── upgrade_from_2.1.3_to_2.2.0.cql
│               └── upgrade_from_3.0.26_to_3.0.27.cql
├── tatamibot/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── fr/
│       │   │       └── ippon/
│       │   │           └── tatami/
│       │   │               ├── bot/
│       │   │               │   ├── Tatamibot.java
│       │   │               │   ├── config/
│       │   │               │   │   └── TatamibotConfiguration.java
│       │   │               │   ├── processor/
│       │   │               │   │   ├── LastUpdateDateTatamibotConfigurationUpdater.java
│       │   │               │   │   └── TatamiStatusProcessor.java
│       │   │               │   └── route/
│       │   │               │       ├── CommonRouteBuilder.java
│       │   │               │       ├── GitHubRouteBuilder.java
│       │   │               │       ├── RssRouteBuilder.java
│       │   │               │       ├── SourceRouteBuilderBase.java
│       │   │               │       └── TwitterRouteBuilder.java
│       │   │               ├── repository/
│       │   │               │   ├── TatamibotConfigurationRepository.java
│       │   │               │   └── cassandra/
│       │   │               │       └── CassandraTatamibotConfigurationRepository.java
│       │   │               └── web/
│       │   │                   └── bot/
│       │   │                       └── TatamibotController.java
│       │   └── resources/
│       │       └── META-INF/
│       │           └── spring/
│       │               └── applicationContext-tatamibot.xml
│       └── test/
│           ├── java/
│           │   └── fr/
│           │       └── ippon/
│           │           └── tatami/
│           │               ├── bot/
│           │               │   ├── TatamibotTest.java
│           │               │   └── route/
│           │               │       ├── CommonRouteBuilderTest.java
│           │               │       ├── RssRouteBuilderCamelTest.java
│           │               │       ├── RssRouteBuilderUnitTest.java
│           │               │       ├── SourceRouteBuilderBaseCamelTest.java
│           │               │       └── TwitterRouteBuilderCamelTest.java
│           │               └── test/
│           │                   └── MockUtils.java
│           └── resources/
│               └── fr/
│                   └── ippon/
│                       └── tatami/
│                           └── bot/
│                               └── route/
│                                   └── rss.xml
└── web/
    ├── gruntfile.js
    ├── karma.ci.conf.js
    ├── karma.conf.js
    ├── package.json
    ├── pom.xml
    └── src/
        ├── main/
        │   ├── java/
        │   │   └── fr/
        │   │       └── ippon/
        │   │           └── tatami/
        │   │               └── web/
        │   │                   ├── atmosphere/
        │   │                   │   └── RealtimeService.java
        │   │                   ├── controller/
        │   │                   │   ├── ErrorController.java
        │   │                   │   ├── HomeController.java
        │   │                   │   └── Pac4JSecurityCheckController.java
        │   │                   ├── fileupload/
        │   │                   │   ├── FileController.java
        │   │                   │   ├── Message.java
        │   │                   │   ├── StatusResponse.java
        │   │                   │   └── UploadedFile.java
        │   │                   ├── filter/
        │   │                   │   ├── IeRefreshWrapper.java
        │   │                   │   └── TatamiGzipFilter.java
        │   │                   ├── init/
        │   │                   │   └── WebConfigurer.java
        │   │                   └── rest/
        │   │                       ├── AccountController.java
        │   │                       ├── AttachmentController.java
        │   │                       ├── BlockController.java
        │   │                       ├── CompanyWallController.java
        │   │                       ├── FavoritesController.java
        │   │                       ├── FriendshipController.java
        │   │                       ├── GroupController.java
        │   │                       ├── MentionsController.java
        │   │                       ├── SearchController.java
        │   │                       ├── StatsController.java
        │   │                       ├── TagController.java
        │   │                       ├── TimelineController.java
        │   │                       ├── TrendController.java
        │   │                       ├── UserController.java
        │   │                       └── UserXAuthController.java
        │   └── webapp/
        │       ├── .bowerrc
        │       ├── WEB-INF/
        │       │   ├── messages/
        │       │   │   ├── messages_en.properties
        │       │   │   └── messages_fr.properties
        │       │   ├── pages/
        │       │   │   ├── errors/
        │       │   │   │   ├── 404.jsp
        │       │   │   │   ├── 500.jsp
        │       │   │   │   └── file_not_found.jsp
        │       │   │   ├── home.jsp
        │       │   │   ├── includes/
        │       │   │   │   ├── footer.jsp
        │       │   │   │   ├── header.jsp
        │       │   │   │   ├── help-home.jsp
        │       │   │   │   ├── navigation-admin.jsp
        │       │   │   │   ├── template-search-engine.jsp
        │       │   │   │   ├── templates-admin.jsp
        │       │   │   │   ├── templates.jsp
        │       │   │   │   ├── topavatar.jsp
        │       │   │   │   └── topmenu.jsp
        │       │   │   └── login.jsp
        │       │   └── web.xml
        │       ├── app/
        │       │   ├── TatamiApp.js
        │       │   ├── components/
        │       │   │   ├── about/
        │       │   │   │   ├── AboutModule.js
        │       │   │   │   ├── AboutView.html
        │       │   │   │   ├── license/
        │       │   │   │   │   ├── LicenseController.js
        │       │   │   │   │   └── LicenseView.html
        │       │   │   │   ├── presentation/
        │       │   │   │   │   └── PresentationView.html
        │       │   │   │   └── tos/
        │       │   │   │       └── ToSView.html
        │       │   │   ├── account/
        │       │   │   │   ├── AccountController.js
        │       │   │   │   ├── AccountModule.js
        │       │   │   │   ├── AccountView.html
        │       │   │   │   ├── FormController.js
        │       │   │   │   ├── FormView.html
        │       │   │   │   ├── files/
        │       │   │   │   │   ├── FilesController.js
        │       │   │   │   │   ├── FilesModule.js
        │       │   │   │   │   ├── FilesService.js
        │       │   │   │   │   └── FilesView.html
        │       │   │   │   ├── groups/
        │       │   │   │   │   ├── GroupsController.js
        │       │   │   │   │   ├── GroupsModule.js
        │       │   │   │   │   ├── GroupsView.html
        │       │   │   │   │   ├── creation/
        │       │   │   │   │   │   ├── GroupsCreateController.js
        │       │   │   │   │   │   └── GroupsCreateView.html
        │       │   │   │   │   ├── list/
        │       │   │   │   │   │   ├── GroupListController.js
        │       │   │   │   │   │   └── GroupsListView.html
        │       │   │   │   │   └── manage/
        │       │   │   │   │       ├── GroupsManageController.js
        │       │   │   │   │       └── GroupsManageView.html
        │       │   │   │   ├── password/
        │       │   │   │   │   ├── PasswordController.js
        │       │   │   │   │   ├── PasswordModule.js
        │       │   │   │   │   ├── PasswordService.js
        │       │   │   │   │   └── PasswordView.html
        │       │   │   │   ├── preferences/
        │       │   │   │   │   ├── PreferencesController.js
        │       │   │   │   │   ├── PreferencesModule.js
        │       │   │   │   │   ├── PreferencesService.js
        │       │   │   │   │   └── PreferencesView.html
        │       │   │   │   ├── profile/
        │       │   │   │   │   ├── ProfileController.js
        │       │   │   │   │   ├── ProfileModule.js
        │       │   │   │   │   └── ProfileView.html
        │       │   │   │   ├── tags/
        │       │   │   │   │   ├── TagsController.js
        │       │   │   │   │   ├── TagsModule.js
        │       │   │   │   │   └── TagsView.html
        │       │   │   │   ├── topPosters/
        │       │   │   │   │   ├── TopPostersController.js
        │       │   │   │   │   ├── TopPostersModule.js
        │       │   │   │   │   └── TopPostersView.html
        │       │   │   │   └── users/
        │       │   │   │       ├── UsersController.js
        │       │   │   │       ├── UsersModule.js
        │       │   │   │       ├── UsersView.html
        │       │   │   │       └── directives/
        │       │   │   │           ├── UserAccountController.js
        │       │   │   │           ├── UserAccountDirective.js
        │       │   │   │           └── UserAccountView.html
        │       │   │   ├── admin/
        │       │   │   │   ├── AdminController.js
        │       │   │   │   ├── AdminModule.js
        │       │   │   │   ├── AdminService.js
        │       │   │   │   └── AdminView.html
        │       │   │   ├── home/
        │       │   │   │   ├── HomeModule.js
        │       │   │   │   ├── HomeView.html
        │       │   │   │   ├── group/
        │       │   │   │   │   ├── GroupHeaderController.js
        │       │   │   │   │   └── GroupHeaderView.html
        │       │   │   │   ├── profile/
        │       │   │   │   │   ├── ProfileHeaderController.js
        │       │   │   │   │   └── ProfileHeaderView.html
        │       │   │   │   ├── search/
        │       │   │   │   │   ├── SearchHeaderController.js
        │       │   │   │   │   └── SearchHeaderView.html
        │       │   │   │   ├── status/
        │       │   │   │   │   ├── StatusController.js
        │       │   │   │   │   └── StatusView.html
        │       │   │   │   ├── tag/
        │       │   │   │   │   ├── TagHeaderController.js
        │       │   │   │   │   └── TagHeaderView.html
        │       │   │   │   ├── timeline/
        │       │   │   │   │   └── TimelineHeaderView.html
        │       │   │   │   └── welcome/
        │       │   │   │       ├── WelcomeController.js
        │       │   │   │       └── WelcomeView.html
        │       │   │   └── login/
        │       │   │       ├── LoginController.js
        │       │   │       ├── LoginModule.js
        │       │   │       ├── LoginView.html
        │       │   │       ├── RegistrationService.js
        │       │   │       ├── email/
        │       │   │       │   ├── EmailRegistration.html
        │       │   │       │   └── EmailRegistrationController.js
        │       │   │       ├── google/
        │       │   │       │   ├── GoogleLoginController.js
        │       │   │       │   └── GoogleLoginView.html
        │       │   │       ├── manual/
        │       │   │       │   ├── ManualLoginController.js
        │       │   │       │   └── ManualLoginView.html
        │       │   │       ├── recoverPassword/
        │       │   │       │   ├── RecoverPasswordController.js
        │       │   │       │   └── RecoverPasswordView.html
        │       │   │       └── register/
        │       │   │           ├── RegisterController.js
        │       │   │           └── RegisterView.html
        │       │   └── shared/
        │       │       ├── configs/
        │       │       │   ├── MarkedConfig.js
        │       │       │   ├── MomentConfig.js
        │       │       │   └── TranslateConfig.js
        │       │       ├── error/
        │       │       │   ├── 404View.html
        │       │       │   └── 500View.html
        │       │       ├── filters/
        │       │       │   ├── EmoticonFilter.js
        │       │       │   ├── MarkdownFilter.js
        │       │       │   └── PlaceholderFilter.js
        │       │       ├── footer/
        │       │       │   ├── FooterController.js
        │       │       │   ├── FooterModule.js
        │       │       │   └── FooterView.html
        │       │       ├── lists/
        │       │       │   ├── status/
        │       │       │   │   ├── withContext/
        │       │       │   │   │   ├── StatusListContextController.js
        │       │       │   │   │   └── StatusListContextView.html
        │       │       │   │   └── withoutContext/
        │       │       │   │       ├── StatusListController.js
        │       │       │   │       └── StatusListView.html
        │       │       │   └── user/
        │       │       │       ├── UserListController.js
        │       │       │       └── UserListView.html
        │       │       ├── services/
        │       │       │   ├── AuthenticationService.js
        │       │       │   ├── GeolocService.js
        │       │       │   ├── GroupService.js
        │       │       │   ├── HomeService.js
        │       │       │   ├── ProfileService.js
        │       │       │   ├── SearchService.js
        │       │       │   ├── StatusService.js
        │       │       │   ├── TagService.js
        │       │       │   ├── TopPostersService.js
        │       │       │   ├── UserService.js
        │       │       │   └── UserSession.js
        │       │       ├── sidebars/
        │       │       │   ├── home/
        │       │       │   │   ├── HomeSidebarController.js
        │       │       │   │   ├── HomeSidebarModule.js
        │       │       │   │   └── HomeSidebarView.html
        │       │       │   └── profile/
        │       │       │       ├── ProfileSidebarController.js
        │       │       │       ├── ProfileSidebarModule.js
        │       │       │       └── ProfileSidebarView.html
        │       │       └── topMenu/
        │       │           ├── SearchView.html
        │       │           ├── TopMenuController.js
        │       │           ├── TopMenuModule.js
        │       │           ├── TopMenuView.html
        │       │           └── post/
        │       │               ├── DropdownTagTemplate.html
        │       │               ├── DropdownUserTemplate.html
        │       │               ├── PostController.js
        │       │               ├── PostModule.js
        │       │               └── PostView.html
        │       ├── assets/
        │       │   ├── bower_components/
        │       │   │   ├── angular/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-csp.css
        │       │   │   │   ├── angular.min.js.gzip
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-animate/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-bootstrap/
        │       │   │   │   ├── .bower.json
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-bootstrap-tour/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── app/
        │       │   │   │   │   ├── angular-bootstrap-tour.js
        │       │   │   │   │   ├── tour_config_provider.js
        │       │   │   │   │   ├── tour_controller.js
        │       │   │   │   │   ├── tour_directive.js
        │       │   │   │   │   ├── tour_helpers.js
        │       │   │   │   │   └── tour_step_directive.js
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── demo/
        │       │   │   │   │   └── angular-bootstrap-tour.js
        │       │   │   │   ├── dist/
        │       │   │   │   │   └── angular-bootstrap-tour.js
        │       │   │   │   ├── gruntfile.js
        │       │   │   │   ├── karma.conf.js
        │       │   │   │   └── test/
        │       │   │   │       └── spec/
        │       │   │   │           └── angular-bootstrap-tour.spec.js
        │       │   │   ├── angular-cookies/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-mocks/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-mocks.js
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── ngAnimateMock.js
        │       │   │   │   ├── ngMock.js
        │       │   │   │   ├── ngMockE2E.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-moment/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── .editorconfig
        │       │   │   │   ├── .gitignore
        │       │   │   │   ├── .jshintrc
        │       │   │   │   ├── .npmignore
        │       │   │   │   ├── .travis.yml
        │       │   │   │   ├── CHANGELOG.md
        │       │   │   │   ├── CONTRIBUTING.md
        │       │   │   │   ├── Gruntfile.js
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-moment.nuspec
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── karma.conf.js
        │       │   │   │   ├── package.json
        │       │   │   │   └── tests.js
        │       │   │   ├── angular-resource/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-route/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-route.js
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-sanitize/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-touch/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-translate/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-translate-storage-cookie/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-ui-router/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── CHANGELOG.md
        │       │   │   │   ├── CONTRIBUTING.md
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── api/
        │       │   │   │   │   └── angular-ui-router.d.ts
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── release/
        │       │   │   │   │   └── angular-ui-router.js
        │       │   │   │   └── src/
        │       │   │   │       ├── common.js
        │       │   │   │       ├── resolve.js
        │       │   │   │       ├── state.js
        │       │   │   │       ├── stateDirectives.js
        │       │   │   │       ├── stateFilters.js
        │       │   │   │       ├── templateFactory.js
        │       │   │   │       ├── urlMatcherFactory.js
        │       │   │   │       ├── urlRouter.js
        │       │   │   │       ├── view.js
        │       │   │   │       ├── viewDirective.js
        │       │   │   │       └── viewScroll.js
        │       │   │   ├── bootstrap/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── DOCS-LICENSE
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── LICENSE-MIT
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── dist/
        │       │   │   │   │   ├── css/
        │       │   │   │   │   │   ├── bootstrap-theme.css
        │       │   │   │   │   │   └── bootstrap.css
        │       │   │   │   │   └── js/
        │       │   │   │   │       └── bootstrap.js
        │       │   │   │   ├── js/
        │       │   │   │   │   ├── affix.js
        │       │   │   │   │   ├── alert.js
        │       │   │   │   │   ├── button.js
        │       │   │   │   │   ├── carousel.js
        │       │   │   │   │   ├── collapse.js
        │       │   │   │   │   ├── dropdown.js
        │       │   │   │   │   ├── modal.js
        │       │   │   │   │   ├── popover.js
        │       │   │   │   │   ├── scrollspy.js
        │       │   │   │   │   ├── tab.js
        │       │   │   │   │   ├── tooltip.js
        │       │   │   │   │   └── transition.js
        │       │   │   │   └── less/
        │       │   │   │       ├── alerts.less
        │       │   │   │       ├── badges.less
        │       │   │   │       ├── bootstrap.less
        │       │   │   │       ├── breadcrumbs.less
        │       │   │   │       ├── button-groups.less
        │       │   │   │       ├── buttons.less
        │       │   │   │       ├── carousel.less
        │       │   │   │       ├── close.less
        │       │   │   │       ├── code.less
        │       │   │   │       ├── component-animations.less
        │       │   │   │       ├── dropdowns.less
        │       │   │   │       ├── forms.less
        │       │   │   │       ├── glyphicons.less
        │       │   │   │       ├── grid.less
        │       │   │   │       ├── input-groups.less
        │       │   │   │       ├── jumbotron.less
        │       │   │   │       ├── labels.less
        │       │   │   │       ├── list-group.less
        │       │   │   │       ├── media.less
        │       │   │   │       ├── mixins.less
        │       │   │   │       ├── modals.less
        │       │   │   │       ├── navbar.less
        │       │   │   │       ├── navs.less
        │       │   │   │       ├── normalize.less
        │       │   │   │       ├── pager.less
        │       │   │   │       ├── pagination.less
        │       │   │   │       ├── panels.less
        │       │   │   │       ├── popovers.less
        │       │   │   │       ├── print.less
        │       │   │   │       ├── progress-bars.less
        │       │   │   │       ├── responsive-utilities.less
        │       │   │   │       ├── scaffolding.less
        │       │   │   │       ├── tables.less
        │       │   │   │       ├── theme.less
        │       │   │   │       ├── thumbnails.less
        │       │   │   │       ├── tooltip.less
        │       │   │   │       ├── type.less
        │       │   │   │       ├── utilities.less
        │       │   │   │       ├── variables.less
        │       │   │   │       └── wells.less
        │       │   │   ├── jquery/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── MIT-LICENSE.txt
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── dist/
        │       │   │   │   │   └── jquery.js
        │       │   │   │   └── src/
        │       │   │   │       ├── ajax/
        │       │   │   │       │   ├── jsonp.js
        │       │   │   │       │   ├── load.js
        │       │   │   │       │   ├── parseJSON.js
        │       │   │   │       │   ├── parseXML.js
        │       │   │   │       │   ├── script.js
        │       │   │   │       │   ├── var/
        │       │   │   │       │   │   ├── nonce.js
        │       │   │   │       │   │   └── rquery.js
        │       │   │   │       │   └── xhr.js
        │       │   │   │       ├── ajax.js
        │       │   │   │       ├── attributes/
        │       │   │   │       │   ├── attr.js
        │       │   │   │       │   ├── classes.js
        │       │   │   │       │   ├── prop.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   └── val.js
        │       │   │   │       ├── attributes.js
        │       │   │   │       ├── callbacks.js
        │       │   │   │       ├── core/
        │       │   │   │       │   ├── access.js
        │       │   │   │       │   ├── init.js
        │       │   │   │       │   ├── parseHTML.js
        │       │   │   │       │   ├── ready.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       └── rsingleTag.js
        │       │   │   │       ├── core.js
        │       │   │   │       ├── css/
        │       │   │   │       │   ├── addGetHookIf.js
        │       │   │   │       │   ├── curCSS.js
        │       │   │   │       │   ├── defaultDisplay.js
        │       │   │   │       │   ├── hiddenVisibleSelectors.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   ├── swap.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       ├── cssExpand.js
        │       │   │   │       │       ├── isHidden.js
        │       │   │   │       │       ├── rmargin.js
        │       │   │   │       │       └── rnumnonpx.js
        │       │   │   │       ├── css.js
        │       │   │   │       ├── data.js
        │       │   │   │       ├── deferred.js
        │       │   │   │       ├── deprecated.js
        │       │   │   │       ├── dimensions.js
        │       │   │   │       ├── effects/
        │       │   │   │       │   ├── Tween.js
        │       │   │   │       │   ├── animatedSelector.js
        │       │   │   │       │   └── support.js
        │       │   │   │       ├── effects.js
        │       │   │   │       ├── event/
        │       │   │   │       │   ├── alias.js
        │       │   │   │       │   └── support.js
        │       │   │   │       ├── event.js
        │       │   │   │       ├── exports/
        │       │   │   │       │   ├── amd.js
        │       │   │   │       │   └── global.js
        │       │   │   │       ├── intro.js
        │       │   │   │       ├── jquery.js
        │       │   │   │       ├── manipulation/
        │       │   │   │       │   ├── _evalUrl.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       └── rcheckableType.js
        │       │   │   │       ├── manipulation.js
        │       │   │   │       ├── offset.js
        │       │   │   │       ├── outro.js
        │       │   │   │       ├── queue/
        │       │   │   │       │   └── delay.js
        │       │   │   │       ├── queue.js
        │       │   │   │       ├── selector-sizzle.js
        │       │   │   │       ├── selector.js
        │       │   │   │       ├── serialize.js
        │       │   │   │       ├── sizzle/
        │       │   │   │       │   └── dist/
        │       │   │   │       │       └── sizzle.js
        │       │   │   │       ├── support.js
        │       │   │   │       ├── traversing/
        │       │   │   │       │   ├── findFilter.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       └── rneedsContext.js
        │       │   │   │       ├── traversing.js
        │       │   │   │       ├── var/
        │       │   │   │       │   ├── class2type.js
        │       │   │   │       │   ├── concat.js
        │       │   │   │       │   ├── deletedIds.js
        │       │   │   │       │   ├── hasOwn.js
        │       │   │   │       │   ├── indexOf.js
        │       │   │   │       │   ├── pnum.js
        │       │   │   │       │   ├── push.js
        │       │   │   │       │   ├── rnotwhite.js
        │       │   │   │       │   ├── slice.js
        │       │   │   │       │   ├── strundefined.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   └── toString.js
        │       │   │   │       └── wrap.js
        │       │   │   ├── ment.io/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── LICENSE-MIT
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── dist/
        │       │   │   │   │   ├── mentio.js
        │       │   │   │   │   └── templates.js
        │       │   │   │   ├── gulpfile.js
        │       │   │   │   ├── karma.conf.js
        │       │   │   │   ├── ment.io/
        │       │   │   │   │   ├── index.html
        │       │   │   │   │   ├── peopledata.json
        │       │   │   │   │   ├── productdata.json
        │       │   │   │   │   ├── scripts.js
        │       │   │   │   │   ├── simplepeopledata.json
        │       │   │   │   │   └── styles.css
        │       │   │   │   ├── package.json
        │       │   │   │   └── src/
        │       │   │   │       ├── mentio-menu.tpl.html
        │       │   │   │       ├── mentio.directive.js
        │       │   │   │       └── mentio.service.js
        │       │   │   ├── moment/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── CHANGELOG.md
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── Moment.js.nuspec
        │       │   │   │   ├── README.md
        │       │   │   │   ├── benchmarks/
        │       │   │   │   │   └── clone.js
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── locale/
        │       │   │   │   │   ├── af.js
        │       │   │   │   │   ├── ar-ma.js
        │       │   │   │   │   ├── ar-sa.js
        │       │   │   │   │   ├── ar-tn.js
        │       │   │   │   │   ├── ar.js
        │       │   │   │   │   ├── az.js
        │       │   │   │   │   ├── be.js
        │       │   │   │   │   ├── bg.js
        │       │   │   │   │   ├── bn.js
        │       │   │   │   │   ├── bo.js
        │       │   │   │   │   ├── br.js
        │       │   │   │   │   ├── bs.js
        │       │   │   │   │   ├── ca.js
        │       │   │   │   │   ├── cs.js
        │       │   │   │   │   ├── cv.js
        │       │   │   │   │   ├── cy.js
        │       │   │   │   │   ├── da.js
        │       │   │   │   │   ├── de-at.js
        │       │   │   │   │   ├── de.js
        │       │   │   │   │   ├── el.js
        │       │   │   │   │   ├── en-au.js
        │       │   │   │   │   ├── en-ca.js
        │       │   │   │   │   ├── en-gb.js
        │       │   │   │   │   ├── eo.js
        │       │   │   │   │   ├── es.js
        │       │   │   │   │   ├── et.js
        │       │   │   │   │   ├── eu.js
        │       │   │   │   │   ├── fa.js
        │       │   │   │   │   ├── fi.js
        │       │   │   │   │   ├── fo.js
        │       │   │   │   │   ├── fr-ca.js
        │       │   │   │   │   ├── fr.js
        │       │   │   │   │   ├── fy.js
        │       │   │   │   │   ├── gl.js
        │       │   │   │   │   ├── he.js
        │       │   │   │   │   ├── hi.js
        │       │   │   │   │   ├── hr.js
        │       │   │   │   │   ├── hu.js
        │       │   │   │   │   ├── hy-am.js
        │       │   │   │   │   ├── id.js
        │       │   │   │   │   ├── is.js
        │       │   │   │   │   ├── it.js
        │       │   │   │   │   ├── ja.js
        │       │   │   │   │   ├── ka.js
        │       │   │   │   │   ├── km.js
        │       │   │   │   │   ├── ko.js
        │       │   │   │   │   ├── lb.js
        │       │   │   │   │   ├── lt.js
        │       │   │   │   │   ├── lv.js
        │       │   │   │   │   ├── mk.js
        │       │   │   │   │   ├── ml.js
        │       │   │   │   │   ├── mr.js
        │       │   │   │   │   ├── ms-my.js
        │       │   │   │   │   ├── my.js
        │       │   │   │   │   ├── nb.js
        │       │   │   │   │   ├── ne.js
        │       │   │   │   │   ├── nl.js
        │       │   │   │   │   ├── nn.js
        │       │   │   │   │   ├── pl.js
        │       │   │   │   │   ├── pt-br.js
        │       │   │   │   │   ├── pt.js
        │       │   │   │   │   ├── ro.js
        │       │   │   │   │   ├── ru.js
        │       │   │   │   │   ├── sk.js
        │       │   │   │   │   ├── sl.js
        │       │   │   │   │   ├── sq.js
        │       │   │   │   │   ├── sr-cyrl.js
        │       │   │   │   │   ├── sr.js
        │       │   │   │   │   ├── sv.js
        │       │   │   │   │   ├── ta.js
        │       │   │   │   │   ├── th.js
        │       │   │   │   │   ├── tl-ph.js
        │       │   │   │   │   ├── tr.js
        │       │   │   │   │   ├── tzm-latn.js
        │       │   │   │   │   ├── tzm.js
        │       │   │   │   │   ├── uk.js
        │       │   │   │   │   ├── uz.js
        │       │   │   │   │   ├── vi.js
        │       │   │   │   │   ├── zh-cn.js
        │       │   │   │   │   └── zh-tw.js
        │       │   │   │   ├── meteor/
        │       │   │   │   │   ├── README.md
        │       │   │   │   │   ├── export.js
        │       │   │   │   │   └── test.js
        │       │   │   │   ├── min/
        │       │   │   │   │   ├── locales.js
        │       │   │   │   │   ├── moment-with-locales.js
        │       │   │   │   │   └── tests.js
        │       │   │   │   ├── moment.js
        │       │   │   │   ├── scripts/
        │       │   │   │   │   └── npm_prepublish.sh
        │       │   │   │   ├── src/
        │       │   │   │   │   ├── lib/
        │       │   │   │   │   │   ├── create/
        │       │   │   │   │   │   │   ├── check-overflow.js
        │       │   │   │   │   │   │   ├── date-from-array.js
        │       │   │   │   │   │   │   ├── default-parsing-flags.js
        │       │   │   │   │   │   │   ├── from-anything.js
        │       │   │   │   │   │   │   ├── from-array.js
        │       │   │   │   │   │   │   ├── from-object.js
        │       │   │   │   │   │   │   ├── from-string-and-array.js
        │       │   │   │   │   │   │   ├── from-string-and-format.js
        │       │   │   │   │   │   │   ├── from-string.js
        │       │   │   │   │   │   │   ├── local.js
        │       │   │   │   │   │   │   ├── utc.js
        │       │   │   │   │   │   │   └── valid.js
        │       │   │   │   │   │   ├── duration/
        │       │   │   │   │   │   │   ├── abs.js
        │       │   │   │   │   │   │   ├── add-subtract.js
        │       │   │   │   │   │   │   ├── as.js
        │       │   │   │   │   │   │   ├── bubble.js
        │       │   │   │   │   │   │   ├── constructor.js
        │       │   │   │   │   │   │   ├── create.js
        │       │   │   │   │   │   │   ├── duration.js
        │       │   │   │   │   │   │   ├── get.js
        │       │   │   │   │   │   │   ├── humanize.js
        │       │   │   │   │   │   │   ├── iso-string.js
        │       │   │   │   │   │   │   └── prototype.js
        │       │   │   │   │   │   ├── format/
        │       │   │   │   │   │   │   └── format.js
        │       │   │   │   │   │   ├── locale/
        │       │   │   │   │   │   │   ├── calendar.js
        │       │   │   │   │   │   │   ├── constructor.js
        │       │   │   │   │   │   │   ├── en.js
        │       │   │   │   │   │   │   ├── formats.js
        │       │   │   │   │   │   │   ├── invalid.js
        │       │   │   │   │   │   │   ├── lists.js
        │       │   │   │   │   │   │   ├── locale.js
        │       │   │   │   │   │   │   ├── locales.js
        │       │   │   │   │   │   │   ├── ordinal.js
        │       │   │   │   │   │   │   ├── pre-post-format.js
        │       │   │   │   │   │   │   ├── prototype.js
        │       │   │   │   │   │   │   ├── relative.js
        │       │   │   │   │   │   │   └── set.js
        │       │   │   │   │   │   ├── moment/
        │       │   │   │   │   │   │   ├── add-subtract.js
        │       │   │   │   │   │   │   ├── calendar.js
        │       │   │   │   │   │   │   ├── clone.js
        │       │   │   │   │   │   │   ├── compare.js
        │       │   │   │   │   │   │   ├── constructor.js
        │       │   │   │   │   │   │   ├── diff.js
        │       │   │   │   │   │   │   ├── format.js
        │       │   │   │   │   │   │   ├── from.js
        │       │   │   │   │   │   │   ├── get-set.js
        │       │   │   │   │   │   │   ├── locale.js
        │       │   │   │   │   │   │   ├── min-max.js
        │       │   │   │   │   │   │   ├── moment.js
        │       │   │   │   │   │   │   ├── prototype.js
        │       │   │   │   │   │   │   ├── start-end-of.js
        │       │   │   │   │   │   │   ├── to-type.js
        │       │   │   │   │   │   │   └── valid.js
        │       │   │   │   │   │   ├── parse/
        │       │   │   │   │   │   │   ├── regex.js
        │       │   │   │   │   │   │   └── token.js
        │       │   │   │   │   │   ├── units/
        │       │   │   │   │   │   │   ├── aliases.js
        │       │   │   │   │   │   │   ├── constants.js
        │       │   │   │   │   │   │   ├── day-of-month.js
        │       │   │   │   │   │   │   ├── day-of-week.js
        │       │   │   │   │   │   │   ├── day-of-year.js
        │       │   │   │   │   │   │   ├── hour.js
        │       │   │   │   │   │   │   ├── millisecond.js
        │       │   │   │   │   │   │   ├── minute.js
        │       │   │   │   │   │   │   ├── month.js
        │       │   │   │   │   │   │   ├── offset.js
        │       │   │   │   │   │   │   ├── quarter.js
        │       │   │   │   │   │   │   ├── second.js
        │       │   │   │   │   │   │   ├── timestamp.js
        │       │   │   │   │   │   │   ├── timezone.js
        │       │   │   │   │   │   │   ├── units.js
        │       │   │   │   │   │   │   ├── week-year.js
        │       │   │   │   │   │   │   ├── week.js
        │       │   │   │   │   │   │   └── year.js
        │       │   │   │   │   │   └── utils/
        │       │   │   │   │   │       ├── abs-floor.js
        │       │   │   │   │   │       ├── compare-arrays.js
        │       │   │   │   │   │       ├── defaults.js
        │       │   │   │   │   │       ├── deprecate.js
        │       │   │   │   │   │       ├── extend.js
        │       │   │   │   │   │       ├── has-own-prop.js
        │       │   │   │   │   │       ├── hooks.js
        │       │   │   │   │   │       ├── is-array.js
        │       │   │   │   │   │       ├── is-date.js
        │       │   │   │   │   │       ├── map.js
        │       │   │   │   │   │       ├── to-int.js
        │       │   │   │   │   │       └── zero-fill.js
        │       │   │   │   │   ├── locale/
        │       │   │   │   │   │   ├── af.js
        │       │   │   │   │   │   ├── ar-ma.js
        │       │   │   │   │   │   ├── ar-sa.js
        │       │   │   │   │   │   ├── ar-tn.js
        │       │   │   │   │   │   ├── ar.js
        │       │   │   │   │   │   ├── az.js
        │       │   │   │   │   │   ├── be.js
        │       │   │   │   │   │   ├── bg.js
        │       │   │   │   │   │   ├── bn.js
        │       │   │   │   │   │   ├── bo.js
        │       │   │   │   │   │   ├── br.js
        │       │   │   │   │   │   ├── bs.js
        │       │   │   │   │   │   ├── ca.js
        │       │   │   │   │   │   ├── cs.js
        │       │   │   │   │   │   ├── cv.js
        │       │   │   │   │   │   ├── cy.js
        │       │   │   │   │   │   ├── da.js
        │       │   │   │   │   │   ├── de-at.js
        │       │   │   │   │   │   ├── de.js
        │       │   │   │   │   │   ├── el.js
        │       │   │   │   │   │   ├── en-au.js
        │       │   │   │   │   │   ├── en-ca.js
        │       │   │   │   │   │   ├── en-gb.js
        │       │   │   │   │   │   ├── eo.js
        │       │   │   │   │   │   ├── es.js
        │       │   │   │   │   │   ├── et.js
        │       │   │   │   │   │   ├── eu.js
        │       │   │   │   │   │   ├── fa.js
        │       │   │   │   │   │   ├── fi.js
        │       │   │   │   │   │   ├── fo.js
        │       │   │   │   │   │   ├── fr-ca.js
        │       │   │   │   │   │   ├── fr.js
        │       │   │   │   │   │   ├── fy.js
        │       │   │   │   │   │   ├── gl.js
        │       │   │   │   │   │   ├── he.js
        │       │   │   │   │   │   ├── hi.js
        │       │   │   │   │   │   ├── hr.js
        │       │   │   │   │   │   ├── hu.js
        │       │   │   │   │   │   ├── hy-am.js
        │       │   │   │   │   │   ├── id.js
        │       │   │   │   │   │   ├── is.js
        │       │   │   │   │   │   ├── it.js
        │       │   │   │   │   │   ├── ja.js
        │       │   │   │   │   │   ├── ka.js
        │       │   │   │   │   │   ├── km.js
        │       │   │   │   │   │   ├── ko.js
        │       │   │   │   │   │   ├── lb.js
        │       │   │   │   │   │   ├── lt.js
        │       │   │   │   │   │   ├── lv.js
        │       │   │   │   │   │   ├── mk.js
        │       │   │   │   │   │   ├── ml.js
        │       │   │   │   │   │   ├── mr.js
        │       │   │   │   │   │   ├── ms-my.js
        │       │   │   │   │   │   ├── my.js
        │       │   │   │   │   │   ├── nb.js
        │       │   │   │   │   │   ├── ne.js
        │       │   │   │   │   │   ├── nl.js
        │       │   │   │   │   │   ├── nn.js
        │       │   │   │   │   │   ├── pl.js
        │       │   │   │   │   │   ├── pt-br.js
        │       │   │   │   │   │   ├── pt.js
        │       │   │   │   │   │   ├── ro.js
        │       │   │   │   │   │   ├── ru.js
        │       │   │   │   │   │   ├── sk.js
        │       │   │   │   │   │   ├── sl.js
        │       │   │   │   │   │   ├── sq.js
        │       │   │   │   │   │   ├── sr-cyrl.js
        │       │   │   │   │   │   ├── sr.js
        │       │   │   │   │   │   ├── sv.js
        │       │   │   │   │   │   ├── ta.js
        │       │   │   │   │   │   ├── th.js
        │       │   │   │   │   │   ├── tl-ph.js
        │       │   │   │   │   │   ├── tr.js
        │       │   │   │   │   │   ├── tzm-latn.js
        │       │   │   │   │   │   ├── tzm.js
        │       │   │   │   │   │   ├── uk.js
        │       │   │   │   │   │   ├── uz.js
        │       │   │   │   │   │   ├── vi.js
        │       │   │   │   │   │   ├── zh-cn.js
        │       │   │   │   │   │   └── zh-tw.js
        │       │   │   │   │   └── moment.js
        │       │   │   │   └── templates/
        │       │   │   │       ├── amd-named.js
        │       │   │   │       ├── amd.js
        │       │   │   │       ├── globals.js
        │       │   │   │       ├── locale-header.js
        │       │   │   │       └── test-header.js
        │       │   │   ├── ng-file-upload/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── FileAPI.flash.swf
        │       │   │   │   ├── FileAPI.js
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-file-upload-all.js
        │       │   │   │   ├── angular-file-upload-shim.js
        │       │   │   │   ├── angular-file-upload.js
        │       │   │   │   ├── bower.json
        │       │   │   │   └── ng-file-upload-all.js
        │       │   │   ├── ngInfiniteScroll/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── build/
        │       │   │   │   │   └── ng-infinite-scroll.js
        │       │   │   │   ├── package.json
        │       │   │   │   └── src/
        │       │   │   │       └── infinite-scroll.coffee
        │       │   │   ├── ngtoast/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   └── dist/
        │       │   │   │       ├── ngToast-animations.css
        │       │   │   │       ├── ngToast.css
        │       │   │   │       └── ngToast.js
        │       │   │   └── openlayers/
        │       │   │       ├── .bower.json
        │       │   │       ├── .gitignore
        │       │   │       ├── apidoc_config/
        │       │   │       │   ├── Languages.txt
        │       │   │       │   ├── Menu.txt
        │       │   │       │   ├── OL.css
        │       │   │       │   └── Topics.txt
        │       │   │       ├── authors.txt
        │       │   │       ├── build/
        │       │   │       │   ├── README.txt
        │       │   │       │   ├── build.py
        │       │   │       │   ├── buildUncompressed.py
        │       │   │       │   ├── closure-compiler/
        │       │   │       │   │   └── Externs.js
        │       │   │       │   ├── full.cfg
        │       │   │       │   ├── license.txt
        │       │   │       │   ├── light.cfg
        │       │   │       │   ├── lite.cfg
        │       │   │       │   ├── mobile.cfg
        │       │   │       │   └── tests.cfg
        │       │   │       ├── doc_config/
        │       │   │       │   ├── Languages.txt
        │       │   │       │   ├── Menu.txt
        │       │   │       │   ├── OL.css
        │       │   │       │   └── Topics.txt
        │       │   │       ├── lib/
        │       │   │       │   ├── Firebug/
        │       │   │       │   │   ├── firebug.css
        │       │   │       │   │   ├── firebug.html
        │       │   │       │   │   ├── firebug.js
        │       │   │       │   │   ├── firebugx.js
        │       │   │       │   │   ├── license.txt
        │       │   │       │   │   └── readme.txt
        │       │   │       │   ├── OpenLayers/
        │       │   │       │   │   ├── Animation.js
        │       │   │       │   │   ├── BaseTypes/
        │       │   │       │   │   │   ├── Bounds.js
        │       │   │       │   │   │   ├── Class.js
        │       │   │       │   │   │   ├── Date.js
        │       │   │       │   │   │   ├── Element.js
        │       │   │       │   │   │   ├── LonLat.js
        │       │   │       │   │   │   ├── Pixel.js
        │       │   │       │   │   │   └── Size.js
        │       │   │       │   │   ├── BaseTypes.js
        │       │   │       │   │   ├── Console.js
        │       │   │       │   │   ├── Control/
        │       │   │       │   │   │   ├── ArgParser.js
        │       │   │       │   │   │   ├── Attribution.js
        │       │   │       │   │   │   ├── Button.js
        │       │   │       │   │   │   ├── CacheRead.js
        │       │   │       │   │   │   ├── CacheWrite.js
        │       │   │       │   │   │   ├── DragFeature.js
        │       │   │       │   │   │   ├── DragPan.js
        │       │   │       │   │   │   ├── DrawFeature.js
        │       │   │       │   │   │   ├── EditingToolbar.js
        │       │   │       │   │   │   ├── Geolocate.js
        │       │   │       │   │   │   ├── GetFeature.js
        │       │   │       │   │   │   ├── Graticule.js
        │       │   │       │   │   │   ├── KeyboardDefaults.js
        │       │   │       │   │   │   ├── LayerSwitcher.js
        │       │   │       │   │   │   ├── Measure.js
        │       │   │       │   │   │   ├── ModifyFeature/
        │       │   │       │   │   │   │   └── BySegment.js
        │       │   │       │   │   │   ├── ModifyFeature.js
        │       │   │       │   │   │   ├── MousePosition.js
        │       │   │       │   │   │   ├── NavToolbar.js
        │       │   │       │   │   │   ├── Navigation.js
        │       │   │       │   │   │   ├── NavigationHistory.js
        │       │   │       │   │   │   ├── OverviewMap.js
        │       │   │       │   │   │   ├── Pan.js
        │       │   │       │   │   │   ├── PanPanel.js
        │       │   │       │   │   │   ├── PanZoom.js
        │       │   │       │   │   │   ├── PanZoomBar.js
        │       │   │       │   │   │   ├── Panel.js
        │       │   │       │   │   │   ├── Permalink.js
        │       │   │       │   │   │   ├── PinchZoom.js
        │       │   │       │   │   │   ├── SLDSelect.js
        │       │   │       │   │   │   ├── Scale.js
        │       │   │       │   │   │   ├── ScaleLine.js
        │       │   │       │   │   │   ├── SelectFeature.js
        │       │   │       │   │   │   ├── Snapping.js
        │       │   │       │   │   │   ├── Split.js
        │       │   │       │   │   │   ├── TextButtonPanel.js
        │       │   │       │   │   │   ├── TouchNavigation.js
        │       │   │       │   │   │   ├── TransformFeature.js
        │       │   │       │   │   │   ├── UTFGrid.js
        │       │   │       │   │   │   ├── WMSGetFeatureInfo.js
        │       │   │       │   │   │   ├── WMTSGetFeatureInfo.js
        │       │   │       │   │   │   ├── Zoom.js
        │       │   │       │   │   │   ├── ZoomBox.js
        │       │   │       │   │   │   ├── ZoomIn.js
        │       │   │       │   │   │   ├── ZoomOut.js
        │       │   │       │   │   │   ├── ZoomPanel.js
        │       │   │       │   │   │   └── ZoomToMaxExtent.js
        │       │   │       │   │   ├── Control.js
        │       │   │       │   │   ├── Events/
        │       │   │       │   │   │   ├── buttonclick.js
        │       │   │       │   │   │   └── featureclick.js
        │       │   │       │   │   ├── Events.js
        │       │   │       │   │   ├── Feature/
        │       │   │       │   │   │   └── Vector.js
        │       │   │       │   │   ├── Feature.js
        │       │   │       │   │   ├── Filter/
        │       │   │       │   │   │   ├── Comparison.js
        │       │   │       │   │   │   ├── FeatureId.js
        │       │   │       │   │   │   ├── Function.js
        │       │   │       │   │   │   ├── Logical.js
        │       │   │       │   │   │   └── Spatial.js
        │       │   │       │   │   ├── Filter.js
        │       │   │       │   │   ├── Format/
        │       │   │       │   │   │   ├── ArcXML/
        │       │   │       │   │   │   │   └── Features.js
        │       │   │       │   │   │   ├── ArcXML.js
        │       │   │       │   │   │   ├── Atom.js
        │       │   │       │   │   │   ├── CQL.js
        │       │   │       │   │   │   ├── CSWGetDomain/
        │       │   │       │   │   │   │   └── v2_0_2.js
        │       │   │       │   │   │   ├── CSWGetDomain.js
        │       │   │       │   │   │   ├── CSWGetRecords/
        │       │   │       │   │   │   │   └── v2_0_2.js
        │       │   │       │   │   │   ├── CSWGetRecords.js
        │       │   │       │   │   │   ├── Context.js
        │       │   │       │   │   │   ├── EncodedPolyline.js
        │       │   │       │   │   │   ├── Filter/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   ├── v2.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   ├── Filter.js
        │       │   │       │   │   │   ├── GML/
        │       │   │       │   │   │   │   ├── Base.js
        │       │   │       │   │   │   │   ├── v2.js
        │       │   │       │   │   │   │   └── v3.js
        │       │   │       │   │   │   ├── GML.js
        │       │   │       │   │   │   ├── GPX.js
        │       │   │       │   │   │   ├── GeoJSON.js
        │       │   │       │   │   │   ├── GeoRSS.js
        │       │   │       │   │   │   ├── JSON.js
        │       │   │       │   │   │   ├── KML.js
        │       │   │       │   │   │   ├── OGCExceptionReport.js
        │       │   │       │   │   │   ├── OSM.js
        │       │   │       │   │   │   ├── OWSCommon/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── OWSCommon.js
        │       │   │       │   │   │   ├── OWSContext/
        │       │   │       │   │   │   │   └── v0_3_1.js
        │       │   │       │   │   │   ├── OWSContext.js
        │       │   │       │   │   │   ├── QueryStringFilter.js
        │       │   │       │   │   │   ├── SLD/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_0_0_GeoServer.js
        │       │   │       │   │   │   ├── SLD.js
        │       │   │       │   │   │   ├── SOSCapabilities/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── SOSCapabilities.js
        │       │   │       │   │   │   ├── SOSGetFeatureOfInterest.js
        │       │   │       │   │   │   ├── SOSGetObservation.js
        │       │   │       │   │   │   ├── TMSCapabilities.js
        │       │   │       │   │   │   ├── Text.js
        │       │   │       │   │   │   ├── WCSCapabilities/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── WCSCapabilities.js
        │       │   │       │   │   │   ├── WCSDescribeCoverage/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── WCSDescribeCoverage.js
        │       │   │       │   │   │   ├── WCSGetCoverage.js
        │       │   │       │   │   │   ├── WFS.js
        │       │   │       │   │   │   ├── WFSCapabilities/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   ├── WFSCapabilities.js
        │       │   │       │   │   │   ├── WFSDescribeFeatureType.js
        │       │   │       │   │   │   ├── WFST/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   ├── WFST.js
        │       │   │       │   │   │   ├── WKT.js
        │       │   │       │   │   │   ├── WMC/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── WMC.js
        │       │   │       │   │   │   ├── WMSCapabilities/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_1.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   ├── v1_1_1.js
        │       │   │       │   │   │   │   ├── v1_1_1_WMSC.js
        │       │   │       │   │   │   │   ├── v1_3.js
        │       │   │       │   │   │   │   └── v1_3_0.js
        │       │   │       │   │   │   ├── WMSCapabilities.js
        │       │   │       │   │   │   ├── WMSDescribeLayer/
        │       │   │       │   │   │   │   └── v1_1.js
        │       │   │       │   │   │   ├── WMSDescribeLayer.js
        │       │   │       │   │   │   ├── WMSGetFeatureInfo.js
        │       │   │       │   │   │   ├── WMTSCapabilities/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── WMTSCapabilities.js
        │       │   │       │   │   │   ├── WPSCapabilities/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── WPSCapabilities.js
        │       │   │       │   │   │   ├── WPSDescribeProcess/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── WPSDescribeProcess.js
        │       │   │       │   │   │   ├── WPSExecute.js
        │       │   │       │   │   │   ├── XLS/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── XLS.js
        │       │   │       │   │   │   ├── XML/
        │       │   │       │   │   │   │   └── VersionedOGC.js
        │       │   │       │   │   │   └── XML.js
        │       │   │       │   │   ├── Format.js
        │       │   │       │   │   ├── Geometry/
        │       │   │       │   │   │   ├── Collection.js
        │       │   │       │   │   │   ├── Curve.js
        │       │   │       │   │   │   ├── LineString.js
        │       │   │       │   │   │   ├── LinearRing.js
        │       │   │       │   │   │   ├── MultiLineString.js
        │       │   │       │   │   │   ├── MultiPoint.js
        │       │   │       │   │   │   ├── MultiPolygon.js
        │       │   │       │   │   │   ├── Point.js
        │       │   │       │   │   │   └── Polygon.js
        │       │   │       │   │   ├── Geometry.js
        │       │   │       │   │   ├── Handler/
        │       │   │       │   │   │   ├── Box.js
        │       │   │       │   │   │   ├── Click.js
        │       │   │       │   │   │   ├── Drag.js
        │       │   │       │   │   │   ├── Feature.js
        │       │   │       │   │   │   ├── Hover.js
        │       │   │       │   │   │   ├── Keyboard.js
        │       │   │       │   │   │   ├── MouseWheel.js
        │       │   │       │   │   │   ├── Path.js
        │       │   │       │   │   │   ├── Pinch.js
        │       │   │       │   │   │   ├── Point.js
        │       │   │       │   │   │   ├── Polygon.js
        │       │   │       │   │   │   └── RegularPolygon.js
        │       │   │       │   │   ├── Handler.js
        │       │   │       │   │   ├── Icon.js
        │       │   │       │   │   ├── Kinetic.js
        │       │   │       │   │   ├── Lang/
        │       │   │       │   │   │   ├── ar.js
        │       │   │       │   │   │   ├── be-tarask.js
        │       │   │       │   │   │   ├── bg.js
        │       │   │       │   │   │   ├── br.js
        │       │   │       │   │   │   ├── ca.js
        │       │   │       │   │   │   ├── cs-CZ.js
        │       │   │       │   │   │   ├── da-DK.js
        │       │   │       │   │   │   ├── de.js
        │       │   │       │   │   │   ├── el.js
        │       │   │       │   │   │   ├── en-CA.js
        │       │   │       │   │   │   ├── en.js
        │       │   │       │   │   │   ├── es.js
        │       │   │       │   │   │   ├── fi.js
        │       │   │       │   │   │   ├── fr.js
        │       │   │       │   │   │   ├── fur.js
        │       │   │       │   │   │   ├── gl.js
        │       │   │       │   │   │   ├── gsw.js
        │       │   │       │   │   │   ├── hr.js
        │       │   │       │   │   │   ├── hsb.js
        │       │   │       │   │   │   ├── hu.js
        │       │   │       │   │   │   ├── ia.js
        │       │   │       │   │   │   ├── id.js
        │       │   │       │   │   │   ├── io.js
        │       │   │       │   │   │   ├── is.js
        │       │   │       │   │   │   ├── it.js
        │       │   │       │   │   │   ├── ja.js
        │       │   │       │   │   │   ├── km.js
        │       │   │       │   │   │   ├── ksh.js
        │       │   │       │   │   │   ├── lt.js
        │       │   │       │   │   │   ├── nb.js
        │       │   │       │   │   │   ├── nds.js
        │       │   │       │   │   │   ├── nl.js
        │       │   │       │   │   │   ├── nn.js
        │       │   │       │   │   │   ├── oc.js
        │       │   │       │   │   │   ├── pl.js
        │       │   │       │   │   │   ├── pt-BR.js
        │       │   │       │   │   │   ├── pt.js
        │       │   │       │   │   │   ├── ro.js
        │       │   │       │   │   │   ├── ru.js
        │       │   │       │   │   │   ├── sk.js
        │       │   │       │   │   │   ├── sv-SE.js
        │       │   │       │   │   │   ├── te.js
        │       │   │       │   │   │   ├── vi.js
        │       │   │       │   │   │   ├── zh-CN.js
        │       │   │       │   │   │   └── zh-TW.js
        │       │   │       │   │   ├── Lang.js
        │       │   │       │   │   ├── Layer/
        │       │   │       │   │   │   ├── ArcGIS93Rest.js
        │       │   │       │   │   │   ├── ArcGISCache.js
        │       │   │       │   │   │   ├── ArcIMS.js
        │       │   │       │   │   │   ├── Bing.js
        │       │   │       │   │   │   ├── Boxes.js
        │       │   │       │   │   │   ├── EventPane.js
        │       │   │       │   │   │   ├── FixedZoomLevels.js
        │       │   │       │   │   │   ├── GeoRSS.js
        │       │   │       │   │   │   ├── Google/
        │       │   │       │   │   │   │   └── v3.js
        │       │   │       │   │   │   ├── Google.js
        │       │   │       │   │   │   ├── Grid.js
        │       │   │       │   │   │   ├── HTTPRequest.js
        │       │   │       │   │   │   ├── Image.js
        │       │   │       │   │   │   ├── KaMap.js
        │       │   │       │   │   │   ├── KaMapCache.js
        │       │   │       │   │   │   ├── MapGuide.js
        │       │   │       │   │   │   ├── MapServer.js
        │       │   │       │   │   │   ├── Markers.js
        │       │   │       │   │   │   ├── OSM.js
        │       │   │       │   │   │   ├── PointGrid.js
        │       │   │       │   │   │   ├── PointTrack.js
        │       │   │       │   │   │   ├── SphericalMercator.js
        │       │   │       │   │   │   ├── TMS.js
        │       │   │       │   │   │   ├── Text.js
        │       │   │       │   │   │   ├── TileCache.js
        │       │   │       │   │   │   ├── UTFGrid.js
        │       │   │       │   │   │   ├── Vector/
        │       │   │       │   │   │   │   └── RootContainer.js
        │       │   │       │   │   │   ├── Vector.js
        │       │   │       │   │   │   ├── WMS.js
        │       │   │       │   │   │   ├── WMTS.js
        │       │   │       │   │   │   ├── WorldWind.js
        │       │   │       │   │   │   ├── XYZ.js
        │       │   │       │   │   │   └── Zoomify.js
        │       │   │       │   │   ├── Layer.js
        │       │   │       │   │   ├── Map.js
        │       │   │       │   │   ├── Marker/
        │       │   │       │   │   │   └── Box.js
        │       │   │       │   │   ├── Marker.js
        │       │   │       │   │   ├── Popup/
        │       │   │       │   │   │   ├── Anchored.js
        │       │   │       │   │   │   ├── Framed.js
        │       │   │       │   │   │   └── FramedCloud.js
        │       │   │       │   │   ├── Popup.js
        │       │   │       │   │   ├── Projection.js
        │       │   │       │   │   ├── Protocol/
        │       │   │       │   │   │   ├── CSW/
        │       │   │       │   │   │   │   └── v2_0_2.js
        │       │   │       │   │   │   ├── CSW.js
        │       │   │       │   │   │   ├── HTTP.js
        │       │   │       │   │   │   ├── SOS/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── SOS.js
        │       │   │       │   │   │   ├── Script.js
        │       │   │       │   │   │   ├── WFS/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   └── WFS.js
        │       │   │       │   │   ├── Protocol.js
        │       │   │       │   │   ├── Renderer/
        │       │   │       │   │   │   ├── Canvas.js
        │       │   │       │   │   │   ├── Elements.js
        │       │   │       │   │   │   ├── SVG.js
        │       │   │       │   │   │   └── VML.js
        │       │   │       │   │   ├── Renderer.js
        │       │   │       │   │   ├── Request/
        │       │   │       │   │   │   └── XMLHttpRequest.js
        │       │   │       │   │   ├── Request.js
        │       │   │       │   │   ├── Rule.js
        │       │   │       │   │   ├── SingleFile.js
        │       │   │       │   │   ├── Spherical.js
        │       │   │       │   │   ├── Strategy/
        │       │   │       │   │   │   ├── BBOX.js
        │       │   │       │   │   │   ├── Cluster.js
        │       │   │       │   │   │   ├── Filter.js
        │       │   │       │   │   │   ├── Fixed.js
        │       │   │       │   │   │   ├── Paging.js
        │       │   │       │   │   │   ├── Refresh.js
        │       │   │       │   │   │   └── Save.js
        │       │   │       │   │   ├── Strategy.js
        │       │   │       │   │   ├── Style.js
        │       │   │       │   │   ├── Style2.js
        │       │   │       │   │   ├── StyleMap.js
        │       │   │       │   │   ├── Symbolizer/
        │       │   │       │   │   │   ├── Line.js
        │       │   │       │   │   │   ├── Point.js
        │       │   │       │   │   │   ├── Polygon.js
        │       │   │       │   │   │   ├── Raster.js
        │       │   │       │   │   │   └── Text.js
        │       │   │       │   │   ├── Symbolizer.js
        │       │   │       │   │   ├── Tile/
        │       │   │       │   │   │   ├── Image/
        │       │   │       │   │   │   │   └── IFrame.js
        │       │   │       │   │   │   ├── Image.js
        │       │   │       │   │   │   └── UTFGrid.js
        │       │   │       │   │   ├── Tile.js
        │       │   │       │   │   ├── TileManager.js
        │       │   │       │   │   ├── Tween.js
        │       │   │       │   │   ├── Util/
        │       │   │       │   │   │   └── vendorPrefix.js
        │       │   │       │   │   ├── Util.js
        │       │   │       │   │   ├── WPSClient.js
        │       │   │       │   │   └── WPSProcess.js
        │       │   │       │   ├── OpenLayers.js
        │       │   │       │   ├── Rico/
        │       │   │       │   │   ├── Color.js
        │       │   │       │   │   ├── Corner.js
        │       │   │       │   │   └── license.js
        │       │   │       │   └── deprecated.js
        │       │   │       ├── license.txt
        │       │   │       ├── licenses/
        │       │   │       │   ├── APACHE-2.0.txt
        │       │   │       │   ├── BSD-LICENSE.txt
        │       │   │       │   └── MIT-LICENSE.txt
        │       │   │       ├── notes/
        │       │   │       │   ├── 2.12.md
        │       │   │       │   ├── 2.13.md
        │       │   │       │   └── 2.14.md
        │       │   │       ├── readme.md
        │       │   │       ├── tests/
        │       │   │       │   ├── Animation.html
        │       │   │       │   ├── BaseTypes/
        │       │   │       │   │   ├── Bounds.html
        │       │   │       │   │   ├── Class.html
        │       │   │       │   │   ├── Date.html
        │       │   │       │   │   ├── Element.html
        │       │   │       │   │   ├── LonLat.html
        │       │   │       │   │   ├── Pixel.html
        │       │   │       │   │   └── Size.html
        │       │   │       │   ├── BaseTypes.html
        │       │   │       │   ├── Console.html
        │       │   │       │   ├── Control/
        │       │   │       │   │   ├── ArgParser.html
        │       │   │       │   │   ├── Attribution.html
        │       │   │       │   │   ├── Button.html
        │       │   │       │   │   ├── CacheRead.html
        │       │   │       │   │   ├── CacheWrite.html
        │       │   │       │   │   ├── DragFeature.html
        │       │   │       │   │   ├── DragPan.html
        │       │   │       │   │   ├── DrawFeature.html
        │       │   │       │   │   ├── EditingToolbar.html
        │       │   │       │   │   ├── Geolocate.html
        │       │   │       │   │   ├── GetFeature.html
        │       │   │       │   │   ├── Graticule.html
        │       │   │       │   │   ├── KeyboardDefaults.html
        │       │   │       │   │   ├── LayerSwitcher.html
        │       │   │       │   │   ├── Measure.html
        │       │   │       │   │   ├── ModifyFeature/
        │       │   │       │   │   │   └── BySegment.html
        │       │   │       │   │   ├── ModifyFeature.html
        │       │   │       │   │   ├── MousePosition.html
        │       │   │       │   │   ├── NavToolbar.html
        │       │   │       │   │   ├── Navigation.html
        │       │   │       │   │   ├── NavigationHistory.html
        │       │   │       │   │   ├── OverviewMap.html
        │       │   │       │   │   ├── Pan.html
        │       │   │       │   │   ├── PanPanel.html
        │       │   │       │   │   ├── PanZoom.html
        │       │   │       │   │   ├── PanZoomBar.html
        │       │   │       │   │   ├── Panel.html
        │       │   │       │   │   ├── Permalink.html
        │       │   │       │   │   ├── PinchZoom.html
        │       │   │       │   │   ├── SLDSelect.html
        │       │   │       │   │   ├── Scale.html
        │       │   │       │   │   ├── ScaleLine.html
        │       │   │       │   │   ├── SelectFeature.html
        │       │   │       │   │   ├── Snapping.html
        │       │   │       │   │   ├── Split.html
        │       │   │       │   │   ├── TextButtonPanel.html
        │       │   │       │   │   ├── TouchNavigation.html
        │       │   │       │   │   ├── TransformFeature.html
        │       │   │       │   │   ├── UTFGrid.html
        │       │   │       │   │   ├── WMSGetFeatureInfo.html
        │       │   │       │   │   ├── WMTSGetFeatureInfo.html
        │       │   │       │   │   ├── Zoom.html
        │       │   │       │   │   ├── ZoomBox.html
        │       │   │       │   │   ├── ZoomIn.html
        │       │   │       │   │   ├── ZoomOut.html
        │       │   │       │   │   └── ZoomToMaxExtent.html
        │       │   │       │   ├── Control.html
        │       │   │       │   ├── Events/
        │       │   │       │   │   ├── buttonclick.html
        │       │   │       │   │   └── featureclick.html
        │       │   │       │   ├── Events.html
        │       │   │       │   ├── Extras.html
        │       │   │       │   ├── Feature/
        │       │   │       │   │   └── Vector.html
        │       │   │       │   ├── Feature.html
        │       │   │       │   ├── Filter/
        │       │   │       │   │   ├── Comparison.html
        │       │   │       │   │   ├── FeatureId.html
        │       │   │       │   │   ├── Logical.html
        │       │   │       │   │   └── Spatial.html
        │       │   │       │   ├── Filter.html
        │       │   │       │   ├── Format/
        │       │   │       │   │   ├── ArcXML/
        │       │   │       │   │   │   └── Features.html
        │       │   │       │   │   ├── ArcXML.html
        │       │   │       │   │   ├── Atom.html
        │       │   │       │   │   ├── CQL.html
        │       │   │       │   │   ├── CSWGetDomain/
        │       │   │       │   │   │   ├── v2_0_2.html
        │       │   │       │   │   │   └── v2_0_2.js
        │       │   │       │   │   ├── CSWGetDomain.html
        │       │   │       │   │   ├── CSWGetRecords/
        │       │   │       │   │   │   ├── v2_0_2.html
        │       │   │       │   │   │   └── v2_0_2.js
        │       │   │       │   │   ├── CSWGetRecords.html
        │       │   │       │   │   ├── EncodedPolyline.html
        │       │   │       │   │   ├── Filter/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   ├── v1_1_0.html
        │       │   │       │   │   │   └── v2_0_0.html
        │       │   │       │   │   ├── Filter.html
        │       │   │       │   │   ├── GML/
        │       │   │       │   │   │   ├── cases.js
        │       │   │       │   │   │   ├── v2.html
        │       │   │       │   │   │   └── v3.html
        │       │   │       │   │   ├── GML.html
        │       │   │       │   │   ├── GPX.html
        │       │   │       │   │   ├── GeoJSON.html
        │       │   │       │   │   ├── GeoRSS.html
        │       │   │       │   │   ├── JSON.html
        │       │   │       │   │   ├── KML.html
        │       │   │       │   │   ├── OGCExceptionReport.html
        │       │   │       │   │   ├── OSM.html
        │       │   │       │   │   ├── OWSCommon/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_1_0.html
        │       │   │       │   │   ├── OWSContext/
        │       │   │       │   │   │   └── v0_3_1.html
        │       │   │       │   │   ├── QueryStringFilter.html
        │       │   │       │   │   ├── SLD/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_0_0_GeoServer.html
        │       │   │       │   │   ├── SLD.html
        │       │   │       │   │   ├── SOSCapabilities/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_0_0.js
        │       │   │       │   │   ├── SOSGetFeatureOfInterest.html
        │       │   │       │   │   ├── SOSGetObservation.html
        │       │   │       │   │   ├── TMSCapabilities.html
        │       │   │       │   │   ├── Text.html
        │       │   │       │   │   ├── WCSCapabilities/
        │       │   │       │   │   │   └── v1.html
        │       │   │       │   │   ├── WCSCapabilities.html
        │       │   │       │   │   ├── WCSDescribeCoverage/
        │       │   │       │   │   │   └── v1.html
        │       │   │       │   │   ├── WCSDescribeCoverage.html
        │       │   │       │   │   ├── WCSGetCoverage.html
        │       │   │       │   │   ├── WFS.html
        │       │   │       │   │   ├── WFSCapabilities/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   └── v2.html
        │       │   │       │   │   ├── WFSCapabilities.html
        │       │   │       │   │   ├── WFSDescribeFeatureType.html
        │       │   │       │   │   ├── WFST/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   ├── v1_1_0.html
        │       │   │       │   │   │   └── v2_0_0.html
        │       │   │       │   │   ├── WFST.html
        │       │   │       │   │   ├── WKT.html
        │       │   │       │   │   ├── WMC/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   └── v1_1_0.html
        │       │   │       │   │   ├── WMC.html
        │       │   │       │   │   ├── WMSCapabilities/
        │       │   │       │   │   │   ├── v1_1_1.html
        │       │   │       │   │   │   ├── v1_1_1_WMSC.html
        │       │   │       │   │   │   └── v1_3_0.html
        │       │   │       │   │   ├── WMSCapabilities.html
        │       │   │       │   │   ├── WMSDescribeLayer.html
        │       │   │       │   │   ├── WMSGetFeatureInfo.html
        │       │   │       │   │   ├── WMTSCapabilities/
        │       │   │       │   │   │   └── v1_0_0.html
        │       │   │       │   │   ├── WMTSCapabilities.html
        │       │   │       │   │   ├── WPSCapabilities/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_0_0.js
        │       │   │       │   │   ├── WPSDescribeProcess.html
        │       │   │       │   │   ├── WPSExecute.html
        │       │   │       │   │   ├── XLS/
        │       │   │       │   │   │   └── v1_1_0.html
        │       │   │       │   │   ├── XML/
        │       │   │       │   │   │   └── VersionedOGC.html
        │       │   │       │   │   └── XML.html
        │       │   │       │   ├── Format.html
        │       │   │       │   ├── Geometry/
        │       │   │       │   │   ├── Collection.html
        │       │   │       │   │   ├── Curve.html
        │       │   │       │   │   ├── LineString.html
        │       │   │       │   │   ├── LinearRing.html
        │       │   │       │   │   ├── MultiLineString.html
        │       │   │       │   │   ├── MultiPoint.html
        │       │   │       │   │   ├── MultiPolygon.html
        │       │   │       │   │   ├── Point.html
        │       │   │       │   │   └── Polygon.html
        │       │   │       │   ├── Geometry.html
        │       │   │       │   ├── Handler/
        │       │   │       │   │   ├── Box.html
        │       │   │       │   │   ├── Click.html
        │       │   │       │   │   ├── Drag.html
        │       │   │       │   │   ├── Feature.html
        │       │   │       │   │   ├── Hover.html
        │       │   │       │   │   ├── Keyboard.html
        │       │   │       │   │   ├── MouseWheel.html
        │       │   │       │   │   ├── Path.html
        │       │   │       │   │   ├── Pinch.html
        │       │   │       │   │   ├── Point.html
        │       │   │       │   │   ├── Polygon.html
        │       │   │       │   │   └── RegularPolygon.html
        │       │   │       │   ├── Handler.html
        │       │   │       │   ├── Icon.html
        │       │   │       │   ├── Kinetic.html
        │       │   │       │   ├── Lang.html
        │       │   │       │   ├── Layer/
        │       │   │       │   │   ├── ArcGIS93Rest.html
        │       │   │       │   │   ├── ArcGISCache.html
        │       │   │       │   │   ├── ArcGISCache.json
        │       │   │       │   │   ├── ArcIMS.html
        │       │   │       │   │   ├── Bing.html
        │       │   │       │   │   ├── EventPane.html
        │       │   │       │   │   ├── FixedZoomLevels.html
        │       │   │       │   │   ├── GeoRSS.html
        │       │   │       │   │   ├── Google/
        │       │   │       │   │   │   └── v3.html
        │       │   │       │   │   ├── Grid.html
        │       │   │       │   │   ├── HTTPRequest.html
        │       │   │       │   │   ├── Image.html
        │       │   │       │   │   ├── KaMap.html
        │       │   │       │   │   ├── MapGuide.html
        │       │   │       │   │   ├── MapServer.html
        │       │   │       │   │   ├── Markers.html
        │       │   │       │   │   ├── OSM.html
        │       │   │       │   │   ├── PointGrid.html
        │       │   │       │   │   ├── PointTrack.html
        │       │   │       │   │   ├── SphericalMercator.html
        │       │   │       │   │   ├── TMS.html
        │       │   │       │   │   ├── Text.html
        │       │   │       │   │   ├── TileCache.html
        │       │   │       │   │   ├── UTFGrid.html
        │       │   │       │   │   ├── Vector/
        │       │   │       │   │   │   └── RootContainer.html
        │       │   │       │   │   ├── Vector.html
        │       │   │       │   │   ├── WMS.html
        │       │   │       │   │   ├── WMTS.html
        │       │   │       │   │   ├── WrapDateLine.html
        │       │   │       │   │   ├── XYZ.html
        │       │   │       │   │   ├── atom-1.0.xml
        │       │   │       │   │   ├── data_Layer_Text_textfile.txt
        │       │   │       │   │   ├── data_Layer_Text_textfile_2.txt
        │       │   │       │   │   ├── data_Layer_Text_textfile_overflow.txt
        │       │   │       │   │   └── georss.txt
        │       │   │       │   ├── Layer.html
        │       │   │       │   ├── Map.html
        │       │   │       │   ├── Marker/
        │       │   │       │   │   └── Box.html
        │       │   │       │   ├── Marker.html
        │       │   │       │   ├── OLLoader.js
        │       │   │       │   ├── OpenLayers1.html
        │       │   │       │   ├── OpenLayers2.html
        │       │   │       │   ├── OpenLayers3.html
        │       │   │       │   ├── OpenLayers4.html
        │       │   │       │   ├── OpenLayersJsFiles.html
        │       │   │       │   ├── Popup/
        │       │   │       │   │   ├── Anchored.html
        │       │   │       │   │   └── FramedCloud.html
        │       │   │       │   ├── Popup.html
        │       │   │       │   ├── Projection.html
        │       │   │       │   ├── Protocol/
        │       │   │       │   │   ├── CSW.html
        │       │   │       │   │   ├── HTTP.html
        │       │   │       │   │   ├── SOS.html
        │       │   │       │   │   ├── Script.html
        │       │   │       │   │   └── WFS.html
        │       │   │       │   ├── Protocol.html
        │       │   │       │   ├── README.txt
        │       │   │       │   ├── Renderer/
        │       │   │       │   │   ├── Canvas.html
        │       │   │       │   │   ├── Elements.html
        │       │   │       │   │   ├── SVG.html
        │       │   │       │   │   └── VML.html
        │       │   │       │   ├── Renderer.html
        │       │   │       │   ├── Request/
        │       │   │       │   │   └── XMLHttpRequest.html
        │       │   │       │   ├── Request.html
        │       │   │       │   ├── Rule.html
        │       │   │       │   ├── SingleFile1.html
        │       │   │       │   ├── SingleFile2.html
        │       │   │       │   ├── SingleFile3.html
        │       │   │       │   ├── Strategy/
        │       │   │       │   │   ├── BBOX.html
        │       │   │       │   │   ├── Cluster.html
        │       │   │       │   │   ├── Filter.html
        │       │   │       │   │   ├── Fixed.html
        │       │   │       │   │   ├── Paging.html
        │       │   │       │   │   ├── Refresh.html
        │       │   │       │   │   └── Save.html
        │       │   │       │   ├── Strategy.html
        │       │   │       │   ├── Style.html
        │       │   │       │   ├── Style2.html
        │       │   │       │   ├── StyleMap.html
        │       │   │       │   ├── Symbolizer/
        │       │   │       │   │   ├── Line.html
        │       │   │       │   │   ├── Point.html
        │       │   │       │   │   ├── Polygon.html
        │       │   │       │   │   ├── Raster.html
        │       │   │       │   │   └── Text.html
        │       │   │       │   ├── Symbolizer.html
        │       │   │       │   ├── Test.AnotherWay.baseadditions.js
        │       │   │       │   ├── Test.AnotherWay.css
        │       │   │       │   ├── Test.AnotherWay.geom_eq.js
        │       │   │       │   ├── Test.AnotherWay.js
        │       │   │       │   ├── Test.AnotherWay.xml_eq.js
        │       │   │       │   ├── Tile/
        │       │   │       │   │   ├── Image/
        │       │   │       │   │   │   └── IFrame.html
        │       │   │       │   │   ├── Image.html
        │       │   │       │   │   └── UTFGrid.html
        │       │   │       │   ├── Tile.html
        │       │   │       │   ├── TileManager.html
        │       │   │       │   ├── Tween.html
        │       │   │       │   ├── Util/
        │       │   │       │   │   └── vendorPrefix.html
        │       │   │       │   ├── Util.html
        │       │   │       │   ├── Util_common.js
        │       │   │       │   ├── Util_w3c.html
        │       │   │       │   ├── WPSClient.html
        │       │   │       │   ├── WPSProcess.html
        │       │   │       │   ├── atom-1.0.xml
        │       │   │       │   ├── auto-tests.html
        │       │   │       │   ├── data_Layer_Text_textfile.txt
        │       │   │       │   ├── data_Layer_Text_textfile_2.txt
        │       │   │       │   ├── data_Layer_Text_textfile_overflow.txt
        │       │   │       │   ├── deprecated/
        │       │   │       │   │   ├── Ajax.html
        │       │   │       │   │   ├── BaseTypes/
        │       │   │       │   │   │   ├── Class.html
        │       │   │       │   │   │   └── Element.html
        │       │   │       │   │   ├── Control/
        │       │   │       │   │   │   └── MouseToolbar.html
        │       │   │       │   │   ├── Geometry/
        │       │   │       │   │   │   └── Rectangle.html
        │       │   │       │   │   ├── Layer/
        │       │   │       │   │   │   ├── GML.html
        │       │   │       │   │   │   ├── MapServer/
        │       │   │       │   │   │   │   └── Untiled.html
        │       │   │       │   │   │   ├── MapServer.html
        │       │   │       │   │   │   ├── WFS.html
        │       │   │       │   │   │   ├── WMS/
        │       │   │       │   │   │   │   └── Post.html
        │       │   │       │   │   │   ├── WMS.html
        │       │   │       │   │   │   ├── Yahoo.html
        │       │   │       │   │   │   ├── mice.xml
        │       │   │       │   │   │   └── owls.xml
        │       │   │       │   │   ├── Popup/
        │       │   │       │   │   │   └── AnchoredBubble.html
        │       │   │       │   │   ├── Protocol/
        │       │   │       │   │   │   ├── SQL/
        │       │   │       │   │   │   │   └── Gears.html
        │       │   │       │   │   │   └── SQL.html
        │       │   │       │   │   ├── Renderer/
        │       │   │       │   │   │   └── SVG2.html
        │       │   │       │   │   ├── Tile/
        │       │   │       │   │   │   └── WFS.html
        │       │   │       │   │   └── Util.html
        │       │   │       │   ├── georss.txt
        │       │   │       │   ├── grid_inittiles.html
        │       │   │       │   ├── index.html
        │       │   │       │   ├── list-tests.html
        │       │   │       │   ├── manual/
        │       │   │       │   │   ├── ajax.html
        │       │   │       │   │   ├── ajax.txt
        │       │   │       │   │   ├── alloverlays-mixed.html
        │       │   │       │   │   ├── arcims-2117.html
        │       │   │       │   │   ├── arkansas.rss
        │       │   │       │   │   ├── big-georss.html
        │       │   │       │   │   ├── box-quirks.html
        │       │   │       │   │   ├── box-strict.html
        │       │   │       │   │   ├── clip-features-svg.html
        │       │   │       │   │   ├── dateline-sketch.html
        │       │   │       │   │   ├── dateline-smallextent.html
        │       │   │       │   │   ├── draw-feature.html
        │       │   │       │   │   ├── feature-handler.html
        │       │   │       │   │   ├── geodesic.html
        │       │   │       │   │   ├── geojson-geomcoll-reprojection.html
        │       │   │       │   │   ├── google-fullscreen-overlay.html
        │       │   │       │   │   ├── google-panning.html
        │       │   │       │   │   ├── google-resize.html
        │       │   │       │   │   ├── google-tilt.html
        │       │   │       │   │   ├── google-v3-resize.html
        │       │   │       │   │   ├── loadend.html
        │       │   │       │   │   ├── map-events.html
        │       │   │       │   │   ├── memory/
        │       │   │       │   │   │   ├── Marker-2258.html
        │       │   │       │   │   │   ├── PanZoom-2323.html
        │       │   │       │   │   │   ├── RemoveChild-2170.html
        │       │   │       │   │   │   └── VML-2170.html
        │       │   │       │   │   ├── multiple-google-layers.html
        │       │   │       │   │   ├── overviewmap-projection.html
        │       │   │       │   │   ├── page-position.html
        │       │   │       │   │   ├── pan-redraw-svg.html
        │       │   │       │   │   ├── popup-keepInMap.html
        │       │   │       │   │   ├── reflow.html
        │       │   │       │   │   ├── renderedDimensions.html
        │       │   │       │   │   ├── select-feature-right-click.html
        │       │   │       │   │   ├── select-feature.html
        │       │   │       │   │   ├── tiles-loading.html
        │       │   │       │   │   ├── tween.html
        │       │   │       │   │   ├── vector-features-performance.html
        │       │   │       │   │   └── vector-layer-zindex.html
        │       │   │       │   ├── mice.xml
        │       │   │       │   ├── node.js/
        │       │   │       │   │   ├── mockdom.js
        │       │   │       │   │   ├── node-tests.cfg
        │       │   │       │   │   ├── node.js
        │       │   │       │   │   ├── run-test.js
        │       │   │       │   │   └── run.sh
        │       │   │       │   ├── owls.xml
        │       │   │       │   ├── run-tests.html
        │       │   │       │   ├── selenium/
        │       │   │       │   │   └── remotecontrol/
        │       │   │       │   │       ├── config.cfg
        │       │   │       │   │       ├── selenium.py
        │       │   │       │   │       ├── setup.txt
        │       │   │       │   │       └── test_ol.py
        │       │   │       │   ├── speed/
        │       │   │       │   │   ├── geometry.html
        │       │   │       │   │   ├── string_format.html
        │       │   │       │   │   ├── vector-renderers.html
        │       │   │       │   │   ├── vector-renderers.js
        │       │   │       │   │   ├── wmc_speed.html
        │       │   │       │   │   ├── wmscaps.html
        │       │   │       │   │   ├── wmscaps.js
        │       │   │       │   │   └── wmscaps.xml
        │       │   │       │   └── throws.js
        │       │   │       ├── theme/
        │       │   │       │   └── default/
        │       │   │       │       ├── google.css
        │       │   │       │       ├── ie6-style.css
        │       │   │       │       ├── style.css
        │       │   │       │       └── style.mobile.css
        │       │   │       └── tools/
        │       │   │           ├── BeautifulSoup.py
        │       │   │           ├── README.txt
        │       │   │           ├── closure_library_jscompiler.py
        │       │   │           ├── closure_ws.py
        │       │   │           ├── exampleparser.py
        │       │   │           ├── jsmin.c
        │       │   │           ├── jsmin.py
        │       │   │           ├── mergejs.py
        │       │   │           ├── minimize.py
        │       │   │           ├── oldot.py
        │       │   │           ├── release.sh
        │       │   │           ├── shrinksafe.py
        │       │   │           ├── toposort.py
        │       │   │           ├── uglify_js.py
        │       │   │           └── update_dev_dir.sh
        │       │   ├── css/
        │       │   │   ├── ie-only.css
        │       │   │   └── tatami.css
        │       │   └── vendor/
        │       │       ├── backgroundsize.min.htc
        │       │       ├── css/
        │       │       │   └── bootstrap/
        │       │       │       ├── css/
        │       │       │       │   └── bootstrap.css
        │       │       │       ├── fonts/
        │       │       │       │   └── glyphiconshalflings-regular.otf
        │       │       │       └── js/
        │       │       │           └── bootstrap.js
        │       │       └── js/
        │       │           ├── marked/
        │       │           │   └── marked.js
        │       │           └── respond/
        │       │               └── respond.js
        │       ├── css/
        │       │   ├── ie-only.css
        │       │   ├── tatami.css
        │       │   └── vendor/
        │       │       ├── backgroundsize.min.htc
        │       │       ├── css/
        │       │       │   ├── bootstrap.css
        │       │       │   └── jQueryjGrowl.css
        │       │       └── fonts/
        │       │           └── glyphiconshalflings-regular.otf
        │       ├── index.html
        │       ├── index.html.tpl
        │       ├── index.jsp
        │       ├── robots.txt
        │       └── sitemap.xml
        └── test/
            ├── java/
            │   └── fr/
            │       └── ippon/
            │           └── tatami/
            │               └── web/
            │                   └── rest/
            │                       ├── GroupControllerTest.java
            │                       ├── TagControllerTest.java
            │                       ├── TimelineControllerTest.java
            │                       └── UserControllerTest.java
            └── javascript/
                └── webapp/
                    └── app/
                        └── components/
                            ├── about/
                            │   └── license/
                            │       └── LicenseController_spec.js
                            ├── account/
                            │   ├── PasswordModule_spec.js
                            │   └── preferences/
                            │       └── Preferences_spec.js
                            └── home/
                                └── status/
                                    └── StatusController_spec.js

================================================
FILE CONTENTS
================================================

================================================
FILE: .gitignore
================================================
data
.idea
*.iml
tatami.iml
tatami.ipr
tatami.iws
.classpath
.project
.settings
target
node_modules/
web/node_modules/
src/main/webapp/WEB-INF/generated-wro4j
.merge_file*
.DS_Store
phantomjsdriver.log
*.log
web/src/main/webapp/app/**/*.CONCAT.js
web/src/main/webapp/app/**/*.min.html
web/src/main/webapp/app/**/*.min.js
web/src/main/webapp/app/**/*.MIN.css
web/src/main/webapp/app/**/*.min.css
web/src/main/webapp/css/tatami.min.css
src/main/webapp/app/shared/footer/FooterView.html.sed.del


================================================
FILE: CONTRIBUTING.md
================================================
Contributing to Tatami
=========================

Open Source
------------------

Tatami is an Open Source project, which uses the Apache 2 [http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)
license. If you contribute to Tatami, you agree that your code belongs to the Tatami project and follows this license.

Submitting code
------------------

* Create a [GitHub account](https://github.com/signup/free).
* [Submit a ticket for your issue](https://github.com/ippontech/tatami/issues), assuming one does not already exist.
  * Clearly describe the issue including steps to reproduce it, when it is a bug.
* Fork the repository on GitHub.
* Make commits of logical units.
* Make sure your commit messages include the ticket number you have created. Github should automatically link
your changes with the ticket.
* Make sure you have added the necessary tests for your changes.
* Run _all_ the tests to assure nothing else was accidentally broken.
* Push your changes in your fork of the repository.
* Submit a pull request to [the repository in the ippontech organization](https://github.com/ippontech/tatami).
  * If you need help about making a pull request, [here is the documentation](https://help.github.com/articles/using-pull-requests).
* Your code will be automatically built by [Buildhive](https://buildhive.cloudbees.com/job/ippontech/job/tatami/). Your
pull request should have a Buildhive comment a few minutes after your commit.



================================================
FILE: README.md
================================================
Tatami
================

Presentation
------------------

Tatami is an Open Source enterprise social network.

A public installation of Tatami is provided by [Ippon Technologies](http://www.ippon.fr) at : [https://tatami.ippon.fr](https://tatami.ippon.fr)

Tatami is made with the following technologies :

- HTML5, [AngularJS](https://angularjs.org/) and [Twitter Bootstrap](http://twitter.github.com/bootstrap/)
- [The Spring Framework](http://www.springsource.org/)
- [Apache Cassandra](http://cassandra.apache.org/)
- [Elastic Search](http://www.elasticsearch.org/)

Tatami is developed by [Ippon Technologies](http://www.ippon.fr)


Installation for developers
---------------------------------------

### 5 minute installation

- Clone, fork or download the source code from this Github page
- Install [Maven 3](http://maven.apache.org/)
- Install [npm](https://www.npmjs.com/)
- Point your terminal to the directory you cloned Tatami to.
    - `cd web`
    - Type `npm install`
    - You may need to give root user permissions: `sudo !!`
    - `cd ..`
- Run Cassandra with Maven : `mvn cassandra:run`
- Run Jetty from tatami/web with Maven: `mvn jetty:run`
- Connect to the application at http://127.0.0.1:8080


To create users, use the registration form. As we have not configured a SMTP server (you can configure it in src/main/resources/META-INF/tatami/tatami.properties - see below "installation for production use" for more options), the validation URL as well as the password will not be e-mailed to you, but you can see them in the log (look at the Jetty console output).

### Using Tomcat instead of Jetty

If you want to use Tomcat instead of Jetty (which works better in development mode on Windows), just use :

- Run Tomcat from Maven : `mvn tomcat7:run`

### Maven tuning and troubleshooting

If you run into some Permgen or OutOfMemory errors, you can configure your Maven settings accordingly :
```
export MAVEN_OPTS="-XX:PermSize=64m -XX:MaxPermSize=128m -Xms256m -Xmx1024m"
```

If you want to debug remotely the application with your IDE, set up your MAVEN_OPTS :
```
export MAVEN_OPTS="$MAVEN_OPTS -Xdebug -Xnoagent -Djava.compiler=NONE -Xrunjdwp:transport=dt_socket,address=8000,server=y,suspend=n"
```

### Cassandra troubleshooting

On Mac OS X, you should use JDK 6 and not JDK 7, see [issue #281](https://github.com/ippontech/tatami/issues/281#issuecomment-12430701).


How to Contribute
---------------------------------------
In order to assure code quality, Ippon manages the pull requests for the project, and upholds certain rules regarding how individuals may contribute. 
You may find these rules in your Tatami installation in the file `CONTRIBUTING.md`.


Installation for production use
---------------------------------------

### Cassandra installation

- Download [Apache Cassandra](http://cassandra.apache.org/)
- Install Cassandra : the application will work fine with just one node, but ideally you should have a cluster with at least 3 or 5 nodes
- Cassandra is configured with its cassandra.yaml file : don't forget to backup your "data" and "commitlog" directories

### Tatami installation

In order to use a stable version, use one of the [available tags](https://github.com/ippontech/tatami/tags).

Tatami can be configured with the src/main/resources/META-INF/tatami/tatami.properties file. You can configure this file in 2 ways :

- Edit the file in your own Tatami fork
- Properties in this file are replaced at build time by Maven : you can set up your own Maven profile with your specific properties

Once Tatami is started, you will be able to check your properties at runtime in the Administration page.

To deploy Tatami :

- Create the Tatami WAR file : `mvn package`
- The WAR file will be called "root.war", as Tatami should be run as the root application (on the "/" Web context)
- Deploy the WAR file on your favorite Java EE server
- The WAR has been tested on Jetty 8 and Tomcat 7, and should work fine on all Java EE servers

Upgrading from a previous version
---------------------------------------

Upgrading is normally just a matter of using a newer version of the application.

Sometimes, you will need to update the Cassandra keyspace: upgrade scripts are available in the src/main/cql/upgrade directory.

Launching stress tests
---------------------------------------

Stress tests are done with [Apache JMeter](http://jmeter.apache.org/).

- Launch Cassandra
- Run Tatami from Maven with the `stress-tests` profile : `mvn jetty:run -Pstress-tests`
- Launch JMeter
- Run the `src/test/jmeter/tatami-create-users.jmx` script : it will create 200 normal users, which each has 200 follower users
- Run the stress test : `src/test/jmeter/tatami-stress-test.jmx`

Launching functional tests
---------------------------------------

Functional tests are a work in progress, you do not have to run them in order to use the application.

Requirement : all components must run on localhost :

- for LDAP authentication, the tests starts the LDAP server that the Tatami server will use
- for fixture setup and assertions, the test connects directly to the local cassandra

Launching UI Tests from maven :

- add this profile on your settings.xml :
```xml
<profile>
  <id>tatami</id>
  <activation>
    <activeByDefault>true</activeByDefault>
  </activation>
  <properties>
    <webdriver.chrome.driver>C:\path\to\chromedriver.exe</webdriver.chrome.driver><!--optional-->
    <google.password>xxxx</google.password>
    <google.email>xxx@xxx.fr</google.email>
  </properties>
</profile>
```

- Run Maven with this command : `mvn clean verify -Puitest`

Launching UI Tests from maven with Chrome :

- install ChromeDriver in your system
- configure the property "webdriver.chrome.driver" in your settings pointing to your chrome driver install directory
- add `-Dgeb.env=chrome` to the maven command above

Launching UI Tests from your IDE :

- Enable a groovy plugin on your IDE
- Activate maven profile "uitest" or add src/integration/* in your classpath
- Run Tatami with Maven : `mvn cassandra:delete cassandra:start jetty:run -Djetty.scanIntervalSeconds=0 -Puitest`
- Run Specs (in src\integration\java\fr\ippon\tatami\uitest) as Junit Tests from your IDE
  => you have to set adequate system properties to your running configurations (the same as those that are necessary in setting.xml for maven : see above)


Thanks
------

Jetbrains is providing us free [Intellij IDEA](http://www.jetbrains.com/idea/) licenses, 
which definitely allows us to be more productive and have more fun on the project!

YourKit is kindly supporting open source projects with its full-featured Java Profiler.
YourKit, LLC is the creator of innovative and intelligent tools for profiling
Java and .NET applications. Take a look at YourKit's leading software products:
[YourKit Java Profiler](http://www.yourkit.com/java/profiler/index.jsp) and
[YourKit .NET Profiler](http://www.yourkit.com/.net/profiler/index.jsp).

License
-------

Copyright © 2012-2015 [Ippon Technologies](http://www.ippon.fr)

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this application except in compliance with the License.
You may obtain a copy of the License at

[http://www.apache.org/licenses/LICENSE-2.0](http://www.apache.org/licenses/LICENSE-2.0)

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.


================================================
FILE: etc/installation/ubuntu/files/maven/settings.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>

<settings xmlns="http://maven.apache.org/SETTINGS/1.0.0"
          xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:schemaLocation="http://maven.apache.org/SETTINGS/1.0.0 http://maven.apache.org/xsd/settings-1.0.0.xsd">

    <localRepository>/opt/tatami/maven/repository</localRepository>

    <pluginGroups></pluginGroups>

    <proxies></proxies>

    <servers></servers>

    <mirrors></mirrors>

    <profiles></profiles>

    <!-- activeProfiles
     | List of profiles that are active for all builds.
     |
    <activeProfiles>
      <activeProfile>alwaysActiveProfile</activeProfile>
      <activeProfile>anotherAlwaysActiveProfile</activeProfile>
    </activeProfiles>
    -->
</settings>

================================================
FILE: etc/installation/ubuntu/install.sh
================================================
#!/bin/sh
#
# description: Installs Tatami on Ubuntu
# This script must be run by the "root" user.
# Run this script directly by typing :
# curl -L https://github.com/ippontech/tatami/raw/master/etc/installation/ubuntu/install.sh | sudo bash
#
# - Tatami is installed in the "/opt/tatami" directory
# - Tatami is run by the "tatami" user
#
echo "Welcome to the Tatami installer"

#################################
# Variables
#################################
echo "Setting up variables"
export USER=tatami
export TATAMI_DIR=/opt/tatami
export MAVEN_VERSION=3.0.4
export JETTY_VERSION=8.1.8.v20121106

#################################
# Install missing packages
#################################
echo "Installing missing packages"
apt-get install git-core curl wget -y --force-yes

#################################
# Install Java
#################################
wget https://github.com/flexiondotorg/oab-java6/raw/0.2.6/oab-java.sh -O oab-java.sh
chmod +x oab-java.sh
sudo ./oab-java.sh
rm oab-java.sh
sudo apt-get install sun-java6-jdk -y

#################################
# Create directories & users
#################################
echo "Creating directories and users"
useradd -m -s /bin/bash $USER

mkdir -p $TATAMI_DIR
mkdir -p $TATAMI_DIR/application
mkdir -p $TATAMI_DIR/maven
mkdir -p $TATAMI_DIR/data
mkdir -p $TATAMI_DIR/data/elasticsearch
mkdir -p $TATAMI_DIR/log
mkdir -p $TATAMI_DIR/log/elasticsearch

#################################
## Download Application
#################################
echo "Getting the application from Github"
cd $TATAMI_DIR/application

git clone https://github.com/ippontech/tatami.git

#################################
## Install Cassandra
#################################
cd $TATAMI_DIR

echo "Installing JNA"
sudo apt-get install libjna-java -y

echo "Configuring OS limits"
cp /etc/security/limits.conf /etc/security/limits.conf.original

echo "* soft nofile 32768" | sudo tee -a /etc/security/limits.conf
echo "* hard nofile 32768" | sudo tee -a /etc/security/limits.conf
echo "root soft nofile 32768" | sudo tee -a /etc/security/limits.conf
echo "root hard nofile 32768" | sudo tee -a /etc/security/limits.conf

echo "* soft nofile 32768"  >> /etc/security/limits.conf
echo "* hard nofile 32768"  >> /etc/security/limits.conf
echo "root soft nofile 32768"  >> /etc/security/limits.conf
echo "root hard nofile 32768"  >> /etc/security/limits.conf
echo "* soft memlock unlimited"  >> /etc/security/limits.conf
echo "* hard memlock unlimited"  >> /etc/security/limits.conf
echo "root soft memlock unlimited"  >> /etc/security/limits.conf
echo "root hard memlock unlimited"  >> /etc/security/limits.conf
echo "* soft as unlimited"  >> /etc/security/limits.conf
echo "* hard as unlimited"  >> /etc/security/limits.conf
echo "root soft as unlimited"  >> /etc/security/limits.conf
echo "root hard as unlimited"  >> /etc/security/limits.conf

sysctl -w vm.max_map_count=131072

sudo swapoff --all

# Cassandra Installation
echo "Installing Cassandra"
echo "deb http://debian.datastax.com/community stable main"  >> /etc/apt/sources.list
curl -L http://debian.datastax.com/debian/repo_key | sudo apt-key add -
sudo apt-get update
sudo apt-get install python-cql dsc1.1 -y
sudo apt-get install opscenter-free -y

sudo service opscenterd start

#################################
## Install Jetty
#################################
echo "Installing Jetty"
cd $TATAMI_DIR

sysctl -w net.core.rmem_max=16777216
sysctl -w net.core.wmem_max=16777216
sysctl -w net.ipv4.tcp_rmem="4096 87380 16777216"
sysctl -w net.ipv4.tcp_wmem="4096 16384 16777216"
sysctl -w net.core.somaxconn=4096
sysctl -w net.core.netdev_max_backlog=16384
sysctl -w net.ipv4.tcp_max_syn_backlog=8192
sysctl -w net.ipv4.tcp_syncookies=1
sysctl -w net.ipv4.ip_local_port_range="1024 65535"
sysctl -w net.ipv4.tcp_tw_recycle=1
sysctl -w net.ipv4.tcp_congestion_control=cubic

wget http://central.maven.org/maven2/org/mortbay/jetty/dist/jetty-deb/$JETTY_VERSION/jetty-deb-$JETTY_VERSION.deb
dpkg -i jetty-deb-$JETTY_VERSION.deb
rm -f jetty-deb-$JETTY_VERSION.deb
rm -rf /opt/jetty/webapps/*

#################################
## Install Maven
#################################
echo "Installing Maven"

cd $TATAMI_DIR/maven

wget http://mirrors.linsrv.net/apache/maven/maven-3/$MAVEN_VERSION/binaries/apache-maven-$MAVEN_VERSION-bin.tar.gz
tar -xzf apache-maven-$MAVEN_VERSION-bin.tar.gz
rm -f apache-maven-$MAVEN_VERSION-bin.tar.gz
ln -s $TATAMI_DIR/maven/apache-maven-$MAVEN_VERSION $TATAMI_DIR/maven/current

# Configure Maven for the tatami user
echo "# Begin tatami configuration" >> /home/tatami/.profile
echo "export M2_HOME=/opt/tatami/maven/current" >> /home/tatami/.profile
echo "export PATH=/opt/tatami/maven/current/bin:$PATH" >> /home/tatami/.profile
echo "export MAVEN_OPTS=\"-XX:MaxPermSize=64m -Xms256m -Xmx1024m\"" >> /home/tatami/.profile
echo "# End tatami configuration" >> /home/tatami/.profile

# Configure Maven repository
mkdir -p $TATAMI_DIR/maven/repository
cp $TATAMI_DIR/application/tatami/etc/installation/ubuntu/files/maven/settings.xml $TATAMI_DIR/maven/apache-maven-$MAVEN_VERSION/conf

#################################
## Install & run Application
#################################
chown -R $USER $TATAMI_DIR
./update.sh

#################################
## Post install
#################################


================================================
FILE: etc/installation/ubuntu/uninstall.sh
================================================
#!/bin/sh
#
# description: Uninstalls Tatami on Ubuntu
# This script must be run by the "root" user.
#
# Run this script directly by typing :
# curl -L https://github.com/ippontech/tatami/raw/master/etc/installation/ubuntu/uninstall.sh | sudo bash
#
# - Deletes the "/opt/tatami"
# - Deletes the "tatami" user

echo "Tatami uninstaller"

mv /etc/security/limits.conf.original /etc/security/limits.conf

userdel -f -r tatami

echo "Delete Tatami directory"
rm -rf /opt/tatami

================================================
FILE: etc/installation/ubuntu/update.sh
================================================
#!/bin/sh
#
# description: Updates Tatami from Git
# This script must be run by the "tatami" user, who must be a sudoer.
echo "Welcome to the Tatami updater"

#################################
# Variables
#################################
echo "Setting up variables"
export USER=tatami
export TATAMI_DIR=/opt/tatami

#################################
# Update application
#################################
cd $TATAMI_DIR/application/tatami
git pull
cd /opt/tatami/application/tatami && mvn -Pprod -DskipTests clean package
sudo /etc/init.d/jetty stop
sudo cp /opt/tatami/application/tatami/target/root.war /opt/jetty/webapps/root.war
sudo /etc/init.d/jetty start


================================================
FILE: jenkinsScripts/insertGoogleAuthKeys.sh
================================================
#!/bin/bash

#Insert google auth variables into the build. 
googleKey=$1
googleSecret=$2
newServer=$3


usage='startTatami <googleKey> <googleSecret> <serverURL>'

if [ "$#" -ne 3 ]; then
	echo "Need 3 paremeters"
        echo "$usage"
        exit 1
fi


replaceKey='${tatami.google.clientId}'
replaceSecret='${tatami.google.clientSecret}'
oldServer="<tatami.url>http:\/\/localhost:8080<\/tatami.url>"

find ../src -name *security.xml | xargs sed -i "s/$replaceSecret/$googleSecret/g" 
find ../src -name *security.xml | xargs sed -i "s/$replaceKey/$googleKey/g" 
sed -i "s/$oldServer/$newServer/g" ../pom.xml




================================================
FILE: jenkinsScripts/restoreDatabase.sh
================================================
#!/bin/bash

rm -rf ../target/cassandra || true
rm -rf ./target/elasticsearch || true

tar -zxvf save.tar.gz -C ../target/
tar -zxvf db.tar.gz -C ./target/

rm -f save.tar.gz || true


================================================
FILE: jenkinsScripts/saveDatabase.sh
================================================
#!/bin/bash

tar -zcvf save.tar.gz ../target/cassandra ../target/elasticsearch
tar -zcvf db.tar.gz ./target/elasticsearch


================================================
FILE: jenkinsScripts/startTatami.sh
================================================
#!/bin/bash

#Insert google Authentication keys.
./insertGoogleAuthKeys.sh $1 $2 $3

if [ $? -ne 0 ]; then
    exit 1
fi

#Start cassandra
mvn -f ../pom.xml cassandra:run 2> cassandra.error >cassandra.log &
echo "$!" >tatamiPID

#start jetty
mvn -f ../pom.xml jetty:run 2> jetty.error >jetty.log &
echo "$!" >> tatamiPID



================================================
FILE: jenkinsScripts/stopTatami.sh
================================================
#!/bin/bash
cat tatamiPID | xargs kill || true
rm tatamiPID || true


================================================
FILE: mobile/.bowerrc
================================================
{
  "directory": "www/lib"
}


================================================
FILE: mobile/.editorconfig
================================================
# http://editorconfig.org
root = true

[*]
charset = utf-8
indent_style = space
indent_size = 4
end_of_line = lf
insert_final_newline = true
trim_trailing_whitespace = true

[*.md]
insert_final_newline = false
trim_trailing_whitespace = false

================================================
FILE: mobile/.gitignore
================================================
# Specifies intentionally untracked files to ignore when using Git
# http://git-scm.com/docs/gitignore

www/lib/
node_modules/
platforms/
plugins/


================================================
FILE: mobile/README.md
================================================
Tatami Mobile Beta
==================

If interested in the mobile beta, follow these steps:

Prepare Project
---------------

- Clone, fork or download the source code from this Github page
- Install [Maven](http://maven.apache.org/)
- Install [Ionic](http://ionicframework.com/)
    - `npm install -g cordova ionic`
- Point your terminal to the directory you cloned Tatami to.
    - `cd mobile`
- Run Maven : `mvn -Pmobile-prod install`

Deploy to Device
----------------

### iOS
- Open Xcode
- Open `tatami/mobile/platforms/ios/Tatami.xcodeproj`
- Connect device
- Click play on top left


### Android

- Connect device
- Run the following command
    - `ionic build android && ionic run android`



================================================
FILE: mobile/bower.json
================================================
{
  "name": "tatami",
  "private": "true",
  "devDependencies": {
    "ionic": "~1.2.4",
    "angular-mocks": "1.4.3",
    "angular-marked": "~1.0.1",
    "angular-animate": "~1.5.3",
    "angular-sanitize": "~1.5.3",
    "angular-resource": "~1.5.3",
    "ngCordova": "~0.1.24-alpha",
    "angular-translate": "~2.11.0",
    "angular-translate-interpolation-messageformat": "~2.11.0",
    "angular-translate-loader-partial": "~2.11.0",
    "messageformat": "~0.3.1"
  },
  "resolutions": {
    "angular-sanitize": "~1.5.3",
    "angular-animate": "~1.5.3",
    "ionic-toast": "v0.2.0"
  },
  "dependencies": {
    "ionic-toast": "^0.4.1"
  }
}


================================================
FILE: mobile/config.xml
================================================
<?xml version="1.0" encoding="UTF-8" standalone="yes"?>
<widget id="com.ippon.tatami.mobile" version="1.0.1" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
  <name>Tatami</name>
  <description>
        The Tatami mobile app is designed to access the Tatami API, and it is an open source, enterprise social media platform.
    </description>
  <author email="tatami-dev@ippon.fr">
      Ippon Technology, Inc
    </author>
  <content src="index.html"/>
  <access origin="*"/>
  <preference name="webviewbounce" value="false"/>
  <preference name="UIWebViewBounce" value="false"/>
  <preference name="DisallowOverscroll" value="true"/>
  <preference name="android-minSdkVersion" value="16"/>
  <preference name="BackupWebStorage" value="none"/>
  <preference name="SplashScreen" value="screen"/>
  <preference name="SplashScreenDelay" value="3000"/>
  <feature name="StatusBar">
    <param name="ios-package" value="CDVStatusBar" onload="true"/>
  </feature>
  <platform name="ios">
    <icon src="resources/ios/icon/icon.png" width="57" height="57"/>
    <icon src="resources/ios/icon/icon@2x.png" width="114" height="114"/>
    <icon src="resources/ios/icon/icon-40.png" width="40" height="40"/>
    <icon src="resources/ios/icon/icon-40@2x.png" width="80" height="80"/>
    <icon src="resources/ios/icon/icon-50.png" width="50" height="50"/>
    <icon src="resources/ios/icon/icon-50@2x.png" width="100" height="100"/>
    <icon src="resources/ios/icon/icon-60.png" width="60" height="60"/>
    <icon src="resources/ios/icon/icon-60@2x.png" width="120" height="120"/>
    <icon src="resources/ios/icon/icon-60@3x.png" width="180" height="180"/>
    <icon src="resources/ios/icon/icon-72.png" width="72" height="72"/>
    <icon src="resources/ios/icon/icon-72@2x.png" width="144" height="144"/>
    <icon src="resources/ios/icon/icon-76.png" width="76" height="76"/>
    <icon src="resources/ios/icon/icon-76@2x.png" width="152" height="152"/>
    <icon src="resources/ios/icon/icon-small.png" width="29" height="29"/>
    <icon src="resources/ios/icon/icon-small@2x.png" width="58" height="58"/>
    <icon src="resources/ios/icon/icon-small@3x.png" width="87" height="87"/>
    <splash src="resources/ios/splash/Default-568h@2x~iphone.png" width="640" height="1136"/>
    <splash src="resources/ios/splash/Default-667h.png" width="750" height="1334"/>
    <splash src="resources/ios/splash/Default-736h.png" width="1242" height="2208"/>
    <splash src="resources/ios/splash/Default-Landscape-736h.png" width="2208" height="1242"/>
    <splash src="resources/ios/splash/Default-Landscape@2x~ipad.png" width="2048" height="1536"/>
    <splash src="resources/ios/splash/Default-Landscape~ipad.png" width="1024" height="768"/>
    <splash src="resources/ios/splash/Default-Portrait@2x~ipad.png" width="1536" height="2048"/>
    <splash src="resources/ios/splash/Default-Portrait~ipad.png" width="768" height="1024"/>
    <splash src="resources/ios/splash/Default@2x~iphone.png" width="640" height="960"/>
    <splash src="resources/ios/splash/Default~iphone.png" width="320" height="480"/>
  </platform>
  <platform name="android">
    <icon src="resources/android/icon/drawable-ldpi-icon.png" density="ldpi"/>
    <icon src="resources/android/icon/drawable-mdpi-icon.png" density="mdpi"/>
    <icon src="resources/android/icon/drawable-hdpi-icon.png" density="hdpi"/>
    <icon src="resources/android/icon/drawable-xhdpi-icon.png" density="xhdpi"/>
    <icon src="resources/android/icon/drawable-xxhdpi-icon.png" density="xxhdpi"/>
    <icon src="resources/android/icon/drawable-xxxhdpi-icon.png" density="xxxhdpi"/>
    <splash src="resources/android/splash/drawable-land-ldpi-screen.png" density="land-ldpi"/>
    <splash src="resources/android/splash/drawable-land-mdpi-screen.png" density="land-mdpi"/>
    <splash src="resources/android/splash/drawable-land-hdpi-screen.png" density="land-hdpi"/>
    <splash src="resources/android/splash/drawable-land-xhdpi-screen.png" density="land-xhdpi"/>
    <splash src="resources/android/splash/drawable-land-xxhdpi-screen.png" density="land-xxhdpi"/>
    <splash src="resources/android/splash/drawable-land-xxxhdpi-screen.png" density="land-xxxhdpi"/>
    <splash src="resources/android/splash/drawable-port-ldpi-screen.png" density="port-ldpi"/>
    <splash src="resources/android/splash/drawable-port-mdpi-screen.png" density="port-mdpi"/>
    <splash src="resources/android/splash/drawable-port-hdpi-screen.png" density="port-hdpi"/>
    <splash src="resources/android/splash/drawable-port-xhdpi-screen.png" density="port-xhdpi"/>
    <splash src="resources/android/splash/drawable-port-xxhdpi-screen.png" density="port-xxhdpi"/>
    <splash src="resources/android/splash/drawable-port-xxxhdpi-screen.png" density="port-xxxhdpi"/>
  </platform>
  <icon src="resources/android/icon/drawable-xhdpi-icon.png"/>
</widget>


================================================
FILE: mobile/gulpfile.js
================================================
var gulp = require('gulp');
var gutil = require('gulp-util');
var bower = require('bower');
var concat = require('gulp-concat');
var sass = require('gulp-sass');
var minifyCss = require('gulp-minify-css');
var rename = require('gulp-rename');
var sh = require('shelljs');
var replace = require('replace');

var paths = {
    sass: ['./scss/**/*.scss'],
    css: ['./www/css/*.css']
};

gulp.task('default', ['sass', 'css']);

gulp.task('sass', function(done) {
  gulp.src('./scss/ionic.app.scss')
    .pipe(sass())
    .on('error', sass.logError)
    .pipe(gulp.dest('./www/css/'))
    .pipe(minifyCss({
      keepSpecialComments: 0
    }))
    .pipe(rename({ extname: '.min.css' }))
    .pipe(gulp.dest('./www/css/'))
    .on('end', done);
});

gulp.task('css', function(done) {
    gulp.src('./www/css/style.css')
        .pipe(minifyCss({
            keepSpecialComments: 0
        }))
        .pipe(rename({ extname: '.min.css' }))
        .pipe(gulp.dest('./www/css/'))
        .on('end', done);
});

gulp.task('watch', function() {
    gulp.watch(paths.sass, ['sass']);
    gulp.watch(paths.css, ['css']);
});

gulp.task('install', ['git-check'], function() {
  return bower.commands.install()
    .on('log', function(data) {
      gutil.log('bower', gutil.colors.cyan(data.id), data.message);
    });
});

gulp.task('git-check', function(done) {
  if (!sh.which('git')) {
    console.log(
      '  ' + gutil.colors.red('Git is not installed.'),
      '\n  Git, the version control system, is required to download Ionic.',
      '\n  Download git here:', gutil.colors.cyan('http://git-scm.com/downloads') + '.',
      '\n  Once git is installed, run \'' + gutil.colors.cyan('gulp install') + '\' again.'
    );
    process.exit(1);
  }
  done();
});

var replaceFiles = ['./www/app/tatami.endpoint.js'];

gulp.task('dev', function() {
    return replace({
        regex: 'http://tatami.ippon.fr|http://10.1.10.202:8100',
        replacement: 'http://localhost:8100',
        paths: replaceFiles,
        recursive: false,
        silent: false
    });
});

gulp.task('device-dev', function() {
    return replace({
        regex: 'http://localhost:8100|http://tatami.ippon.fr',
        replacement: 'http://10.1.10.202:8100',
        paths: replaceFiles,
        recursive: false,
        silent: false
    });
});

gulp.task('prod', function() {
    return replace({
        regex: 'http://localhost:8100|http://10.1.10.202:8100',
        replacement: 'http://tatami.ippon.fr',
        paths: replaceFiles,
        recursive: false,
        silent: false
    });
});


================================================
FILE: mobile/hooks/README.md
================================================
<!--
#
# Licensed to the Apache Software Foundation (ASF) under one
# or more contributor license agreements.  See the NOTICE file
# distributed with this work for additional information
# regarding copyright ownership.  The ASF licenses this file
# to you under the Apache License, Version 2.0 (the
# "License"); you may not use this file except in compliance
# with the License.  You may obtain a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing,
# software distributed under the License is distributed on an
# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
#  KIND, either express or implied.  See the License for the
# specific language governing permissions and limitations
# under the License.
#
-->
# Cordova Hooks

This directory may contain scripts used to customize cordova commands. This
directory used to exist at `.cordova/hooks`, but has now been moved to the
project root. Any scripts you add to these directories will be executed before
and after the commands corresponding to the directory name. Useful for
integrating your own build systems or integrating with version control systems.

__Remember__: Make your scripts executable.

## Hook Directories
The following subdirectories will be used for hooks:

    after_build/
    after_compile/
    after_docs/
    after_emulate/
    after_platform_add/
    after_platform_rm/
    after_platform_ls/
    after_plugin_add/
    after_plugin_ls/
    after_plugin_rm/
    after_plugin_search/
    after_prepare/
    after_run/
    after_serve/
    before_build/
    before_compile/
    before_docs/
    before_emulate/
    before_platform_add/
    before_platform_rm/
    before_platform_ls/
    before_plugin_add/
    before_plugin_ls/
    before_plugin_rm/
    before_plugin_search/
    before_prepare/
    before_run/
    before_serve/
    pre_package/ <-- Windows 8 and Windows Phone only.

## Script Interface

All scripts are run from the project's root directory and have the root directory passes as the first argument. All other options are passed to the script using environment variables:

* CORDOVA_VERSION - The version of the Cordova-CLI.
* CORDOVA_PLATFORMS - Comma separated list of platforms that the command applies to (e.g.: android, ios).
* CORDOVA_PLUGINS - Comma separated list of plugin IDs that the command applies to (e.g.: org.apache.cordova.file, org.apache.cordova.file-transfer)
* CORDOVA_HOOK - Path to the hook that is being executed.
* CORDOVA_CMDLINE - The exact command-line arguments passed to cordova (e.g.: cordova run ios --emulate)

If a script returns a non-zero exit code, then the parent cordova command will be aborted.


## Writing hooks

We highly recommend writting your hooks using Node.js so that they are
cross-platform. Some good examples are shown here:

[http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/](http://devgirl.org/2013/11/12/three-hooks-your-cordovaphonegap-project-needs/)



================================================
FILE: mobile/hooks/after_prepare/010_add_platform_class.js
================================================
#!/usr/bin/env node

// Add Platform Class
// v1.0
// Automatically adds the platform class to the body tag
// after the `prepare` command. By placing the platform CSS classes
// directly in the HTML built for the platform, it speeds up
// rendering the correct layout/style for the specific platform
// instead of waiting for the JS to figure out the correct classes.

var fs = require('fs');
var path = require('path');

var rootdir = process.argv[2];

function addPlatformBodyTag(indexPath, platform) {
  // add the platform class to the body tag
  try {
    var platformClass = 'platform-' + platform;
    var cordovaClass = 'platform-cordova platform-webview';

    var html = fs.readFileSync(indexPath, 'utf8');

    var bodyTag = findBodyTag(html);
    if(!bodyTag) return; // no opening body tag, something's wrong

    if(bodyTag.indexOf(platformClass) > -1) return; // already added

    var newBodyTag = bodyTag;

    var classAttr = findClassAttr(bodyTag);
    if(classAttr) {
      // body tag has existing class attribute, add the classname
      var endingQuote = classAttr.substring(classAttr.length-1);
      var newClassAttr = classAttr.substring(0, classAttr.length-1);
      newClassAttr += ' ' + platformClass + ' ' + cordovaClass + endingQuote;
      newBodyTag = bodyTag.replace(classAttr, newClassAttr);

    } else {
      // add class attribute to the body tag
      newBodyTag = bodyTag.replace('>', ' class="' + platformClass + ' ' + cordovaClass + '">');
    }

    html = html.replace(bodyTag, newBodyTag);

    fs.writeFileSync(indexPath, html, 'utf8');

    process.stdout.write('add to body class: ' + platformClass + '\n');
  } catch(e) {
    process.stdout.write(e);
  }
}

function findBodyTag(html) {
  // get the body tag
  try{
    return html.match(/<body(?=[\s>])(.*?)>/gi)[0];
  }catch(e){}
}

function findClassAttr(bodyTag) {
  // get the body tag's class attribute
  try{
    return bodyTag.match(/ class=["|'](.*?)["|']/gi)[0];
  }catch(e){}
}

if (rootdir) {

  // go through each of the platform directories that have been prepared
  var platforms = (process.env.CORDOVA_PLATFORMS ? process.env.CORDOVA_PLATFORMS.split(',') : []);

  for(var x=0; x<platforms.length; x++) {
    // open up the index.html file at the www root
    try {
      var platform = platforms[x].trim().toLowerCase();
      var indexPath;

      if(platform == 'android') {
        indexPath = path.join('platforms', platform, 'assets', 'www', 'index.html');
      } else {
        indexPath = path.join('platforms', platform, 'www', 'index.html');
      }

      if(fs.existsSync(indexPath)) {
        addPlatformBodyTag(indexPath, platform);
      }

    } catch(e) {
      process.stdout.write(e);
    }
  }

}


================================================
FILE: mobile/ionic.project
================================================
{
    "name": "mobile",
    "app_id": "",
    "proxies": [
        {
            "path": "/tatami",
            "proxyUrl": "http://localhost:8080/tatami"
        },
        {
            "path": "/assets",
            "proxyUrl": "http://localhost:8080/assets"
        }
  ],
  "gulpStartupTasks": [
    "sass",
    "watch"
  ],
  "watchPatterns": [
    "www/**/*",
    "!www/lib/**/*"
  ]
}


================================================
FILE: mobile/karma.ci.conf.js
================================================
// Karma configuration
// Generated on Wed May 06 2015 15:23:11 GMT-0400 (EDT)

module.exports = function (config) {
    config.set({

        // base path that will be used to resolve all patterns (eg. files, exclude)
        basePath: '',


        // frameworks to use
        // available frameworks: https://npmjs.org/browse/keyword/karma-adapter
        frameworks: ['jasmine'],

        // list of files / patterns to load in the browser
        files: [
            "www/lib/ionic/release/js/ionic.bundle.js",
            "www/lib/ionic/js/angular/angular-resource.js",
            "www/lib/angular-mocks/angular-mocks.js",
            "www/test/javascript/**/*.js"
        ],


        // list of files to exclude
        exclude: [
            '**/*.swp'
        ],


        // preprocess matching files before serving them to the browser
        // available preprocessors: https://npmjs.org/browse/keyword/karma-preprocessor
        preprocessors: {
            'src/**/*.js': ['coverage']
        },


        // test results reporter to use
        // possible values: 'dots', 'progress'
        // available reporters: https://npmjs.org/browse/keyword/karma-reporter
        reporters: ['dots', 'jenkins', 'coverage', 'progress'],

        jenkinsReporter: {
            outputFile: 'target/test-results/karma/TESTS-resuts.xml'
        },

        coverageReporter: {
            dir: 'target/test-results/coverage',

            reporters: [
                {type: 'lcov', subdir: 'report-lcov'}
            ]
        },

        // web server port
        port: 9876,


        // enable / disable colors in the output (reporters and logs)
        colors: true,


        // level of logging
        // possible values: config.LOG_DISABLE || config.LOG_ERROR || config.LOG_WARN || config.LOG_INFO || config.LOG_DEBUG
        logLevel: config.LOG_INFO,


        // enable / disable watching file and executing tests whenever any file changes
        autoWatch: false,


        // start these browsers
        // available browser launchers: https://npmjs.org/browse/keyword/karma-launcher
        browsers: ['PhantomJS'],


        // Continuous Integration mode
        // if true, Karma captures browsers, runs the tests and exits
        singleRun: true
    });
};


================================================
FILE: mobile/package.json
================================================
{
  "name": "mobile",
  "version": "1.1.1",
  "description": "mobile: An Ionic project",
  "dependencies": {
    "gulp": "^3.5.6",
    "gulp-concat": "^2.2.0",
    "gulp-minify-css": "^0.3.0",
    "gulp-rename": "^1.2.0",
    "gulp-sass": "^2.0.4",
    "replace": "^0.3.0"
  },
  "devDependencies": {
    "bower": "^1.3.3",
    "gulp-util": "^2.2.14",
    "karma": "^0.13.19",
    "karma-jasmine": "^0.3.6",
    "jasmine-core": "^2.3.4",
    "karma-chrome-launcher": "^0.2.0",
    "karma-cli": "^0.1.1",
    "karma-coverage": "^0.5.2",
    "karma-firefox-launcher": "^0.1.6",
    "karma-ie-launcher": "^0.2.0",
    "karma-jenkins-reporter": "0.0.2",
    "karma-jshint": "^0.1.0",
    "karma-junit-reporter": "^0.3.6",
    "karma-phantomjs-launcher": "^0.2.1",
    "karma-safari-launcher": "^0.1.1",
    "phantomjs": "^1.9.18",
    "shelljs": "^0.3.0"
  },
  "cordovaPlugins": [
    "cordova-plugin-device",
    "cordova-plugin-console",
    "cordova-plugin-splashscreen",
    "cordova-plugin-statusbar",
    "ionic-plugin-keyboard",
    "cordova-plugin-inappbrowser",
    "cordova-plugin-camera",
    {
      "locator": "https://github.com/apache/cordova-plugin-whitelist.git",
      "id": "cordova-plugin-whitelist"
    },
    "cordova-plugin-file-transfer"
  ],
  "cordovaPlatforms": [
    "android",
    "ios"
  ]
}


================================================
FILE: mobile/pom.xml
================================================
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
         xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
    <parent>
        <artifactId>tatami</artifactId>
        <groupId>fr.ippon.tatami</groupId>
        <version>4.0.5</version>
    </parent>

    <modelVersion>4.0.0</modelVersion>
    <artifactId>mobile</artifactId>

    <dependencies>
        <dependency>
            <groupId>fr.ippon.tatami</groupId>
            <artifactId>services</artifactId>
            <version>4.0.5</version>
        </dependency>
        <dependency>
            <groupId>fr.ippon.tatami</groupId>
            <artifactId>services</artifactId>
            <version>4.0.5</version>
            <type>test-jar</type>
            <scope>test</scope>
        </dependency>
    </dependencies>

    <profiles>
        <profile>
            <id>dev</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <version>1.2.1</version>
                        <executions>
                            <execution>
                                <id>gulp</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>${project.npm.bin}/gulp</executable>
                                    <arguments>
                                        <argument>dev</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                            <execution>
                                <id>ionic</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>ionic</executable>
                                    <arguments>
                                        <argument>serve</argument>
                                        <argument>-l</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>

        </profile>
        <profile>
            <id>device-dev</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <version>1.2.1</version>
                        <executions>
                            <execution>
                                <phase>install</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>${project.npm.bin}/gulp</executable>
                                    <arguments>
                                        <argument>device-dev</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                        </executions>
                    </plugin>
                </plugins>
            </build>

        </profile>

        <profile>
            <id>mobile-prod</id>
            <build>
                <plugins>
                    <plugin>
                        <groupId>org.codehaus.mojo</groupId>
                        <artifactId>exec-maven-plugin</artifactId>
                        <version>1.2.1</version>
                        <executions>
                            <execution>
                                <id>gulp</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>${project.npm.bin}/gulp</executable>
                                    <arguments>
                                        <argument>prod</argument>
                                    </arguments>
                                </configuration>
                            </execution>
                            <execution>
                                <id>ionic</id>
                                <phase>install</phase>
                                <goals>
                                    <goal>exec</goal>
                                </goals>
                                <configuration>
                                    <executable>ionic</executable>
                                    <arguments>
                                        <argument>build</argument>
                                    </arguments>
                                </configuration>
                            </execution>

                        </executions>
                    </plugin>
                </plugins>

            </build>

        </profile>
    </profiles>

    <build>
        <finalName>tatami-mobile-${project.version}</finalName>
        <plugins>
	<plugin>
                <artifactId>maven-clean-plugin</artifactId>
                <version>2.6.1</version>
                <configuration>
                    <filesets>
                        <fileset>
                            <directory>${project.basedir}/node_modules/</directory>
                            <followSymlinks>false</followSymlinks>
                        </fileset>
                    </filesets>
                </configuration>
            </plugin>        
	<plugin>
		<groupId>org.codehaus.mojo</groupId>
		<artifactId>exec-maven-plugin</artifactId>
		<version>1.2.1</version>
		<executions>
			<execution>
				<id>install-npm-mobile-dependencies</id>
				<phase>generate-sources</phase>
				<configuration>
					<executable>npm</executable>
					<arguments>
						<argument>install</argument>
					</arguments>
				</configuration>
				<goals>
					<goal>exec</goal>
				</goals>
			</execution>
		</executions>
	</plugin>    
	<plugin>
                <groupId>com.kelveden</groupId>
                <artifactId>maven-karma-plugin</artifactId>
                <version>1.6</version>
                <executions>
                    <execution>
                        <phase>test</phase>
                        <goals>
                            <goal>start</goal>
                        </goals>
                    </execution>
                </executions>
                <configuration>
                    <karmaExecutable>${project.basedir}/node_modules/.bin/karma</karmaExecutable>
                    <configFile>${project.basedir}/karma.ci.conf.js</configFile>
                </configuration>
            </plugin>

        </plugins>
    </build>
</project>


================================================
FILE: mobile/scss/ionic.app.scss
================================================
/*
To customize the look and feel of Ionic, you can override the variables
in ionic's _variables.scss file.

For example, you might change some of the default colors:

$light:                           #fff !default;
$stable:                          #f8f8f8 !default;
$positive:                        #387ef5 !default;
$calm:                            #11c1f3 !default;
$balanced:                        #33cd5f !default;
$energized:                       #ffc900 !default;
$assertive:                       #ef473a !default;
$royal:                           #886aea !default;
$dark:                            #444 !default;
*/

// The path for our ionicons font files, relative to the built CSS in www/css
$ionicons-font-path: "../lib/ionic/release/fonts" !default;

// Include all of Ionic
@import "../www/lib/ionic/release/css/ionic";

.platform-ios {
    .tatami-location {
        @extend .ion-ios-location;
    }
}

.platform-android {
    .tatami-location {
        @extend .ion-android-locate;
    }
}

.item-image i:last-child {
    position: absolute;
    border-radius: 50%;
    width: 20px;
    height: 20px;
    background-color: black;
    top: 15px;
    right: 15px;
}

.link-span {
    cursor: pointer;
    color: #387ef5;
}

.center {
    margin-left: auto;
    margin-right: auto;
    display: block;
}

p ul {
    list-style-type: disc !important;
    list-style-position: inside !important;
}

//#list ul {
//    margin-top: 30px;
//}
//#list ul li {
//    text-align: left;
//    list-style: disc;
//    margin: 10px 0px;
//}


================================================
FILE: mobile/www/app/components/follow/follow.html
================================================
<ion-view>
    <ion-tabs class="tabs-icon-top tabs-color-active-positive">

        <ion-tab title="{{ 'tab.suggested.title' | translate }}" icon-off="ion-ios-personadd-outline" icon-on="ion-ios-personadd" ui-sref="suggested">
            <ion-nav-view name="suggested"></ion-nav-view>
        </ion-tab>

        <ion-tab title="{{ 'tab.following' | translate }}" icon-off="ion-ios-people-outline" icon-on="ion-ios-people" ui-sref="following">
            <ion-nav-view name="following"></ion-nav-view>
        </ion-tab>

        <ion-tab title="{{ 'tab.follower' | translate }}" icon-off="ion-person-stalker" icon-on="ion-person-stalker" ui-sref="follower">
            <ion-nav-view name="follower"></ion-nav-view>
        </ion-tab>

    </ion-tabs>
</ion-view>


================================================
FILE: mobile/www/app/components/follow/follow.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(followConfig);

    followConfig.$inject = ['$stateProvider'];
    function followConfig($stateProvider) {
        $stateProvider
            .state('follow', {
                url: '/follow',
                parent: 'tatami',
                abstract: true,
                templateUrl: 'app/components/follow/follow.html',
                resolve: {
                    currentUser: getCurrentUser,
                    translatePartialLoader: getTranslatePartialLoader
                }
            });

        getCurrentUser.$inject = ['ProfileService'];
        function  getCurrentUser(ProfileService) {
            return ProfileService.get().$promise;
        }

        getTranslatePartialLoader.$inject = ['$translate', '$translatePartialLoader'];
        function getTranslatePartialLoader($translate, $translatePartialLoader) {
            $translatePartialLoader.addPart('follow');
            return $translate.refresh();
        }
    }
})();


================================================
FILE: mobile/www/app/components/follow/follower/follower.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('FollowerCtrl', followerCtrl);

    followerCtrl.$inject = ['followers', 'TatamiUserRefresherService', 'currentUser'];
    function followerCtrl(followers, TatamiUserRefresherService, currentUser) {
        var vm = this;
        vm.followers = followers;
        vm.getNewFollowers = getNewFollowers;

        function getNewFollowers() {
            TatamiUserRefresherService.refreshFollowers(currentUser).then(setUsers);
        }

        setUsers.$inject = ['followers'];
        function setUsers(followers) {
            vm.followers = followers;
        }
    }
})();


================================================
FILE: mobile/www/app/components/follow/follower/follower.html
================================================
<ion-view view-title="{{ 'tab.follower' | translate }}">
    <ion-content class="tatami-header tatami-footer" ng-style="{'background-color':'#f5f5f5'}">
        <ion-refresher on-refresh="vm.getNewFollowers()"></ion-refresher>
        <ion-list>
            <div ng-repeat="user in vm.followers">
                <tatami-user user="user"></tatami-user>
            </div>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/follow/follower/follower.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('follower', {
                url: '/follower',
                parent: 'follow',
                views: {
                    'follower': {
                        templateUrl: 'app/components/follow/follower/follower.html',
                        controller: 'FollowerCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    followers: followers
                }
            });
    }

    followers.$inject = ['UserService', 'currentUser'];
    function followers(UserService, currentUser) {
        return UserService.getFollowers({ username: currentUser.username }).$promise;
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('follower', 'follow');
        TatamiState.addConversationState('follower', 'follow');
        TatamiState.addTagState('follower', 'follow');
    }
})();


================================================
FILE: mobile/www/app/components/follow/following/following.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('FollowingCtrl', FollowingCtrl);

    FollowingCtrl.$inject = ['following', 'TatamiUserRefresherService', 'currentUser'];

    function FollowingCtrl(following, TatamiUserRefresherService, currentUser) {
        var vm = this;
        vm.following = following;
        vm.getNewFollowing = getNewFollowing;

        function getNewFollowing() {
            TatamiUserRefresherService.refreshFollowing(currentUser).then(setUsers);
        }

        setUsers.$inject = ['following'];
        function setUsers(following) {
            vm.following = following;
        }
    }

})();



================================================
FILE: mobile/www/app/components/follow/following/following.html
================================================
<ion-view view-title="{{ 'tab.following' | translate }}">
    <ion-content class="tatami-header tatami-footer" ng-style="{'background-color':'#f5f5f5'}">
        <ion-refresher on-refresh="vm.getNewFollowing()"></ion-refresher>
        <ion-list>
            <div ng-repeat="user in vm.following">
                <tatami-user user="user"></tatami-user>
            </div>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/follow/following/following.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('following', {
                url: '/following',
                parent: 'follow',
                views: {
                    'following': {
                        templateUrl: 'app/components/follow/following/following.html',
                        controller: 'FollowingCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    following: getFollowing
                }
            });
    }

    getFollowing.$inject = ['UserService', 'currentUser'];
    function getFollowing(UserService, currentUser) {
        return UserService.getFollowing({ username: currentUser.username }).$promise;
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('following', 'follow');
        TatamiState.addConversationState('following', 'follow');
        TatamiState.addTagState('following', 'follow');
    }
})();


================================================
FILE: mobile/www/app/components/follow/suggested/suggested.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('SuggestedCtrl', suggestedCtrl);

    suggestedCtrl.$inject = ['suggested', 'TatamiUserRefresherService'];
    function suggestedCtrl(suggested, TatamiUserRefresherService) {
        var vm = this;

        vm.suggested = suggested;

        vm.getNewSuggested = getNewSuggested;

        function getNewSuggested() {
            TatamiUserRefresherService.refreshSuggested().$promise.then(updateUsers);
        }

        updateUsers.$inject = ['suggested'];
        function updateUsers(suggested) {
            vm.suggested = suggested;
        }
    }
})();



================================================
FILE: mobile/www/app/components/follow/suggested/suggested.html
================================================
<ion-view view-title="{{ 'tab.suggested.who' | translate }}">
    <ion-content class="tatami-header tatami-footer" ng-style="{'background-color':'#f5f5f5'}">
        <ion-refresher on-refresh="vm.getNewSuggested()"></ion-refresher>
        <ion-list>
            <div ng-repeat="user in vm.suggested">
                <tatami-user user="user"></tatami-user>
            </div>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/follow/suggested/suggested.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('suggested', {
                url: '/suggested',
                parent: 'follow',
                views: {
                    'suggested': {
                        templateUrl: 'app/components/follow/suggested/suggested.html',
                        controller: 'SuggestedCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    suggested: getSuggested
                }
            });
    }

    getSuggested.$inject = ['UserService'];
    function getSuggested(UserService) {
        return UserService.getSuggestions().$promise;
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('suggested', 'follow');
        TatamiState.addConversationState('suggested', 'follow');
        TatamiState.addTagState('suggested', 'follow');
    }
})();


================================================
FILE: mobile/www/app/components/home/favorites/favorites.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('FavoritesCtrl', favoritesCtrl);

    favoritesCtrl.$inject = ['favorites', 'currentUser', 'TatamiStatusRefresherService', '$q'];
    function favoritesCtrl(favorites, currentUser, TatamiStatusRefresherService, $q) {
        var vm = this;
        vm.favorites = favorites;
        vm.currentUser = currentUser;
        vm.getNewStatuses = getNewStatuses;
        vm.getEmpty = getEmpty;

        function getNewStatuses() {
            return TatamiStatusRefresherService.refreshFavorites();
        }

        getEmpty.$inject = ['finalStatus'];
        function getEmpty(finalStatus) {
            var deferred = $q.defer();
            deferred.resolve([]);
            return deferred.promise;
        }
    }
})();


================================================
FILE: mobile/www/app/components/home/favorites/favorites.html
================================================
<ion-view view-title="{{ 'tab.favorites' | translate }}" ng-style="{'background-color':'#f5f5f5'}">
    <tatami-status-list statuses="vm.favorites"
                        current-user="vm.currentUser"
                        tatami-refresher="vm.getNewStatuses()"
                        tatami-infinite-refresher="vm.getEmpty(finalStatus)"></tatami-status-list>
</ion-view>


================================================
FILE: mobile/www/app/components/home/favorites/favorites.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('favorites', {
                url: '/favorites',
                parent: 'home',
                views: {
                    'favorites': {
                        templateUrl: 'app/components/home/favorites/favorites.html',
                        controller: 'FavoritesCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    favorites: favorites
                }
            });

        favorites.$inject = ['HomeService'];
        function favorites(HomeService) {
            return HomeService.getFavorites().$promise;
        }
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('favorites', 'home');
        TatamiState.addConversationState('favorites', 'home');
        TatamiState.addTagState('favorites', 'home');
    }
})();


================================================
FILE: mobile/www/app/components/home/home.html
================================================
<ion-tabs class="tabs-icon-top tabs-color-active-positive">
    <!-- Dashboard Tab -->
    <ion-tab title="{{ 'tab.timeline' | translate }}"
             icon-off="ion-ios-list-outline"
             icon-on="ion-ios-list"
             ui-sref="timeline">
        <ion-nav-view name="timeline"></ion-nav-view>
    </ion-tab>

    <!-- Chats Tab -->
    <ion-tab title="{{ 'tab.mentions' | translate }}"
             icon-off="ion-ios-chatbubble-outline"
             icon-on="ion-ios-chatbubble"
             ui-sref="mentions">
        <ion-nav-view name="mentions"></ion-nav-view>
    </ion-tab>

    <!-- Account Tab -->
    <ion-tab title="{{ 'tab.favorites' | translate }}"
             icon-off="ion-android-star-outline"
             icon-on="ion-android-star"
             ui-sref="favorites">
        <ion-nav-view name="favorites"></ion-nav-view>
    </ion-tab>

    <ion-tab title="{{ 'tab.more' | translate }}"
             icon-off="ion-navicon-round"
             icon-on="ion-navicon-round"
             ui-sref="more">
        <ion-nav-view name="more"></ion-nav-view>
    </ion-tab>

</ion-tabs>


================================================
FILE: mobile/www/app/components/home/home.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(homeConfig);

    homeConfig.$inject = ['$stateProvider'];
    function homeConfig($stateProvider) {
        $stateProvider
            .state('home', {
                parent: 'tatami',
                abstract: true,
                url: '/home',
                templateUrl: 'app/components/home/home.html',
                resolve: {
                    currentUser: getCurrentUser,
                    translatePartialLoader: getTranslatePartialLoader
                }
            })
    }

    getCurrentUser.$inject = ['ProfileService'];
    function getCurrentUser(ProfileService) {
        return ProfileService.get().$promise.then(function(currentUser) {
            console.log(currentUser);
            return currentUser;
        });
    }

    getTranslatePartialLoader.$inject = ['$translate', '$translatePartialLoader'];
    function getTranslatePartialLoader($translate, $translatePartialLoader) {
        $translatePartialLoader.addPart('home');
        return $translate.refresh();
    }
})();


================================================
FILE: mobile/www/app/components/home/mentions/mentions.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('MentionsCtrl', mentionsCtrl);

    mentionsCtrl.$inject = ['mentioned', 'currentUser', 'TatamiStatusRefresherService'];
    function mentionsCtrl(mentioned, currentUser, TatamiStatusRefresherService) {
        var vm = this;
        vm.mentioned = mentioned;
        vm.currentUser = currentUser;

        vm.remove = remove;
        vm.getNewStatuses = getNewStatuses;
        vm.getOldStatuses = getOldStatuses;

        remove.$inject = ['mention'];
        function remove(mention) {
            vm.mentioned.splice(vm.mentioned.indexOf(mention), 1);
        }

        function getNewStatuses() {
            return TatamiStatusRefresherService.refreshMentions();
        }

        getOldStatuses.$inject = ['finalStatus'];
        function getOldStatuses(finalStatus) {
            return TatamiStatusRefresherService.getOldMentions(finalStatus);
        }
    }
})();


================================================
FILE: mobile/www/app/components/home/mentions/mentions.html
================================================
<ion-view view-title="{{ 'tab.mentions' | translate }}" ng-style="{'background-color':'#f5f5f5'}">
    <tatami-status-list statuses="vm.mentioned"
                        current-user="vm.currentUser"
                        tatami-refresher="vm.getNewStatuses()"
                        tatami-infinite-refresher="vm.getOldStatuses(finalStatus)"></tatami-status-list>
</ion-view>


================================================
FILE: mobile/www/app/components/home/mentions/mentions.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('mentions', {
                url: '/mentions',
                parent: 'home',
                views: {
                    'mentions': {
                        templateUrl: 'app/components/home/mentions/mentions.html',
                        controller: 'MentionsCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    mentioned: mentioned
                }
            });
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('mentions', 'home');
        TatamiState.addConversationState('mentions', 'home');
        TatamiState.addTagState('mentions', 'home');
    }

    mentioned.$inject = ['HomeService'];
    function mentioned(HomeService) {
        return HomeService.getMentions().$promise;
    }

})();



================================================
FILE: mobile/www/app/components/home/more/all_users/all.users.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('AllUsersController', allUsersController);

    allUsersController.$inject = ['currentUser', 'TatamiUserRefresherService', '$scope', '$timeout'];
    function allUsersController(currentUser, TatamiUserRefresherService, $scope, $timeout) {
        var vm = this;
        vm.currentUser = currentUser;
        vm.users = [];
        vm.isFinished = false;

        vm.getNextUsers = getNextUsers;

        function getNextUsers() {
            return TatamiUserRefresherService.getNextUsers(vm.users.length).then(addUsers);
        }

        addUsers.$inject = ['users'];
        function addUsers(nextUsers) {
            $timeout(function() {
                $scope.$apply(function() {
                    vm.users.push.apply(vm.users, nextUsers);
                    vm.isFinished = nextUsers.length === 0;
                });
            })
        }
    }
})();


================================================
FILE: mobile/www/app/components/home/more/all_users/all.users.html
================================================
<ion-view view-title="{{ 'more.allUsers' | translate }}">
    <ion-content class="tatami-header tatami-footer" ng-style="{'background-color':'#f5f5f5'}">
        <ion-list ng-init="vm.getAllUsers()">
            <div ng-repeat="user in vm.users">
                <tatami-user user="user" current-user="vm.currentUser"></tatami-user>
            </div>
        </ion-list>
        <ion-infinite-scroll ng-if="!vm.isFinished" on-infinite="vm.getNextUsers()"></ion-infinite-scroll>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/home/more/all_users/all.users.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {

        $stateProvider
            .state('allusers', {
                url: '/allusers',
                parent: 'more',
                views: {
                    'more@home': {
                        templateUrl: 'app/components/home/more/all_users/all.users.html',
                        controller: 'AllUsersController',
                        controllerAs: 'vm'
                    }
                }
            });
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('allusers', 'home');
        TatamiState.addConversationState('allusers', 'home');
        TatamiState.addTagState('allusers', 'home');
    }

})();


================================================
FILE: mobile/www/app/components/home/more/blocked_users/blocked.users.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('BlockedUsersController', blockedUsersController);

    blockedUsersController.$inject = ['$scope', 'currentUser', 'BlockService'];
    function blockedUsersController($scope, currentUser, BlockService) {
        var vm = this;
        vm.currentUser = currentUser;
        vm.blockedUsers = [];

        vm.updateUser = updateUser;
        vm.getBlockedUsersForUser = getBlockedUsersForUser;
        vm.hasBlockedUsers = hasBlockedUsers;

        function updateUser() {
            BlockService.updateBlockedUser(
                {username: vm.status.username}
            );
        }

        function getBlockedUsersForUser() {
            BlockService.getBlockedUsersForUser(
                {username: vm.currentUser.username},
                function (response) {
                    vm.blockedUsers = response;
                }
            );
            $scope.$broadcast('scroll.refreshComplete');
        }

        function  hasBlockedUsers() {
            return vm.blockedUsers.length>0;
        }
    }
})();


================================================
FILE: mobile/www/app/components/home/more/blocked_users/blocked.users.html
================================================
<ion-view view-title="{{ 'more.blockedUsers.title' | translate }}">
    <ion-content ng-style="{'background-color':'#f5f5f5'}">
        <ion-refresher on-refresh="vm.getBlockedUsersForUser()"></ion-refresher>
        <ion-list ng-init="vm.getBlockedUsersForUser()">
            <div class="text-center" ng-if="!vm.hasBlockedUsers()" translate="more.blockedUsers.no" ng-style="{'color':'#ababab','padding':'40px'}"/>
            <div ng-if="vm.hasBlockedUsers()" ng-repeat="blockeduser in vm.blockedUsers">
                <tatami-user user="blockeduser"></tatami-user>
            </div>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/home/more/blocked_users/blocked.users.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {

        $stateProvider
            .state('blockedusers', {
                url: '/blockedusers',
                parent: 'more',
                views: {
                    'more@home': {
                        templateUrl: 'app/components/home/more/blocked_users/blocked.users.html',
                        controller: 'BlockedUsersController',
                        controllerAs: 'vm'
                    }
                }
            });
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('blockedusers', 'home');
        TatamiState.addConversationState('blockedusers', 'home');
        TatamiState.addTagState('blockedusers', 'home');
    }

})();


================================================
FILE: mobile/www/app/components/home/more/company/company-timeline.html
================================================
<ion-view view-title="{{ 'more.company' | translate }}" ng-style="{'background-color':'#f5f5f5'}">
    <tatami-status-list statuses="vm.statuses"
                        current-user="vm.currentUser"
                        tatami-refresher="vm.getNewStatuses()"
                        tatami-infinite-refresher="vm.getOldStatuses(finalStatus)"></tatami-status-list>
</ion-view>


================================================
FILE: mobile/www/app/components/home/more/company/company.timeline.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('CompanyTimelineCtrl', companyTimelineCtrl);

    companyTimelineCtrl.$inject = ['statuses', 'currentUser', 'TatamiStatusRefresherService'];
    function companyTimelineCtrl(statuses, currentUser, TatamiStatusRefresherService) {
        var vm = this;
        vm.statuses = statuses;
        vm.currentUser = currentUser;

        vm.getNewStatuses = getNewStatuses;
        vm.getOldStatuses = getOldStatuses;

        function getNewStatuses() {
            return TatamiStatusRefresherService.refreshCompanyTimeline();
        }

        getOldStatuses.$inject = ['finalStatus'];
        function getOldStatuses(finalStatus) {
            return TatamiStatusRefresherService.getOldFromCompanyTimeline(finalStatus);
        }
    }
})();


================================================
FILE: mobile/www/app/components/home/more/company/company.timeline.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {

        $stateProvider
            .state('company', {
                url: '/company/timeline',
                parent: 'more',
                views: {
                    'more@home': {
                        templateUrl: 'app/components/home/more/company/company-timeline.html',
                        controller: 'CompanyTimelineCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    statuses: getStatuses
                }
            });

        getStatuses.$inject = ['HomeService'];
        function getStatuses(HomeService) {
            return HomeService.getCompanyTimeline().$promise;
        }
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('company', 'home');
        TatamiState.addConversationState('company', 'home');
        TatamiState.addTagState('company', 'home');
    }

})();


================================================
FILE: mobile/www/app/components/home/more/more.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('MoreController', moreController);

    moreController.$inject = [
        '$state',
        '$localStorage',
        'currentUser'
    ];
    function moreController($state, $localStorage, currentUser) {
        var vm = this;

        vm.currentUser = currentUser;
        vm.logout = logout;
        vm.goToCompanyTimeline = goToCompanyTimeline;
        vm.goToSettings = goToSettings;
        vm.goToBlockedUsers = goToBlockedUsers;
        vm.goToAllUsers = goToAllUsers;
        vm.goToReportedStatus = goToReportedStatus;

        function logout() {
            $localStorage.signOut();
            $state.go('login');
        }

        function goToCompanyTimeline() {
            $state.go('company');
        }

        function goToSettings() {
            $state.go('settings');
        }

        function goToBlockedUsers(){
            $state.go('blockedusers');
        }

        function goToReportedStatus(){
            $state.go('reportedStatus')
        }

        function goToAllUsers() {
            $state.go('allusers')
        }

    }
})();


================================================
FILE: mobile/www/app/components/home/more/more.html
================================================
<ion-view view-title="{{ 'tab.more' | translate }}">
    <ion-content class="tatami-header tatami-footer" ng-style="{'background-color':'#f5f5f5'}">
        <ion-list>
            <div>
                <tatami-user user="vm.currentUser" current-user="vm.currentUser"></tatami-user>
            </div>
            <ion-item ng-click="vm.goToCompanyTimeline()" class="text-center">
                <span class="ion-briefcase calm padding-right"></span>&nbsp;
                <span class="calm" translate="more.company">Company Timeline</span>
            </ion-item>
            <ion-item class="text-center" ng-click="vm.goToAllUsers()">
                <span class="ion-earth padding-right"></span>
                <span translate="more.allUsers">All users</span>
            </ion-item>
            <ion-item class="item-divider"></ion-item>
            <ion-item ng-click="vm.goToSettings()" class="text-center">
                <span class="ion-gear-a padding-right"></span>&nbsp;
                <span translate="more.settings">Settings</span>
            </ion-item>
            <ion-item class="text-center" ng-click="vm.goToBlockedUsers()">
                <span class="ion-close-circled padding-right"></span>
                <span translate="more.blockedUsers.title">Manage your blocked users</span>
            </ion-item>
            <ion-item ng-if="vm.currentUser.isAdmin" class="text-center" ng-click="vm.goToReportedStatus()">
                <span class="ion-alert-circled"></span>
                <span translate="more.reportedStatus.title">Reported Statuses</span>
            </ion-item>
            <ion-item class="item-divider"></ion-item>
            <ion-item ng-click="vm.logout()" class="text-center">
                <span class="ion-power padding-right assertive"></span>&nbsp;
                <span class="assertive" translate="more.logout">Logout</span>
            </ion-item>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/home/more/more.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(moreConfig);

    moreConfig.$inject = ['$stateProvider'];
    function moreConfig($stateProvider) {
        $stateProvider
            .state('more', {
                url: '/more',
                parent: 'home',
                views: {
                    'more': {
                        templateUrl: 'app/components/home/more/more.html',
                        controller: 'MoreController',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    translatePartialLoader: getTranslatePartialLoader
                }
            });

        getTranslatePartialLoader.$inject = ['$translate', '$translatePartialLoader'];
        function getTranslatePartialLoader($translate, $translatePartialLoader) {
            $translatePartialLoader.addPart('more');
            return $translate.refresh();
        }
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('more', 'home');
    }
})();


================================================
FILE: mobile/www/app/components/home/more/reportedStatus/reportedStatus.controller.js
================================================
/**
 * Created by emilyklein on 7/11/16.
 */
(function() {
    'use strict';

    angular.module('tatami')
        .controller('ReportedStatusController', reportedStatusController);

    reportedStatusController.$inject = ['$state', '$scope', 'currentUser', 'ReportService', '$ionicPopup', '$translate', 'ToastService'];
    function reportedStatusController($state, $scope, currentUser, ReportService, $ionicPopup, $translate, ToastService) {
        var vm = this;

        vm.reportedStatuses = [];
        vm.currentUser = currentUser;

        vm.getReportedStatuses = getReportedStatuses;
        vm.hasReportedStatus = hasReportedStatus;
        vm.approveStatus = approveStatus;
        vm.deleteStatus = deleteStatus;

        function reportStatus() {
            ReportService.reportStatus({statusId: vm.status.statusId});
            $ionicPopup.alert({
                title: 'Report',
                template: '<span translate="status.reportMessage"></span>'
            });
        }

        goToProfile.$inject = ['username'];
        function goToProfile(username) {
            var destinationState = $state.current.name.split('.')[0] + '.profile';
            $state.go(destinationState, { username : username });
        }

        function getReportedStatuses(){
            ReportService.getReportedStatuses(null, function(response){
                    vm.reportedStatuses = response;
                }
            );
            $scope.$broadcast('scroll.refreshComplete');
        }

        function deleteStatus(statusId){
            var confirmPopup = $ionicPopup.confirm({
                title: 'Delete Status',
                template: '<span translate="status.reportStatus.delete"></span>'
            });
            confirmPopup.then(deleted);
            deleted.$inject = ['decision'];
            function deleted(decision) {
                if(decision) {
                    ReportService.deleteStatus({statusId: statusId}, function () {
                        ToastService.display('status.reportStatus.deleteToast');
                        }
                    );
                    $state.go($state.current, {}, {reload: true});
                }
            }
        }

        function approveStatus(statusId){
            var confirmPopup = $ionicPopup.confirm({
                title: 'Approve Status',
                template: '<span translate="status.reportStatus.approve"></span>'
            });
            confirmPopup.then(approved);
            approved.$inject = ['decision'];
            function approved(decision) {
                if(decision) {
                    ReportService.approveStatus({statusId: statusId}, function () {
                        ToastService.display('status.reportStatus.approveToast');
                        }
                    );
                    $state.go($state.current, {}, {reload: true});
                }
            }
        }

        remove.$inject = ['status'];
        function remove(status) {
            vm.statuses.splice(vm.statuses.indexOf(status), 1);
        }

        function  hasReportedStatus() {
            return vm.reportedStatuses.length > 0
        }
    }
})();




================================================
FILE: mobile/www/app/components/home/more/reportedStatus/reportedStatus.html
================================================
<ion-view view-title="{{ 'more.reportedStatus.title' | translate }}">
    <ion-content class="tatami-header tatami-footer">
        <ion-refresher on-refresh="vm.getReportedStatuses()"></ion-refresher>
        <ion-list ng-init="vm.getReportedStatuses()">
            <ion-item ng-if="vm.hasReportedStatus()" ng-repeat="status in vm.reportedStatuses" >
                <tatami-status status = "status" current-user = "vm.currentUser" on-delete = "vm.remove(status)"></tatami-status>
                <div class="row">
                    <div class="col-25 button button-clear ion-checkmark-round" ng-click="vm.approveStatus(status.statusId)"></div>
                    <div class="col-25 button button-clear ion-close-round" ng-click="vm.deleteStatus(status.statusId)"></div>
                </div>
            </ion-item>
            <div class="text-center" ng-if="!vm.hasReportedStatus()" translate="more.reportedStatus.no" ng-style="{'color':'#ababab','padding':'40px'}"/>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/home/more/reportedStatus/reportedStatus.js
================================================
/**
 * Created by emilyklein on 7/11/16.
 */
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {

        $stateProvider
            .state('reportedStatus', {
                cache: false,
                url: '/reportedStatus',
                parent: 'more',
                views: {
                    'more@home': {
                        templateUrl: 'app/components/home/more/reportedStatus/reportedStatus.html',
                        controller: 'ReportedStatusController',
                        controllerAs: 'vm'
                    }
                }
            });
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('reportedStatus', 'home');
        TatamiState.addConversationState('reportedStatus', 'home');
        TatamiState.addTagState('reportedStatus', 'home');
    }

})();


================================================
FILE: mobile/www/app/components/home/more/settings/settings.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('SettingsController', settingsController);

    settingsController.$inject = ['$scope', '$translate', 'currentUser'];
    function settingsController($scope, $translate, currentUser) {
        var vm = this;
        vm.currentUser = currentUser;

        vm.language = window.localStorage.getItem('language');

        vm.languages = [
            {
                langKey: 'en',
                translateKey: 'more.language.english'
            },
            {
                langKey: 'fr',
                translateKey: 'more.language.french'
            }
        ];

        $scope.$watch('vm.language', updateLanguage);

        function updateLanguage(language) {
            $translate.use(language);
            window.localStorage.setItem('language', language);
        }

    }
})();


================================================
FILE: mobile/www/app/components/home/more/settings/settings.html
================================================
<ion-view view-title="{{ 'more.settings' | translate }}">
    <ion-content ng-style="{'background-color':'#f5f5f5'}">
        <ion-list>
            <ion-item class="item-divider" translate="more.language.change"></ion-item>
            <ion-radio ng-repeat="language in vm.languages"
                       ng-model="vm.language"
                       ng-value="language.langKey">
                {{ language.translateKey | translate }}
            </ion-radio>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/home/more/settings/settings.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {

        $stateProvider
            .state('settings', {
                url: '/settings',
                parent: 'more',
                views: {
                    'more@home': {
                        templateUrl: 'app/components/home/more/settings/settings.html',
                        controller: 'SettingsController',
                        controllerAs: 'vm'
                    }
                }
            });
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('settings', 'home');
        TatamiState.addConversationState('settings', 'home');
        TatamiState.addTagState('settings', 'home');
    }

})();


================================================
FILE: mobile/www/app/components/home/timeline/timeline.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('TimelineCtrl', timelineCtrl);

    timelineCtrl.$inject = ['statuses', 'currentUser', 'TatamiStatusRefresherService'];
    function timelineCtrl(statuses, currentUser, TatamiStatusRefresherService) {
        var vm = this;

        vm.statuses = statuses;
        vm.currentUser = currentUser;
        vm.getNewStatuses = getNewStatuses;
        vm.getOldStatuses = getOldStatuses;

        function getNewStatuses() {
            return TatamiStatusRefresherService.refreshHomeTimeline();
        }

        getOldStatuses.$inject = ['finalStatus'];
        function getOldStatuses(finalStatus) {
            return TatamiStatusRefresherService.getOldFromHomeTimeline(finalStatus);
        }
    }
})();


================================================
FILE: mobile/www/app/components/home/timeline/timeline.html
================================================
<ion-view view-title="{{ 'tab.timeline' | translate }}" ng-style="{'background-color':'#f5f5f5'}">
    <tatami-status-list statuses="vm.statuses"
                        current-user="vm.currentUser"
                        tatami-refresher="vm.getNewStatuses()"
                        tatami-infinite-refresher="vm.getOldStatuses(finalStatus)"></tatami-status-list>
</ion-view>


================================================
FILE: mobile/www/app/components/home/timeline/timeline.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {

        $stateProvider
            .state('timeline', {
                url: '/timeline',
                parent: 'home',
                views: {
                    'timeline': {
                        templateUrl: 'app/components/home/timeline/timeline.html',
                        controller: 'TimelineCtrl',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    statuses: getStatuses
                }
            });

        getStatuses.$inject = ['StatusService'];
        function getStatuses(StatusService) {
            return StatusService.getHomeTimeline().$promise;
        }
    }

    angular.module('tatami')
        .run(run);

    run.$inject = ['TatamiState'];
    function run(TatamiState) {
        TatamiState.addProfileState('timeline', 'home');
        TatamiState.addConversationState('timeline', 'home');
        TatamiState.addTagState('timeline', 'home');
    }

})();


================================================
FILE: mobile/www/app/components/login/login.controller.js
================================================
(function () {
    'use strict';

    angular.module('tatami')
        .controller('LoginCtrl', loginCtrl);

    loginCtrl.$inject = [
        'TatamiEndpoint',
        '$scope',
        '$state',
        '$http',
        '$localStorage',
        '$ionicLoading',
        'PathService',
        '$ionicHistory',
        'ToastService'
    ];
    function loginCtrl(TatamiEndpoint, $scope, $state, $http, $localStorage, $ionicLoading, PathService, $ionicHistory, ToastService) {

        var vm = this;

        $scope.$on("$ionicView.enter", function () {
            $ionicHistory.clearCache();
            $ionicHistory.clearHistory();
            var newEndpoint = TatamiEndpoint.getEndpoint();
            if (vm.lastEndpoint.url !== newEndpoint.url) {
                vm.lastEndpoint.url = newEndpoint.url;
                vm.failed = false;
            }
        });

        vm.user = {
            remember: false
        };
        vm.failed = false;
        vm.login = login;
        vm.tryGoogleLogin = tryGoogleLogin;
        vm.goToServerConfig = goToServerConfig;
        vm.lastEndpoint = {url: ''};

        function login() {
            var data = "j_username=" + encodeURIComponent(vm.user.email) + "&j_password="
                + encodeURIComponent(vm.user.password);
            return $http.post('/tatami/rest/authentication', data, {
                headers: {
                    "Content-Type": "application/x-www-form-urlencoded",
                    "Accept": "application/json"
                }
            }).success(function (data) {
                $localStorage.set('token', data.token);
                vm.user = {remember: false};
                $state.go('timeline');
            }).error(function () {
                vm.failed = true;
            });
        }

        function tryGoogleLogin() {
            $http({
                url: '/tatami/rest/client/id',
                method: 'GET'
            }).then(function (data) {
                var clientId;
                if (data && data.data && data.data.stringList) {
                    // Old tatami return the clientId in the stringList property
                    clientId = data.data.stringList[0];
                } else if (data && data.data && data.data.clientId) {
                    clientId = data.data.clientId;
                }

                // Do Google login or display an error message
                if (clientId) {
                    googleLogin(clientId);
                } else {
                    ToastService.display('login.googleUnavaible');
                }
            }, function () {
                ToastService.display('login.googleUnavaible');
            });
        }

        function googleLogin(clientId) {
            var emailScope = 'https://www.googleapis.com/auth/plus.profile.emails.read';
            var profileScope = 'https://www.googleapis.com/auth/plus.me';
            var googleUrl = 'https://accounts.google.com/o/oauth2/auth?' +
                'client_id=' + clientId + '&' +
                'redirect_uri=http://localhost/callback&' +
                'scope=' + emailScope + ' ' + profileScope + '&' +
                'approval_prompt=force&response_type=code&access_type=offline';

            var ref = window.open(googleUrl, '_blank', 'location=no');

            ref.addEventListener('loadstart', onStart);

            onStart.$inject = ['event'];
            function onStart(event) {
                if (event.url.indexOf('http://localhost/callback') === 0) {
                    ref.close();
                    $ionicLoading.show({
                        template: '<span translate="login.progress">Login in progress...</span>',
                        hideOnStateChange: true
                    });
                    var requestToken = event.url.split("code=")[1];
                    $http({
                        url: '/tatami/rest/oauth/token',
                        method: 'POST',
                        headers: {
                            'x-auth-code-header': requestToken
                        }
                    }).then(onSuccess, onFail);
                }
            }

            onSuccess.$inject = ['result'];
            function onSuccess(result) {
                $localStorage.set('token', result.data.token);
                $state.go('timeline');
            }

            onFail.$inject = ['failure'];
            function onFail() {
                vm.failed = true;
            }
        }

        function goToServerConfig() {
            $state.go('server');
        }
    }
})();


================================================
FILE: mobile/www/app/components/login/login.html
================================================
<ion-view name="login-view" view-title="{{ 'login.title' | translate }}" hide-back-button="true">
    <ion-content class="has-header" scroll="false">
        <form ng-submit="vm.login()">
            <div class="list list-inset">
                <label class="item item-input">
                    <input type="text" autocapitalize="off" autocorrect="off" placeholder="{{ 'login.email' | translate }}" ng-model="vm.user.email">
                </label>
                <label class="item item-input">
                    <input type="password" placeholder="{{ 'login.password' | translate }}" ng-model="vm.user.password">
                </label>
            </div>

            <div align="center">
                <label class="toggle v-align">
                    <input type="checkbox" ng-model="vm.tos">
                    <div class="track">
                        <div class="handle"></div>
                    </div>
                </label>
                <span translate="login.accept"></span>
                <a href="http://tatami.ippon.fr/#/about/tos" translate="login.tos"></a>
            </div>
            <div class="row">
                <div class="col col-50">
                    <button ng-disabled="!vm.user.email && !vm.user.password || !vm.tos"
                            translate="login.title"
                            class="button button-block button-calm"
                            type="submit">
                        Login
                    </button>
                </div>
                <div class="col col-50">
                    <button ng-disabled="!vm.tos"
                            ng-click="vm.tryGoogleLogin()"
                            translate="login.google"
                            class="button button-block button-stable"
                            type="button">
                        Google Login
                    </button>
                </div>
            </div>
            <div class="row">
                <button class="button button-block button-stable"
                        type="button"
                        ng-click="vm.goToServerConfig()">
                    <span>{{ 'login.changeServer' | translate }}</span>
                </button>
            </div>

            <div ng-show="vm.failed" class="bar bar-assertive">
                <h1 class="title" translate="login.failed">Failed to log in!</h1>
            </div>
        </form>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/login/login.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('login', {
                url: '/login',
                parent: 'tatami',
                templateUrl: 'app/components/login/login.html',
                controller: 'LoginCtrl',
                controllerAs: 'vm',
                resolve: {
                    translatePartialLoader: getTranslatePartialLoader
                }
            });

        getTranslatePartialLoader.$inject = ['$translate', '$translatePartialLoader'];
        function getTranslatePartialLoader($translate, $translatePartialLoader) {
            $translatePartialLoader.addPart('login');
            return $translate.refresh();
        }
    }
})();


================================================
FILE: mobile/www/app/components/login/server/server.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('ServerController', serverController);

    serverController.$inject = [
        '$state',
        '$http',
        '$ionicHistory',
        '$translate',
        '$ionicPopup',
        'PathService',
        'TatamiEndpoint'
    ];
    function serverController($state, $http, $ionicHistory, $translate, $ionicPopup, PathService, TatamiEndpoint) {
        var vm = this;

        vm.endpoint = TatamiEndpoint.getEndpoint().url || TatamiEndpoint.getDefault().url;
        vm.success = true;
        vm.previous = vm.endpoint;

        vm.updateEndpoint = updateEndpoint;
        vm.useDefaultEndpoint = useDefaultEndpoint;
        vm.isLastAttempt = isLastAttempt;

        function updateEndpoint() {
            TatamiEndpoint.setEndpoint(vm.endpoint);
            $http({
                url: '/tatami/rest/client/id',
                method: 'GET'
            }).then(success, error);
        }

        function success(result) {
            vm.success = true;
            vm.previous = vm.endpoint;

            var alertPopup = $ionicPopup.alert({
                title: $translate.instant('server.endpoint.authenticate.title'),
                template: '<span translate="server.endpoint.authenticate.body"></span>'
            });

            alertPopup.then($state.go('login'));
        }

        function error(result) {
            vm.success = false;
            vm.previous = vm.endpoint;

            $ionicPopup.alert({
                title: $translate.instant('server.endpoint.error.title'),
                template: '<span translate="server.endpoint.error.body"></span>'
            });

            TatamiEndpoint.reset();
        }

        function isLastAttempt() {
            return vm.previous === vm.endpoint;
        }

        function useDefaultEndpoint() {
            vm.endpoint = TatamiEndpoint.getDefault().url;
            updateEndpoint();
        }
    }
})();


================================================
FILE: mobile/www/app/components/login/server/server.html
================================================
<ion-view view-title="">
    <ion-content ng-style="{'background-color':'#f5f5f5'}">
        <ion-list>
            <ion-item class="item-divider item-button-right" translate="server.endpoint.change"></ion-item>
            <ion-item class="item-input-inset">
                <label class="item-input-wrapper">
                    <input
                        class="item-input-wrapper"
                        type="text"
                           autocapitalize="off"
                           autocorrect="off"
                           ng-model="vm.endpoint"
                           placeholder="{{ 'server.endpoint.title' | translate }}">
                </label>
                <button class="button button-small"
                        ng-class="{ 'button-balanced': vm.isLastAttempt() && vm.success,
                                    'button-assertive': vm.isLastAttempt() && !vm.success }"
                        ng-disabled="vm.isLastAttempt()"
                        ng-click="vm.updateEndpoint()">
                    <span ng-if="vm.isLastAttempt()"
                          ng-class="{ 'ion-checkmark-round': vm.success,
                                      'ion-close-round': !vm.success }"></span>
                    <span ng-if="!vm.isLastAttempt()">Submit</span>
                </button>
            </ion-item>
            <ion-item ng-click="vm.useDefaultEndpoint()"
                      class="text-center"
                      translate="server.endpoint.default"></ion-item>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/components/login/server/server.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(config);

    config.$inject = ['$stateProvider'];
    function config($stateProvider) {
        $stateProvider
            .state('server', {
                url: '/server',
                parent: 'login',
                views: {
                    '@tatami': {
                        templateUrl: 'app/components/login/server/server.html',
                        controller: 'ServerController',
                        controllerAs: 'vm'
                    }
                },
                resolve: {
                    translatePartialLoader: getTranslatePartialLoader
                }
            });

        getTranslatePartialLoader.$inject = ['$translate', '$translatePartialLoader'];
        function getTranslatePartialLoader($translate, $translatePartialLoader) {
            $translatePartialLoader.addPart('server');
            $translate.refresh();
        }
    }
})();


================================================
FILE: mobile/www/app/components/post/post.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('PostCtrl', postCtrl);

    postCtrl.$inject = [
        'StatusService',
        'PathService',
        '$ionicHistory',
        '$state',
        '$cordovaCamera',
        '$q',
        '$ionicLoading',
        '$ionicPopup',
        'repliedToStatus',
        '$scope',
        '$cordovaGeolocation',
        'ToastService'
    ];
    function postCtrl(StatusService, PathService, $ionicHistory, $state, $cordovaCamera, $q, $ionicLoading, $ionicPopup, repliedToStatus, $scope, $cordovaGeolocation, ToastService) {
        var vm = this;
        vm.charCount = 750;
        vm.status = {
            content: repliedToStatus ? '@' + repliedToStatus.username : '',
            statusPrivate: repliedToStatus ? repliedToStatus.private : false,
            replyTo: repliedToStatus ? repliedToStatus.statusId : '',
            replyToUsername: repliedToStatus ? repliedToStatus.username : '',
            attachmentIds: [],
            geoLocalization: ""
        };
        vm.images = [];
        vm.isPosting = false;
        vm.remainingLength = vm.charCount;
        vm.newLineCount = 0; //This field takes into consideration the '\n' character that counts for 2 chars in the database.
        vm.pasteFlag = false;
        vm.shareLocation = false;

        vm.post = post;
        vm.reset = reset;
        vm.close = close;
        vm.getPicture = getPicture;
        vm.getPictureFromLibrary = getPictureFromLibrary;
        vm.remove = remove;
        vm.paste = paste;
        vm.updateLocation = updateLocation;
        vm.updatePrivate = updatePrivate;

        function post() {
            upload().then(createPost);
        }

        function createPost(attachmentIds) {
            vm.status.attachmentIds = attachmentIds;
            StatusService.save(vm.status, function() {
                reset();
                $ionicHistory.clearCache();
                $state.go('timeline');
            });
        }

        function reset() {
            vm.status = {
                content: '',
                statusPrivate: false,
                attachmentIds: [],
                geoLocalization: ""
            };
            vm.images = [];
            vm.isPosting = false;
            vm.shareLocation = false;
        }

        function close() {
            $ionicHistory.goBack();
            reset();
        }

        function getPicture() {
            var options = {
                quality: 10,
                correctOrientation : true
            };

            $cordovaCamera.getPicture(options).then(store);
        }

        function getPictureFromLibrary() {
            var options = {
                quality: 10,
                sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
                correctOrientation: true
            };

            $cordovaCamera.getPicture(options).then(store);
        }

        function store(fileUri) {
            vm.images.push(fileUri);
        }

        function upload() {
            var promises = [];
            vm.isPosting = true;

            var options = new FileUploadOptions();
            var fileTransfer = new FileTransfer();
            angular.forEach(vm.images, function(image) {
                var deferred = $q.defer();
                options.fileKey = 'uploadFile';
                options.fileName = image.substr(image.lastIndexOf('/') + 1);

                $ionicLoading.show({
                    template: '<span translate="post.progress">Post in progress...</span>',
                    hideOnStateChange: true
                });

                fileTransfer.upload(image, '/tatami/rest/fileupload', onSuccess, onFail, options);
                promises.push(deferred.promise);

                function onSuccess(result) {
                    var jsonResult = JSON.parse(result.response)[0];
                    deferred.resolve(jsonResult.attachmentId);
                }

                function onFail(failure) {
                    $ionicLoading.hide();

                    var popupError = $ionicPopup.alert({
                        title: 'Error',
                        template: '<span translate="post.error.message"></span>'
                    });

                    popupError.then(goToTimeline);

                    function goToTimeline() {
                        reset();
                        $state.go('timeline');
                    }

                    deferred.resolve(failure);
                }
            });

            return $q.all(promises);
        }

        function remove(index) {
            vm.images.splice(index, 1);
        }

        function updateRemainingLength(statusContent) {
            vm.remainingLength = vm.charCount - statusContent.length - vm.newLineCount;
        }

        function updateNewLineCount(statusContent) {
            vm.newLineCount = (statusContent.match(/\n/g) || []).length;
        }

        $scope.$watch('vm.status.content', function (newValue) {
            if (newValue) {
                updateNewLineCount(newValue);
                updateRemainingLength(newValue);
                if(vm.remainingLength < 0){
                    if(vm.pasteFlag){
                        $ionicLoading.show({
                            template: '<span translate="post.error.truncated"></span>',
                            duration: 2500
                        });
                        vm.pasteFlag = false;
                    }
                    vm.status.content = newValue.slice(0, vm.charCount - vm.newLineCount);
                    updateNewLineCount(vm.status.content);
                    updateRemainingLength(vm.status.content);
                }
            } else {
                vm.remainingLength = vm.charCount;
                vm.newLineCount = 0;
            }
        });

        function paste(){
            vm.pasteFlag = true;
        }

        function updateLocation() {
            vm.shareLocation = !vm.shareLocation;
            if(vm.shareLocation){
                var posOptions = {timeout: 5000, enableHighAccuracy: false};
                $cordovaGeolocation
                    .getCurrentPosition(posOptions)
                    .then(function (position) {
                        vm.status.geoLocalization = position.coords.latitude + ", " + position.coords.longitude;
                        ToastService.display('post.location.share');
                    }, function() {
                        vm.shareLocation = !vm.shareLocation;
                        ToastService.display('post.location.fail');
                    });
            } else {
                vm.status.geoLocalization = "";
            }
        }

        function updatePrivate(){
            vm.status.statusPrivate = !vm.status.statusPrivate;
            vm.status.statusPrivate ? ToastService.display('post.private.yes') : ToastService.display('post.private.no');
        }
    }
})();


================================================
FILE: mobile/www/app/components/post/post.html
================================================
<ion-view view-title="{{ 'post.title' | translate }}" hide-back-button="true">
    <ion-nav-buttons side="secondary">
        <button class="button button-clear button-small icon ion-close-round" style="opacity:0.4;" ng-click="vm.close()">
        </button>
    </ion-nav-buttons>
    <ion-content class="has-subfooter">
        <form name="newPost" novalidate="">
            <ion-item>
                <ion-textarea>
                        <textarea ng-model="vm.status.content"
                                  rows="15"
                                  placeholder="{{ 'post.message' | translate }}"
                                  ng-required="true"
                                  ng-trim="false"
                                  ng-paste="vm.paste()"
                                  style="width: 100%; height: 100%;">
                            </textarea>
                </ion-textarea>
            </ion-item>
        </form>
        <span ng-repeat="image in vm.images track by $index">
            <div class="list card">
                <div class="item item-image">
                    <img class="center" ng-show="vm.images.length > 0" ng-src="{{ image }}">
                    <i class="icon ion-close-round light" ng-click="vm.remove($index)"></i>
                </div>
            </div>
        </span>
    </ion-content>
    <ion-footer-bar align-title="right" tatami-post-bar-attach="true" class="bar-subfooter">
        <div class="row" style="width:50%;">
            <button class="col-33 button button-clear icon ion-camera" ng-click="vm.getPicture()"></button>
            <button class="col-33 button button-clear icon ion-images" ng-click="vm.getPictureFromLibrary()"></button>
            <button class="col-33 button button-clear icon ion-location"
                    ng-click="vm.updateLocation()"
                    ng-class="{ 'button-calm' : vm.shareLocation, 'button-stable' : !vm.shareLocation }"></button>
            <button class="col-33 button button-clear icon ion-locked"
                    ng-click="vm.updatePrivate()"
                    ng-class="{ 'button-calm' : vm.status.statusPrivate, 'button-stable' : !vm.status.statusPrivate }"></button>
        </div>

        <h1 class="title">{{vm.remainingLength}}</h1>
        <button class="button button-positive"
                translate="post.title"
                ng-disabled="vm.status.content.length === 0 || !vm.status.content || vm.isPosting"
                ng-click="vm.post()">
            Post
        </button>
    </ion-footer-bar>
</ion-view>


================================================
FILE: mobile/www/app/components/post/post.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(postConfig);

    postConfig.$inject = ['$stateProvider'];
    function postConfig($stateProvider) {
        $stateProvider
            .state('post', {
                url: '/post/:statusId',
                parent: 'tatami',
                templateUrl: 'app/components/post/post.html',
                controller: 'PostCtrl',
                controllerAs: 'vm',

                resolve: {
                    repliedToStatus: getRepliedToStatus,
                    translatePartialProvider: getTranslatePartialLoader
                }
            })
    }

    getRepliedToStatus.$inject = ['StatusService', '$stateParams'];
    function getRepliedToStatus(StatusService, $stateParams) {
        if($stateParams.statusId) {
            return StatusService.get({ statusId: $stateParams.statusId }).$promise;
        }
    }

    getTranslatePartialLoader.$inject = ['$translate', '$translatePartialLoader'];
    function getTranslatePartialLoader($translate, $translatePartialLoader) {
        $translatePartialLoader.addPart('post');
        return $translate.refresh();
    }
})();


================================================
FILE: mobile/www/app/components/post/postbar.directive.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .directive('tatamiPostBarAttach', tatamiPostBar);

    function tatamiPostBar() {
        var directive = {
            restrict: 'A',
            link: link
        };

        return directive;
    }

    function link(scope, element, attrs) {
        ionic.on('native.keyboardshow', onShow, window);
        ionic.on('native.keyboardhide', onHide, window);

        //deprecated
        ionic.on('native.showkeyboard', onShow, window);
        ionic.on('native.hidekeyboard', onHide, window);


        var scrollCtrl;

        function onShow(e) {
            if (ionic.Platform.isAndroid() && !ionic.Platform.isFullScreen) {
                return;
            }


            if(attrs['tatamiPostBarAttach'] === 'true') {
                var subheaderOffset = 43;
            }
            //for testing
            var keyboardHeight = e.keyboardHeight || e.detail.keyboardHeight;
            element.css('bottom', (keyboardHeight + subheaderOffset) + "px");
            scrollCtrl = element.controller('$ionicScroll');
            if (scrollCtrl) {
                scrollCtrl.scrollView.__container.style.bottom = subheaderOffset + keyboardHeight + keyboardAttachGetClientHeight(element[0]) + "px";
            }
        }

        function onHide() {
            if (ionic.Platform.isAndroid() && !ionic.Platform.isFullScreen) {
                return;
            }

            element.css('bottom', '');
            if (scrollCtrl) {
                scrollCtrl.scrollView.__container.style.bottom = '';
            }
        }

        scope.$on('$destroy', function() {
            ionic.off('native.keyboardshow', onShow, window);
            ionic.off('native.keyboardhide', onHide, window);

            //deprecated
            ionic.off('native.showkeyboard', onShow, window);
            ionic.off('native.hidekeyboard', onHide, window);
        });

        function keyboardAttachGetClientHeight(element) {
            return element.clientHeight;
        }

    }
})();


================================================
FILE: mobile/www/app/shared/config/marked.config.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .config(markedConfig);

    markedConfig.$inject = ['markedProvider'];
    function markedConfig(markedProvider) {
        markedProvider.setOptions({
            gfm: true,
            pedantic: false,
            sanitize: true,
            highlight: null,
            urls: {
                youtube : function(text, url){
                    var cap;
                    if((cap = /(youtu\.be\/|youtube\.com\/(watch\?(.*&)?v=|(embed|v)\/))([^\?&"'>]+)/.exec(url))){
                        return '<iframe width="420" height="315" src="https://www.youtube.com/embed/' +
                            cap[5] +
                            '" frameborder="0" allowfullscreen></iframe>';
                    }
                },
                vimeo : function(text, url){
                    var cap;
                    if((cap = /^.*(vimeo\.com\/)((channels\/[A-z]+\/)|(groups\/[A-z]+\/videos\/))?([0-9]+)/.exec(url))){
                        return '<iframe src="https://player.vimeo.com/video/' +
                            cap[5] +
                            '" width="500" height="281" frameborder="0" webkitAllowFullScreen mozallowfullscreen allowFullScreen></iframe>';
                    }
                },
                dailymotion : function(text, url){
                    var cap;
                    if((cap = /^.+dailymotion.com\/(video|hub)\/([^_]+)[^#]*(#video=([^_&]+))?/.exec(url))){
                        return '<iframe frameborder="0" width="480" height="271" src="https://www.dailymotion.com/embed/video/' +
                            cap[2] +
                            '"></iframe>';
                    }
                },
                gist : function(text, url){
                    var cap;
                    if((cap = /^.+gist.github.com\/(([A-z0-9-]+)\/)?([0-9A-z]+)/.exec(url))){
                        $.ajax({
                            url: cap[0] + '.json',
                            dataType: 'jsonp',
                            success: function(response){
                                if(response.stylesheet && $('link[href="' + response.stylesheet + '"]').length === 0){
                                    var l = document.createElement("link"),
                                        head = document.getElementsByTagName("head")[0];

                                    l.type = "text/css";
                                    l.rel = "stylesheet";
                                    l.href = response.stylesheet;
                                    head.insertBefore(l, head.firstChild);
                                }
                                var $elements = $('.gist' + cap[3]);
                                $elements.html(response.div);
                            }
                        });
                        return '<div class="gist' + cap[3] + '"/>';
                    }
                }
            }
        });
    }
})();


================================================
FILE: mobile/www/app/shared/config/marked.filter.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .filter('markdown', markdown);

    markdown.$inject = ['$sce'];
    function markdown($sce) {
        return function(content) {
            return content ? marked(content) : '';
        };
    }
})();


================================================
FILE: mobile/www/app/shared/config/tatami.marked.js
================================================
/**
 * marked - a markdown parser
 * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)
 * https://github.com/chjj/marked
 */

;(function() {

    /**
     * Block-Level Grammar
     */

    var block = {
        newline: /^\n+/,
        code: /^( {4}[^\n]+\n*)+/,
        fences: noop,
        hr: /^( *[-*_]){3,} *(?:\n+|$)/,
        heading: /^ *(#{1,6} ) *([^\n]+?) *#* *(?:\n+|$)/,
        nptable: noop,
        lheading: /^([^\n]+)\n *(=|-){3,} *\n*/,
        blockquote: /^( *>[^\n]+(\n[^\n]+)*\n*)+/,
        list: /^( *)(bull) [\s\S]+?(?:hr|\n{2,}(?! )(?!\1bull )\n*|\s*$)/,
        html: /^ *(?:comment|closed|closing) *(?:\n{2,}|\s*$)/,
        def: /^ *\[([^\]]+)\]: *<?([^\s>]+)>?(?: +["(]([^\n]+)[")])? *(?:\n+|$)/,
        table: noop,
        paragraph: /^((?:[^\n]+\n?(?!hr|heading|lheading|blockquote|tag|def))+)\n*/,
        text: /^[^\n]+/
    };

    block.bullet = /(?:[*+-]|\d+\.)/;
    block.item = /^( *)(bull) [^\n]*(?:\n(?!\1bull )[^\n]*)*/;
    block.item = replace(block.item, 'gm')
    (/bull/g, block.bullet)
    ();

    block.list = replace(block.list)
    (/bull/g, block.bullet)
    ('hr', /\n+(?=(?: *[-*_]){3,} *(?:\n+|$))/)
    ();

    block._tag = '(?!(?:'
        + 'a|em|strong|small|s|cite|q|dfn|abbr|data|time|code'
        + '|var|samp|kbd|sub|sup|i|b|u|mark|ruby|rt|rp|bdi|bdo'
        + '|span|br|wbr|ins|del|img)\\b)\\w+(?!:/|@)\\b';

    block.html = replace(block.html)
    ('comment', /<!--[\s\S]*?-->/)
    ('closed', /<(tag)[\s\S]+?<\/\1>/)
    ('closing', /<tag(?:"[^"]*"|'[^']*'|[^'">])*?>/)
    (/tag/g, block._tag)
    ();

    block.paragraph = replace(block.paragraph)
    ('hr', block.hr)
    ('heading', block.heading)
    ('lheading', block.lheading)
    ('blockquote', block.blockquote)
    ('tag', '<' + block._tag)
    ('def', block.def)
    ();

    /**
     * Normal Block Grammar
     */

    block.normal = merge({}, block);

    /**
     * GFM Block Grammar
     */

    block.gfm = merge({}, block.normal, {
        fences: /^ *(`{3,}|~{3,}) *(\w+)? *\n([\s\S]+?)\s*\1 *(?:\n+|$)/,
        paragraph: /^/
    });

    block.gfm.paragraph = replace(block.paragraph)
    ('(?!', '(?!' + block.gfm.fences.source.replace('\\1', '\\2') + '|')
    ();

    /**
     * GFM + Tables Block Grammar
     */

    block.tables = merge({}, block.gfm, {
        nptable: /^ *(\S.*\|.*)\n *([-:]+ *\|[-| :]*)\n((?:.*\|.*(?:\n|$))*)\n*/,
        table: /^ *\|(.+)\n *\|( *[-:]+[-| :]*)\n((?: *\|.*(?:\n|$))*)\n*/
    });

    /**
     * Block Lexer
     */

    function Lexer(options) {
        this.tokens = [];
        this.tokens.links = {};
        this.options = options || marked.defaults;
        this.rules = block.normal;

        if (this.options.gfm) {
            if (this.options.tables) {
                this.rules = block.tables;
            } else {
                this.rules = block.gfm;
            }
        }
    }

    /**
     * Expose Block Rules
     */

    Lexer.rules = block;

    /**
     * Static Lex Method
     */

    Lexer.lex = function(src, options) {
        var lexer = new Lexer(options);
        return lexer.lex(src);
    };

    /**
     * Preprocessing
     */

    Lexer.prototype.lex = function(src) {
        src = src
            .replace(/\r\n|\r/g, '\n')
            .replace(/\t/g, '    ')
            .replace(/\u00a0/g, ' ')
            .replace(/\u2424/g, '\n');

        return this.token(src, true);
    };

    /**
     * Lexing
     */

    Lexer.prototype.token = function(src, top) {
        var src = src.replace(/^ +$/gm, '')
            , next
            , loose
            , cap
            , bull
            , b
            , item
            , space
            , i
            , l;

        while (src) {
            // newline
            if (cap = this.rules.newline.exec(src)) {
                src = src.substring(cap[0].length);
                if (cap[0].length > 1) {
                    this.tokens.push({
                        type: 'space'
                    });
                }
            }

            // code
            if (cap = this.rules.code.exec(src)) {
                src = src.substring(cap[0].length);
                cap = cap[0].replace(/^ {4}/gm, '');
                this.tokens.push({
                    type: 'code',
                    text: !this.options.pedantic
                        ? cap.replace(/\n+$/, '')
                        : cap
                });
                continue;
            }

            // fences (gfm)
            if (cap = this.rules.fences.exec(src)) {
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: 'code',
                    lang: cap[2],
                    text: cap[3]
                });
                continue;
            }

            // heading
            if (cap = this.rules.heading.exec(src)) {
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: 'heading',
                    depth: cap[1].length,
                    text: cap[2]
                });
                continue;
            }

            // table no leading pipe (gfm)
            if (top && (cap = this.rules.nptable.exec(src))) {
                src = src.substring(cap[0].length);

                item = {
                    type: 'table',
                    header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
                    align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
                    cells: cap[3].replace(/\n$/, '').split('\n')
                };

                for (i = 0; i < item.align.length; i++) {
                    if (/^ *-+: *$/.test(item.align[i])) {
                        item.align[i] = 'right';
                    } else if (/^ *:-+: *$/.test(item.align[i])) {
                        item.align[i] = 'center';
                    } else if (/^ *:-+ *$/.test(item.align[i])) {
                        item.align[i] = 'left';
                    } else {
                        item.align[i] = null;
                    }
                }

                for (i = 0; i < item.cells.length; i++) {
                    item.cells[i] = item.cells[i].split(/ *\| */);
                }

                this.tokens.push(item);

                continue;
            }

            // lheading
            if (cap = this.rules.lheading.exec(src)) {
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: 'heading',
                    depth: cap[2] === '=' ? 1 : 2,
                    text: cap[1]
                });
                continue;
            }

            // hr
            if (cap = this.rules.hr.exec(src)) {
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: 'hr'
                });
                continue;
            }

            // blockquote
            if (cap = this.rules.blockquote.exec(src)) {
                src = src.substring(cap[0].length);

                this.tokens.push({
                    type: 'blockquote_start'
                });

                cap = cap[0].replace(/^ *> ?/gm, '');

                // Pass `top` to keep the current
                // "toplevel" state. This is exactly
                // how markdown.pl works.
                this.token(cap, top);

                this.tokens.push({
                    type: 'blockquote_end'
                });

                continue;
            }

            // list
            if (cap = this.rules.list.exec(src)) {
                src = src.substring(cap[0].length);

                this.tokens.push({
                    type: 'list_start',
                    ordered: isFinite(cap[2])
                });

                // Get each top-level item.
                cap = cap[0].match(this.rules.item);

                // Get bullet.
                if (this.options.smartLists) {
                    bull = block.bullet.exec(cap[0])[0];
                }

                next = false;
                l = cap.length;
                i = 0;

                for (; i < l; i++) {
                    item = cap[i];

                    // Remove the list item's bullet
                    // so it is seen as the next token.
                    space = item.length;
                    item = item.replace(/^ *([*+-]|\d+\.) +/, '');

                    // Outdent whatever the
                    // list item contains. Hacky.
                    if (~item.indexOf('\n ')) {
                        space -= item.length;
                        item = !this.options.pedantic
                            ? item.replace(new RegExp('^ {1,' + space + '}', 'gm'), '')
                            : item.replace(/^ {1,4}/gm, '');
                    }

                    // Determine whether the next list item belongs here.
                    // Backpedal if it does not belong in this list.
                    if (this.options.smartLists && i !== l - 1) {
                        b = block.bullet.exec(cap[i+1])[0];
                        if (bull !== b && !(bull[1] === '.' && b[1] === '.')) {
                            src = cap.slice(i + 1).join('\n') + src;
                            i = l - 1;
                        }
                    }

                    // Determine whether item is loose or not.
                    // Use: /(^|\n)(?! )[^\n]+\n\n(?!\s*$)/
                    // for discount behavior.
                    loose = next || /\n\n(?!\s*$)/.test(item);
                    if (i !== l - 1) {
                        next = item[item.length-1] === '\n';
                        if (!loose) loose = next;
                    }

                    this.tokens.push({
                        type: loose
                            ? 'loose_item_start'
                            : 'list_item_start'
                    });

                    // Recurse.
                    this.token(item, false);

                    this.tokens.push({
                        type: 'list_item_end'
                    });
                }

                this.tokens.push({
                    type: 'list_end'
                });

                continue;
            }

            // html
            if (cap = this.rules.html.exec(src)) {
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: this.options.sanitize
                        ? 'paragraph'
                        : 'html',
                    pre: cap[1] === 'pre',
                    text: cap[0]
                });
                continue;
            }

            // def
            if (top && (cap = this.rules.def.exec(src))) {
                src = src.substring(cap[0].length);
                this.tokens.links[cap[1].toLowerCase()] = {
                    href: cap[2],
                    title: cap[3]
                };
                continue;
            }

            // table (gfm)
            if (top && (cap = this.rules.table.exec(src))) {
                src = src.substring(cap[0].length);

                item = {
                    type: 'table',
                    header: cap[1].replace(/^ *| *\| *$/g, '').split(/ *\| */),
                    align: cap[2].replace(/^ *|\| *$/g, '').split(/ *\| */),
                    cells: cap[3].replace(/(?: *\| *)?\n$/, '').split('\n')
                };

                for (i = 0; i < item.align.length; i++) {
                    if (/^ *-+: *$/.test(item.align[i])) {
                        item.align[i] = 'right';
                    } else if (/^ *:-+: *$/.test(item.align[i])) {
                        item.align[i] = 'center';
                    } else if (/^ *:-+ *$/.test(item.align[i])) {
                        item.align[i] = 'left';
                    } else {
                        item.align[i] = null;
                    }
                }

                for (i = 0; i < item.cells.length; i++) {
                    item.cells[i] = item.cells[i]
                        .replace(/^ *\| *| *\| *$/g, '')
                        .split(/ *\| */);
                }

                this.tokens.push(item);

                continue;
            }

            // top-level paragraph
            if (top && (cap = this.rules.paragraph.exec(src))) {
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: 'paragraph',
                    text: cap[1][cap[1].length-1] === '\n'
                        ? cap[1].slice(0, -1)
                        : cap[1]
                });
                continue;
            }

            // text
            if (cap = this.rules.text.exec(src)) {
                // Top-level should never reach here.
                src = src.substring(cap[0].length);
                this.tokens.push({
                    type: 'text',
                    text: cap[0]
                });
                continue;
            }

            if (src) {
                throw new
                    Error('Infinite loop on byte: ' + src.charCodeAt(0));
            }
        }

        return this.tokens;
    };

    /**
     * Inline-Level Grammar
     */

    var inline = {
        escape: /^\\([\\`*{}\[\]()#+\-.!_>])/,
        autolink: /^<([^ >]+(@|:\/)[^ >]+)>/,
        url: noop,
        tag: /^<!--[\s\S]*?-->|^<\/?\w+(?:"[^"]*"|'[^']*'|[^'">])*?>/,
        link: /^!?\[(inside)\]\(href\)/,
        reflink: /^!?\[(inside)\]\s*\[([^\]]*)\]/,
        nolink: /^!?\[((?:\[[^\]]*\]|[^\[\]])*)\]/,
        strong: /^__([\s\S]+?)__(?!_)|^\*\*([\s\S]+?)\*\*(?!\*)/,
        em: /^\b_((?:__|[\s\S])+?)_\b|^\*((?:\*\*|[\s\S])+?)\*(?!\*)/,
        code: /^(`+)\s*([\s\S]*?[^`])\s*\1(?!`)/,
        br: /^ {2,}\n(?!\s*$)/,
        mail: /^([^\s !"#$%'()*+,.\/:;<=>?@\\\[\]\^_`{|}~-]+(@|:\/)[^\s !"#$%'()*+,.\/:;<=>?@\\\[\]\^_`{|}~-]+.[^\s !"#$%'()*+,.\/:;<=>?@\\\[\]\^_`{|}~-]+)/,
        mention: /^@([A-Za-z0-9!#$%&'*+\/=?\^_`{|}~\-]+(?:\.[A-Za-z0-9!#$%&'*+\/=?\^_`{|}~\-]+)*(?!\*))/,
        tags:   /^#([^\s!"#$%'()*+,.\/:;<=>?@\\\[\]\^_`{|}~-]+(?:\.[\^!"#$%'()*+,.\/:;<=>?@\\\[\]\^_`{|}~-]+)*)(?!\*)/,
        del: noop,
        text: /^[\s\S]+?(?=[\\<!\[_*`]| {2,}\n|$)/
    };

    inline._inside = /(?:\[[^\]]*\]|[^\]]|\](?=[^\[]*\]))*/;
    inline._href = /\s*<?([^\s]*?)>?(?:\s+['"]([\s\S]*?)['"])?\s*/;

    inline.link = replace(inline.link)
    ('inside', inline._inside)
    ('href', inline._href)
    ();

    inline.reflink = replace(inline.reflink)
    ('inside', inline._inside)
    ();

    /**
     * Normal Inline Grammar
     */

    inline.normal = merge({}, inline);

    /**
     * Pedantic Inline Grammar
     */

    inline.pedantic = merge({}, inline.normal, {
        strong: /^__(?=\S)([\s\S]*?\S)__(?!_)|^\*\*(?=\S)([\s\S]*?\S)\*\*(?!\*)/,
        em: /^_(?=\S)([\s\S]*?\S)_(?!_)|^\*(?=\S)([\s\S]*?\S)\*(?!\*)/
    });

    /**
     * GFM Inline Grammar
     */

    inline.gfm = merge({}, inline.normal, {
        escape: replace(inline.escape)('])', '~|])')(),
        url: /^(https?:\/\/[^\s<]+[^<.,:;"')\]\s])/,
        del: /^~~(?=\S)([\s\S]*?\S)~~/,
        text: replace(inline.text)
        (']|', '#@~]|')
        ('|', '|https?://|')
        ('|', '||')
        ()
    });

    /**
     * GFM + Line Breaks Inline Grammar
     */

    inline.breaks = merge({}, inline.gfm, {
        br: replace(inline.br)('{2,}', '*')(),
        text: replace(inline.gfm.text)('{2,}', '*')()
    });

    /**
     * Inline Lexer & Compiler
     */

    function InlineLexer(links, options) {
        this.options = options || marked.defaults;
        this.links = links;
        this.rules = inline.normal;

        if (!this.links) {
            throw new
                Error('Tokens array requires a `links` property.');
        }

        if (this.options.gfm) {
            if (this.options.breaks) {
                this.rules = inline.breaks;
            } else {
                this.rules = inline.gfm;
            }
        } else if (this.options.pedantic) {
            this.rules = inline.pedantic;
        }
    }

    /**
     * Expose Inline Rules
     */

    InlineLexer.rules = inline;

    /**
     * Static Lexing/Compiling Method
     */

    InlineLexer.output = function(src, links, options) {
        var inline = new InlineLexer(links, options);
        return inline.output(src);
    };

    /**
     * Lexing/Compiling
     */

    InlineLexer.prototype.output = function(src) {
        var out = ''
            , link
            , text
            , href
            , cap;

        while (src) {
            // escape
            if (cap = this.rules.escape.exec(src)) {
                src = src.substring(cap[0].length);
                out += cap[1];
                continue;
            }

            // autolink
            if (cap = this.rules.autolink.exec(src)) {
                src = src.substring(cap[0].length);
                if (cap[2] === '@') {
                    text = cap[1][6] === ':'
                        ? this.mangle(cap[1].substring(7))
                        : this.mangle(cap[1]);
                    href = this.mangle('mailto:') + text;
                } else {
                    href = escape(cap[1]);
                    text = shortenUrl(href);
                }
                out += '<a href="'
                    + href
                    + '" target="_blank">'
                    + text
                    + '</a>';
                continue;
            }

            // autolink
            if (cap = this.rules.mail.exec(src)) {
                src = src.substring(cap[0].length);
                if (cap[2] === '@') {
                    text = cap[1][6] === ':'
                        ? this.mangle(cap[1].substring(7))
                        : this.mangle(cap[1]);
                    href = this.mangle('mailto:') + text;
                } else {
                    href = escape(cap[1]);
                    text = shortenUrl(href);
                }
                out += '<a href="'
                    + href
                    + '" target="_blank">'
                    + text
                    + '</a>';
                continue;
            }

            // url (gfm)
            if (cap = this.rules.url.exec(src)) {
                var html;
                src = src.substring(cap[0].length);
                href = escape(cap[1]);
                text = shortenUrl(href);
                for(var key in this.options.urls){
                    html = this.options.urls[key](text, href);
                    if(html){
                        out += html;
                        break;
                    }
                }
                if(!html)
                    out += '<a target="_blank" href="'
                        + href
                        + '" target="_blank">'
                        + text
                        + '</a>';
                continue;
            }

            // tag
            if (cap = this.rules.tag.exec(src)) {
                src = src.substring(cap[0].length);
                out += this.options.sanitize
                    ? escape(cap[0])
                    : cap[0];
                continue;
            }

            // link
            if (cap = this.rules.link.exec(src)) {
                src = src.substring(cap[0].length);
                out += this.outputLink(cap, {
                    href: cap[2],
                    title: cap[3]
                });
                continue;
            }

            // reflink, nolink
            if ((cap = this.rules.reflink.exec(src))
                || (cap = this.rules.nolink.exec(src))) {
                src = src.substring(cap[0].length);
                link = (cap[2] || cap[1]).replace(/\s+/g, ' ');
                link = this.links[link.toLowerCase()];
                if (!link || !link.href) {
                    out += cap[0][0];
                    src = cap[0].substring(1) + src;
                    continue;
                }
                out += this.outputLink(cap, link);
                continue;
            }

            // strong
            if (cap = this.rules.strong.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<strong>'
                    + this.output(cap[2] || cap[1])
                    + '</strong>';
                continue;
            }

            // em
            if (cap = this.rules.em.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<em>'
                    + this.output(cap[2] || cap[1])
                    + '</em>';
                continue;
            }

            // code
            if (cap = this.rules.code.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<code>'
                    + escape(cap[2], true)
                    + '</code>';
                continue;
            }

            // mention
            if (cap = inline.mention.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<span class="link-span" ng-click="vm.goToProfile(\'' + cap[1] + '\')">'
                    + cap[0]
                    + '</span>';
                continue;
            }

            // tags
            if (cap = inline.tags.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<span class="link-span"' + ' ng-click="vm.goToTagTimeline(\'' + cap[1] + '\')">' + cap[0] + '</span>';
                continue;
            }

            // br
            if (cap = this.rules.br.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<br>';
                continue;
            }

            // del (gfm)
            if (cap = this.rules.del.exec(src)) {
                src = src.substring(cap[0].length);
                out += '<del>'
                    + this.output(cap[1])
                    + '</del>';
                continue;
            }

            // text
            if (cap = this.rules.text.exec(src)) {
                src = src.substring(cap[0].length);
                out += escape(cap[0]);
                continue;
            }

            if (src) {
                throw new
                    Error('Infinite loop on byte: ' + src.charCodeAt(0));
            }
        }

        return out;
    };

    /**
     * Compile Link
     */

    InlineLexer.prototype.outputLink = function(cap, link) {
        if (cap[0][0] !== '!') {
            return '<a target="_blank" href="'
                + escape(link.href)
                + '"'
                + (link.title
                    ? ' title="'
                + escape(link.title)
                + '"'
                    : '')
                + '>'
                + this.output(cap[1])
                + '</a>';
        } else {
            return '<img src="'
                + escape(link.href)
                + '" alt="'
                + escape(cap[1])
                + '"'
                + (link.title
                    ? ' title="'
                + escape(link.title)
                + '"'
                    : '')
                + '>';
        }
    };

    /**
     * Mangle Links
     */

    InlineLexer.prototype.mangle = function(text) {
        var out = ''
            , l = text.length
            , i = 0
            , ch;

        for (; i < l; i++) {
            ch = text.charCodeAt(i);
            if (Math.random() > 0.5) {
                ch = 'x' + ch.toString(16);
            }
            out += '&#' + ch + ';';
        }

        return out;
    };

    /**
     * Parsing & Compiling
     */

    function Parser(options) {
        this.tokens = [];
        this.token = null;
        this.options = options || marked.defaults;
    }

    /**
     * Static Parse Method
     */

    Parser.parse = function(src, options) {
        var parser = new Parser(options);
        return parser.parse(src);
    };

    /**
     * Parse Loop
     */

    Parser.prototype.parse = function(src) {
        this.inline = new InlineLexer(src.links, this.options);
        this.tokens = src.reverse();

        var out = '';
        while (this.next()) {
            out += this.tok();
        }

        return out;
    };

    /**
     * Next Token
     */

    Parser.prototype.next = function() {
        return this.token = this.tokens.pop();
    };

    /**
     * Preview Next Token
     */

    Parser.prototype.peek = function() {
        return this.tokens[this.tokens.length-1] || 0;
    };

    /**
     * Parse Text Tokens
     */

    Parser.prototype.parseText = function() {
        var body = this.token.text;

        while (this.peek().type === 'text') {
            body += '\n' + this.next().text;
        }

        return this.inline.output(body);
    };

    /**
     * Parse Current Token
     */

    Parser.prototype.tok = function() {
        switch (this.token.type) {
            case 'space': {
                return '';
            }
            case 'hr': {
                return '<hr>\n';
            }
            case 'heading': {
                return '<h'
                    + this.token.depth
                    + '>'
                    + this.inline.output(this.token.text)
                    + '</h'
                    + this.token.depth
                    + '>\n';
            }
            case 'code': {
                if (this.options.highlight) {
                    var code = this.options.highlight(this.token.text, this.token.lang);
                    if (code != null && code !== this.token.text) {
                        this.token.escaped = true;
                        this.token.text = code;
                    }
                }

                if (!this.token.escaped) {
                    this.token.text = escape(this.token.text, true);
                }

                return '<pre><code'
                    + (this.token.lang
                        ? ' class="'
                    + this.options.langPrefix
                    + this.token.lang
                    + '"'
                        : '')
                    + '>'
                    + this.token.text
                    + '</code></pre>\n';
            }
            case 'table': {
                var body = ''
                    , heading
                    , i
                    , row
                    , cell
                    , j;

                // header
                body += '<thead>\n<tr>\n';
                for (i = 0; i < this.token.header.length; i++) {
                    heading = this.inline.output(this.token.header[i]);
                    body += this.token.align[i]
                        ? '<th align="' + this.token.align[i] + '">' + heading + '</th>\n'
                        : '<th>' + heading + '</th>\n';
                }
                body += '</tr>\n</thead>\n';

                // body
                body += '<tbody>\n'
                for (i = 0; i < this.token.cells.length; i++) {
                    row = this.token.cells[i];
                    body += '<tr>\n';
                    for (j = 0; j < row.length; j++) {
                        cell = this.inline.output(row[j]);
                        body += this.token.align[j]
                            ? '<td align="' + this.token.align[j] + '">' + cell + '</td>\n'
                            : '<td>' + cell + '</td>\n';
                    }
                    body += '</tr>\n';
                }
                body += '</tbody>\n';

                return '<table>\n'
                    + body
                    + '</table>\n';
            }
            case 'blockquote_start': {
                var body = '';

                while (this.next().type !== 'blockquote_end') {
                    body += this.tok();
                }

                return '<blockquote>\n'
                    + body
                    + '</blockquote>\n';
            }
            case 'list_start': {
                var type = this.token.ordered ? 'ol' : 'ul'
                    , body = '';

                while (this.next().type !== 'list_end') {
                    body += this.tok();
                }

                return '<'
                    + type
                    + '>\n'
                    + body
                    + '</'
                    + type
                    + '>\n';
            }
            case 'list_item_start': {
                var body = '';

                while (this.next().type !== 'list_item_end') {
                    body += this.token.type === 'text'
                        ? this.parseText()
                        : this.tok();
                }

                return '<li>'
                    + body
                    + '</li>\n';
            }
            case 'loose_item_start': {
                var body = '';

                while (this.next().type !== 'list_item_end') {
                    body += this.tok();
                }

                return '<li>'
                    + body
                    + '</li>\n';
            }
            case 'html': {
                return !this.token.pre && !this.options.pedantic
                    ? this.inline.output(this.token.text)
                    : this.token.text;
            }
            case 'paragraph': {
                return '<p>'
                    + this.inline.output(this.token.text)
                    + '</p>\n';
            }
            case 'text': {
                return '<p>'
                    + this.parseText()
                    + '</p>\n';
            }
        }
    };

    /**
     * Helpers
     */

    function escape(html, encode) {
        return html
            .replace(!encode ? /&(?!#?\w+;)/g : /&/g, '&amp;')
            .replace(/</g, '&lt;')
            .replace(/>/g, '&gt;')
            .replace(/"/g, '&quot;')
            .replace(/'/g, '&#39;');
    }

    function shortenUrl(url) {
        if (url.length < 67) {
            return url;
        } else {
            return url.substring(0, 64) + "...";
        }
    }

    function replace(regex, opt) {
        regex = regex.source;
        opt = opt || '';
        return function self(name, val) {
            if (!name) return new RegExp(regex, opt);
            val = val.source || val;
            val = val.replace(/(^|[^\[])\^/g, '$1');
            regex = regex.replace(name, val);
            return self;
        };
    }

    function noop() {}
    noop.exec = noop;

    function merge(obj) {
        var i = 1
            , target
            , key;

        for (; i < arguments.length; i++) {
            target = arguments[i];
            for (key in target) {
                if (Object.prototype.hasOwnProperty.call(target, key)) {
                    obj[key] = target[key];
                }
            }
        }

        return obj;
    }

    /**
     * Marked
     */

    function marked(src, opt) {
        try {
            if (opt) opt = merge({}, marked.defaults, opt);
            return Parser.parse(Lexer.lex(src, opt), opt);
        } catch (e) {
            e.message += '\nPlease report this to https://github.com/chjj/marked.';
            if ((opt || marked.defaults).silent) {
                return '<p>An error occured:</p><pre>'
                    + escape(e.message + '', true)
                    + '</pre>';
            }
            throw e;
        }
    }

    /**
     * Options
     */

    marked.options =
        marked.setOptions = function(opt) {
            merge(marked.defaults, opt);
            return marked;
        };

    marked.defaults = {
        gfm: true,
        tables: true,
        breaks: false,
        pedantic: false,
        sanitize: false,
        // urls : [function(text, url){ return 'html'; }]
        smartLists: false,
        silent: false,
        highlight: null,
        langPrefix: 'lang-'
    };

    /**
     * Expose
     */

    marked.Parser = Parser;
    marked.parser = Parser.parse;

    marked.Lexer = Lexer;
    marked.lexer = Lexer.lex;

    marked.InlineLexer = InlineLexer;
    marked.inlineLexer = InlineLexer.output;

    marked.parse = marked;

    if (typeof exports === 'object') {
        module.exports = marked;
    } else if (typeof define === 'function' && define.amd) {
        define(function() { return marked; });
    } else {
        this.marked = marked;
    }

}).call(function() {
    return this || (typeof window !== 'undefined' ? window : global);
}());


================================================
FILE: mobile/www/app/shared/interceptor/auth.interceptor.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .factory('authInterceptor', authInterceptor)
        .factory('authExpiredInterceptor', authExpiredInterceptor)
        .factory('endpointInterceptor', endpointInterceptor);

    authInterceptor.$inject = ['$rootScope', '$q', '$location', '$localStorage'];
    function authInterceptor($rootScope, $q, $location, $localStorage) {
        var interceptor = {
            request: request
        };

        return interceptor;

        request.$inject = ['config'];
        function request(config) {
            config.headers = config.headers || {};
            var token = $localStorage.get('token');

            if (token && token.expires && token.expires > new Date().getTime()) {
                config.headers['x-auth-token'] = token.token;
            }

            return config;
        }
    }

    authExpiredInterceptor.$inject = ['$q', '$localStorage', '$injector'];
    function authExpiredInterceptor($q, $localStorage, $injector) {
        var interceptor = {
            responseError: responseError
        };

        return interceptor;

        responseError.$inject = ['response'];
        function responseError(response) {
            if(response.status === 401 && (response.data.error == 'invalid_token' || response.data.error == 'Unauthorized')) {
                $localStorage.signOut();
                var $state = $injector.get('$state');
                $state.go('login');
            }

            return $q.reject(response);
        }
    }

    /* endpointInterceptor built to replace PathService.buildPath(resource)
     *
     * Old implementation was causing issues - for some reason, REST path requests randomly started getting cached
     * so an attempt to access /rest/authentication wouldn't reach buildPath but would return the endpoint used initially
     * This interceptor never caches, so it's a better implementation.
     * 
     * NOTE: Only make requests to server beginning with "/"; only access documents locally using the first folder and
     * NOT "/"; static url requests (i.e. to google.com) should begin with http://, NEVER "/".
     *
     * ONLY USE "/" AS FIRST CHARACTER OF REQUESTS IF YOU NEED THE ENDPOINT URL TO BE A PREFIX
     */
    endpointInterceptor.$inject = ['$localStorage'];
    function endpointInterceptor($localStorage) {
        var interceptor = {
            request: request
        };

        return interceptor;

        request.$inject = ['config'];
        function request(config) {
            if(config.url.indexOf("/") == 0) {
                config.url = $localStorage.get('endpoint').url + config.url;
            }

            return config;
        }
    }
})();


================================================
FILE: mobile/www/app/shared/providers/provider.js
================================================
(function() {
    'use strict';

    angular.module('tatami.providers', []);

})();


================================================
FILE: mobile/www/app/shared/providers/tatami.state.provider.js
================================================
(function() {
    'use strict';

    // This will dynamically create any tab substates inside the current tab. If in the timeline tab, we will
    // create a timeline.status state
    angular.module('tatami.providers')
        .provider('TatamiState', tatamiState);

    tatamiState.$inject = ['$stateProvider'];
    function tatamiState($stateProvider) {
        this.$get = tatamiStateHelper;

        function tatamiStateHelper() {

            var profileViewConfig = {
                templateUrl: 'app/shared/state/profile/profile.html',
                controller: 'ProfileCtrl',
                controllerAs: 'vm'
            };

            var profileViews = [];
            profileViews['suggested@follow'] = { 'suggested@follow': profileViewConfig };
            profileViews['following@follow'] = { 'following@follow': profileViewConfig };
            profileViews['follower@follow'] = { 'follower@follow': profileViewConfig };
            profileViews['timeline@home'] = { 'timeline@home': profileViewConfig };
            profileViews['mentions@home'] = { 'mentions@home': profileViewConfig };
            profileViews['favorites@home'] = { 'favorites@home': profileViewConfig };
            profileViews['more@home'] = { 'more@home': profileViewConfig };
            profileViews['company@home'] = { 'more@home': profileViewConfig };
            profileViews['blockedusers@home'] = { 'more@home': profileViewConfig };
            profileViews['allusers@home'] = { 'more@home': profileViewConfig };

            var conversationViewConfig = {
                templateUrl: 'app/shared/state/conversation/conversation.html',
                controller: 'ConversationCtrl',
                controllerAs: 'vm'
            };

            var conversationViews = [];
            conversationViews['suggested@follow'] = { 'suggested@follow': conversationViewConfig };
            conversationViews['following@follow'] = { 'following@follow': conversationViewConfig };
            conversationViews['follower@follow'] = { 'follower@follow': conversationViewConfig };
            conversationViews['timeline@home'] = { 'timeline@home': conversationViewConfig };
            conversationViews['mentions@home'] = { 'mentions@home': conversationViewConfig };
            conversationViews['favorites@home'] = { 'favorites@home': conversationViewConfig };
            conversationViews['company@home'] = { 'more@home': conversationViewConfig };
            conversationViews['blockedusers@home'] = { 'more@home': profileViewConfig };
            conversationViews['allusers@home'] = { 'more@home': profileViewConfig };

            var tagViewConfig = {
                templateUrl: 'app/shared/state/tag/tag.html',
                controller: 'TagCtrl',
                controllerAs: 'vm'
            };

            var tagViews = [];
            tagViews['suggested@follow'] = { 'suggested@follow': tagViewConfig };
            tagViews['following@follow'] = { 'following@follow': tagViewConfig };
            tagViews['follower@follow'] = { 'follower@follow': tagViewConfig };
            tagViews['timeline@home'] = { 'timeline@home': tagViewConfig };
            tagViews['mentions@home'] = { 'mentions@home': tagViewConfig };
            tagViews['favorites@home'] = { 'favorites@home': tagViewConfig };
            tagViews['company@home'] = { 'more@home': tagViewConfig };
            tagViews['blockedusers@home'] = { 'more@home': profileViewConfig };
            tagViews['allusers@home'] = { 'more@home': profileViewConfig };

            var service = {
                addProfileState: addProfileState,
                addConversationState: addConversationState,
                addTagState: addTagState
            };

            addProfileState.$inject = ['prefixName', 'parentName'];
            function addProfileState(prefixName, parentName) {
                $stateProvider.state(prefixName + '.profile', {
                    url: '/profile/:username',
                    views: profileViews[prefixName + '@' + parentName],
                    resolve: {
                        user: getUser,
                        statuses: getStatuses,
                        currentUser: getCurrentUser
                    }
                });

                getUser.$inject = ['UserService', '$stateParams'];
                function getUser(UserService, $stateParams) {
                    return UserService.get({ username : $stateParams.username }).$promise;
                }

                getStatuses.$inject = ['user', 'StatusService'];
                function getStatuses(user, StatusService) {
                    return StatusService.getUserTimeline({ username: user.username }).$promise;
                }

                getCurrentUser.$inject = ['currentUser'];
                function getCurrentUser(currentUser) {
                    return currentUser;
                }
            }

            addConversationState.$inject = ['prefixName', 'parentName'];
            function addConversationState(prefixName, parentName) {
                $stateProvider.state(prefixName + '.conversation', {
                    url: '/conversation/:statusId',
                    views: conversationViews[prefixName + '@' + parentName],
                    resolve: {
                        originalStatus: getOriginalStatus,
                        conversation: getConversation
                    }
                });

                getOriginalStatus.$inject = ['StatusService', '$stateParams'];
                function getOriginalStatus(StatusService, $stateParams) {
                    return StatusService.get({ statusId : $stateParams.statusId }).$promise;
                }

                getConversation.$inject = ['StatusService', '$stateParams'];
                function getConversation(StatusService, $stateParams) {
                    return StatusService.getDetails({ statusId : $stateParams.statusId }).$promise;
                }
            }

            addTagState.$inject = ['prefixName', 'parentName'];
            function addTagState(prefixName, parentName) {
                $stateProvider.state(prefixName + '.tag', {
                    url: '/tag/:tag',
                    views: tagViews[prefixName + '@' + parentName],
                    resolve: {
                        tag: getTag,
                        statuses: getStatuses
                    }
                });

                getTag.$inject = ['$stateParams'];
                function getTag($stateParams) {
                    return $stateParams.tag;
                }

                getStatuses.$inject = ['TagService', '$stateParams'];
                function getStatuses(TagService, $stateParams) {
                    return TagService.getTagTimeline({ tag: $stateParams.tag }).$promise;
                }
            }

            return service;

        }
    }

})();


================================================
FILE: mobile/www/app/shared/services/HomeService.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('HomeService', homeService);

    homeService.$inject = ['$resource', 'PathService'];
    function homeService($resource, PathService) {
        return $resource(null, null,
            {
                'getMentions': {
                    method: 'GET', isArray: true, url: '/tatami/rest/mentions',
                    transformResponse: responseTransform
                },
                'getFavorites': {
                    method: 'GET', isArray: true, url: '/tatami/rest/favorites',
                    transformResponse: responseTransform
                },
                'getCompanyTimeline': {
                    method: 'GET', isArray: true, url: '/tatami/rest/company',
                    transformResponse: responseTransform
                }
            });

        responseTransform.$inject = ['statuses'];
        function responseTransform(statuses) {
            statuses = angular.fromJson(statuses);

            for(var i = 0; i < statuses.length; i++) {
                statuses[i]['avatarURL'] = PathService.getAvatar(statuses[i]);

                if(statuses[i].geoLocalization) {
                    var latitude = statuses[i].geoLocalization.split(',')[0].trim();
                    var longitude = statuses[i].geoLocalization.split(',')[1].trim();
                    statuses[i]['locationURL'] =
                        'https://www.openstreetmap.org/?mlon='
                        + longitude + '&mlat=' + latitude;
                }
            }

            return statuses;
        }
    }
})();


================================================
FILE: mobile/www/app/shared/services/ProfileService.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('ProfileService', profileService);

    profileService.$inject = ['$resource', 'PathService'];

    function profileService($resource, PathService) {
        return $resource('/tatami/rest/account/profile', null,
            {
                'get': {
                    method: 'GET',
                    transformResponse: function (profile) {
                        profile = angular.fromJson(profile);
                        profile['avatarURL'] = PathService.getAvatar(profile);
                        return profile;
                    }
                },
                'update': {
                    method: 'PUT',
                    transformRequest: function (profile) {
                        delete profile['avatarURL'];
                        return angular.toJson(profile);
                    }
                }
            });
    }
})();


================================================
FILE: mobile/www/app/shared/services/StatusService.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('StatusService', statusService);

    statusService.$inject = ['$resource', 'PathService'];
    function statusService($resource, PathService) {
        var responseTransform = function (statuses) {
            statuses = angular.fromJson(statuses);

            for (var i = 0; i < statuses.length; i++) {
                statuses[i]['avatarURL'] = PathService.getAvatar(statuses[i]);

                if (statuses[i].geoLocalization) {
                    var latitude = statuses[i].geoLocalization.split(',')[0].trim();
                    var longitude = statuses[i].geoLocalization.split(',')[1].trim();
                    statuses[i]['locationURL'] =
                        'https://www.openstreetmap.org/?mlon='
                        + longitude + '&mlat=' + latitude;
                }
            }

            return statuses;
        };
        return $resource('/tatami/rest/statuses/:statusId', null,
            {
                'get': {
                    method: 'GET',
                    cache: false,
                    transformResponse: function (status) {
                        status = angular.fromJson(status);

                        status.avatarURL = PathService.getAvatar(status);

                        if (status.geoLocalization) {
                            var latitude = status.geoLocalization.split(',')[0].trim();
                            var longitude = status.geoLocalization.split(',')[1].trim();
                            status['locationURL'] =
                                'https://www.openstreetmap.org/?mlon='
                                + longitude + '&mlat=' + latitude;
                        }

                        return status;
                    }
                },
                'getHomeTimeline': {
                    method: 'GET',
                    isArray: true,
                    url: '/tatami/rest/statuses/home_timeline',
                    cache: false,
                    transformResponse: responseTransform
                },
                'getUserTimeline': {
                    method: 'GET',
                    isArray: true,
                    params: {username: '@username'},
                    url: '/tatami/rest/statuses/:username/timeline',
                    cache: false,
                    transformResponse: responseTransform
                },
                'getDetails': {
                    method: 'GET',
                    params: {statusId: '@statusId'},
                    url: '/tatami/rest/statuses/details/:statusId',
                    cache: false,
                    transformResponse: function (details) {
                        details = angular.fromJson(details);

                        for (var i = 0; i < details.discussionStatuses.length; i++) {
                            details.discussionStatuses[i]['avatarURL'] = PathService.getAvatar(details.discussionStatuses[i]);

                            if (details.discussionStatuses[i].geoLocalization) {
                                var latitude = details.discussionStatuses[i].geoLocalization.split(',')[0].trim();
                                var longitude = details.discussionStatuses[i].geoLocalization.split(',')[1].trim();
                                details.discussionStatuses[i]['locationURL'] =
                                    'https://www.openstreetmap.org/?mlon='
                                    + longitude + '&mlat=' + latitude;
                            }
                        }

                        for (var i = 0; i < details.sharedByLogins.length; i++) {
                            details.sharedByLogins[i]['avatarURL'] = PathService.getAvatar(details.sharedByLogins[i]);
                        }

                        return details;
                    }
                },
                'update': {method: 'PATCH', cache: false, params: {statusId: '@statusId'}},
                'announce': {method: 'PATCH', cache: false, params: {params: '@statusId'}},
                'hideStatus': {
                    method: 'POST',
                    params: {statusId: '@statusId'},
                    cache: false,
                    url: '/tatami/rest/statuses/hide/:statusId'
                }
            });

    }
})();


================================================
FILE: mobile/www/app/shared/services/UserService.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('UserService', userService);

    userService.$inject = ['$resource', 'PathService'];
    function userService($resource, PathService) {
        var responseTransform = function (users) {
            users = angular.fromJson(users);

            for (var i = 0; i < users.length; i++) {
                users[i]['avatarURL'] = PathService.getAvatar(users[i]);
            }

            return users;
        };
        return $resource('/tatami/rest/users/:username', null,
            {
                'get': {
                    method: 'GET', params: {username: '@username'},
                    cache: false,
                    transformResponse: function (user) {
                        user = angular.fromJson(user);
                        user['avatarURL'] = PathService.getAvatar(user);
                        return user;
                    }
                },
                'query': {
                    method: 'GET',
                    isArray: true,
                    url: '/tatami/rest/users',
                    transformResponse: responseTransform
                },
                'getFollowing': {
                    method: 'GET',
                    isArray: true,
                    params: {username: '@username'},
                    url: '/tatami/rest/users/:username/friends',
                    transformResponse: responseTransform
                },
                'getFollowers': {
                    method: 'GET',
                    isArray: true,
                    params: {username: '@username'},
                    url: '/tatami/rest/users/:username/followers',
                    transformResponse: responseTransform
                },
                'getSuggestions': {
                    method: 'GET',
                    isArray: true,
                    url: '/tatami/rest/users/suggestions',
                    transformResponse: function (suggestions) {
                        suggestions = angular.fromJson(suggestions);

                        for (var i = 0; i < suggestions.length; i++) {
                            suggestions[i]['avatarURL'] = PathService.getAvatar(suggestions[i]);
                            suggestions[i]['followingUser'] = false;
                        }

                        return suggestions;
                    }
                },
                'follow': {
                    method: 'PATCH',
                    params: {username: '@username'}
                },
                'searchUsers': {
                    method: 'GET',
                    isArray: true,
                    url: '/tatami/rest/users/:term',
                    transformResponse: responseTransform
                },
                'deactivate': {
                    method: 'PATCH',
                    params: {username: '@username'}
                }
            });
    }
})();


================================================
FILE: mobile/www/app/shared/services/account.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('AccountService', accountService);

    accountService.$inject = ['$resource', 'PathService'];
    function accountService($resource, PathService) {

        return $resource('/tatami/rest/account/admin', null, null);
    }

})();


================================================
FILE: mobile/www/app/shared/services/block.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('BlockService', blockService);

    blockService.$inject = ['$resource', 'PathService'];
    function blockService($resource, PathService) {

        var responseTransform = function (users) {
            users = angular.fromJson(users);

            for (var i = 0; i < users.length; i++) {
                users[i]['avatarURL'] = PathService.getAvatar(users[i]);
            }
            return users;
        };

        return $resource(null, null,
            {
                'getBlockedUsersForUser': {
                    method: 'GET',
                    isArray: true,
                    params: {username: '@username'},
                    url: '/tatami/rest/block/blockedusers/:username',
                    transformResponse: responseTransform
                },
                'updateBlockedUser': {
                    method: 'PATCH',
                    params: { username: '@username'},
                    url: '/tatami/rest/block/update/:username',
                    transformResponse: function (blockedUser) {
                        blockedUser = angular.fromJson(blockedUser);
                        return blockedUser;
                    }
                }
            });

    }

})();


================================================
FILE: mobile/www/app/shared/services/localStorage.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('$localStorage', localStorage);

    localStorage.$inject = ['$window'];
    function localStorage($window) {
        var service = {
            get: getFromLocalStorage,
            set: setFromLocalStorage,
            signOut: clearToken
        };

        return service;

        getFromLocalStorage.$inject = ['key'];
        function getFromLocalStorage(key) {
            if(isLocalStorageUndefined(key)) {
                return undefined;
            }
            return JSON.parse($window.localStorage[key] || '{}');
        }

        setFromLocalStorage.$inject = ['key', 'value'];
        function setFromLocalStorage(key, value) {
            $window.localStorage[key] = JSON.stringify(value);
        }

        function clearToken() {
            $window.localStorage.removeItem('token');
        }

        isLocalStorageUndefined.$inject = ['key'];
        function isLocalStorageUndefined(key) {
            return $window.localStorage.length === 0 || $window.localStorage[key] === 'undefined';
        }
    }
})();


================================================
FILE: mobile/www/app/shared/services/path.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('PathService', avatarService);

    avatarService.$inject = ['TatamiEndpoint'];
    function avatarService(TatamiEndpoint) {
        var service = {
            getAvatar: getAvatar
        };

        return service;

        getAvatar.$inject = ['user'];
        function getAvatar(user) {
            return TatamiEndpoint.getEndpoint().url + (user.avatar && user.avatar !== '' ? '/tatami/avatar/' + user.avatar + '/photo.jpg' : '/assets/img/default_image_profile.png');
        }

        //buildPath() removed - REST endpoints being accessed were being cached, leading to issues when swapping endpoints
        //new implementation intercepts url requests beginning with "/" and tacks on the current endpoint url as a prefix
    }
})();


================================================
FILE: mobile/www/app/shared/services/report.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('ReportService', reportService);

    reportService.$inject = ['$resource', 'PathService'];
    function reportService($resource, PathService) {

        var responseTransform = function (statuses) {
            statuses = angular.fromJson(statuses);

            for (var i = 0; i < statuses.length; i++) {
                statuses[i]['avatarURL'] = PathService.getAvatar(statuses[i]);

            }

            return statuses;
        };

        return $resource('/tatami/rest/statuses/report/:statusId', null,
            {
                'reportStatus': {
                    method: 'POST',
                    params: {statusId: '@statusId'}
                },
                'getReportedStatuses': {
                    method: 'GET',
                    isArray: true,
                    url: '/tatami/rest/statuses/report/reportedList',
                    transformResponse: responseTransform
                },
                'approveStatus': {
                    method : 'DELETE',
                    params: {statusId: '@statusId'}
                },
                'deleteStatus': {
                    method: 'PUT',
                    params: {statusId: '@statusId'}
                }
            });
    }
})();


================================================
FILE: mobile/www/app/shared/services/service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services', []);

})();


================================================
FILE: mobile/www/app/shared/services/tag.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('TagService', tagService);

    tagService.$inject = ['$resource', 'PathService'];
    function tagService($resource, PathService) {
        return $resource('/tatami/rest/tags', null,
            {
                'get': { method:'GET', params: { tag: '@tag' }, url: '/tatami/rest/tags/:tag' },
                'getTagTimeline': {
                    method:'GET', isArray: true, params: { tag: '@tag' }, url: '/tatami/rest/tags/:tag/tag_timeline',
                    transformResponse: function(statuses) {
                        statuses = angular.fromJson(statuses);

                        for(var i = 0; i < statuses.length; i++) {
                            statuses[i]['avatarURL'] = PathService.getAvatar(statuses[i]);

                            if(statuses[i].geoLocalization) {
                                var latitude = statuses[i].geoLocalization.split(',')[0].trim();
                                var longitude = statuses[i].geoLocalization.split(',')[1].trim();
                                statuses[i]['locationURL'] =
                                    'https://www.openstreetmap.org/?mlon='
                                    + longitude + '&mlat=' + latitude;
                            }
                        }

                        return statuses;
                    }
                },
                'follow': { method:'PUT', params: { tag: '@tag' }, url: '/tatami/rest/tags/:tag' },
                'getPopular': { method: 'GET', isArray: true, url: '/tatami/rest/tags/popular' }
            });
    }
})();


================================================
FILE: mobile/www/app/shared/services/toast.service.js
================================================
(function() {
    'use strict';

    angular.module('tatami.services')
        .factory('ToastService', ToastService);

    ToastService.$inject = ['$window', '$translate', 'ionicToast'];
    function ToastService($window, $translate, ionicToast) {

        var service = {
            display: displayToast
        };

        return service;

        function displayToast(toastMessage){
            $translate(toastMessage).then(function(msg){
                if (ionic.Platform.isIOS()){
                    ionicToast.show(msg, 'top', false, 2000);
                }
                else{
                    ionicToast.show(msg, 'bottom', false, 2000);
                }
            });
        }

    }
})();


================================================
FILE: mobile/www/app/shared/state/conversation/conversation.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('ConversationCtrl', conversationCtrl);

    conversationCtrl.$inject = ['$ionicPopup', '$ionicHistory', '$state', 'originalStatus', 'conversation', 'currentUser'];
    function conversationCtrl($ionicPopup, $ionicHistory, $state, originalStatus, conversation, currentUser) {
        var vm = this;
        vm.conversation = buildStatusList();
        vm.currentUser = currentUser;

        function buildStatusList() {
            try {
                return conversation.discussionStatuses.concat(originalStatus).sort(byDate);
            } catch (error) {
                var deletedPopup = $ionicPopup.alert({
                    title: 'Status Not Found!',
                    template: 'The original status has been deleted. <br>Returning to previous state.'
                });

                deletedPopup.then(goBack);
            }
        }

        function goBack() {
            $ionicHistory.goBack();
        }

        byDate.$inject = ['first', 'second'];
        function byDate(first, second) {
            return first.statusDate - second.statusDate;
        }
    }
})();


================================================
FILE: mobile/www/app/shared/state/conversation/conversation.html
================================================
<ion-view view-title="{{ 'conversation.title' | translate }}">
        <tatami-status-list statuses="vm.conversation"
                            current-user="vm.currentUser"></tatami-status-list>
</ion-view>


================================================
FILE: mobile/www/app/shared/state/profile/profile.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('ProfileCtrl', profileCtrl);

    profileCtrl.$inject = ['$ionicPopover', '$ionicPopup', '$scope', '$translate', 'user', 'statuses', 'currentUser', 'TatamiStatusRefresherService', 'UserService', 'BlockService'];
    function profileCtrl($ionicPopover, $ionicPopup, $scope, $translate, user, statuses, currentUser, TatamiStatusRefresherService, UserService, BlockService) {
        var vm = this;
        vm.user = user;
        vm.statuses = statuses;
        vm.currentUser = currentUser;
        vm.isCurrentUser = (vm.currentUser.username === vm.user.username);
        vm.customHeight = (vm.currentUser.isAdmin) ? {'height': '120px'} : {'height': '70px'}; //Adapts the height of the popover depending on the role because a different number of buttons is displayed

        vm.followUser = followUser;
        vm.getNewStatuses = getNewStatuses;
        vm.toggleActivateUser = toggleActivateUser;
        vm.blockUser = blockUser;

        function getNewStatuses() {
            return TatamiStatusRefresherService.refreshUserTimeline(user).then(setStatuses);
        }

        setStatuses.$inject = ['statuses'];
        function setStatuses(statuses) {
            vm.statuses = statuses;
        }

        function followUser() {
            UserService.follow({ username : vm.user.username }, { friend: !vm.user.friend, friendShip: true },
                function() {
                    vm.user.friend = !vm.user.friend;
                });
        }

        function toggleActivateUser() {
            var confirmPopup;
            if (vm.user.activated) {
                confirmPopup = $ionicPopup.confirm({
                    title: $translate.instant('user.deactivate.title'),
                    template: '<span translate="user.deactivate.confirmation"></span>'
                });
            } else {
                confirmPopup = $ionicPopup.confirm({
                    title: $translate.instant('user.reactivate.title'),
                    template: '<span translate="user.reactivate.confirmation"></span>'
                });
            }

            confirmPopup.then(checkDelete);

            checkDelete.$inject = ['decision'];
            function checkDelete(decision) {
                if(decision) {
                    UserService.deactivate({ username : vm.user.username }, {activate: true},
                        function() {
                            vm.user.activated = !vm.user.activated;
                        });
                }
            }
        }

        function blockUser() {
            var confirmPopup = $ionicPopup.confirm({
                title: $translate.instant('user.block.title'),
                template: '<span translate="user.block.confirmation"></span>'
            });

            confirmPopup.then(checkDelete);

            checkDelete.$inject = ['decision'];
            function checkDelete(decision) {
                if(decision) {
                    BlockService.updateBlockedUser( {username: vm.user.username }, function () {
                            ToastService.display('user.block.success');
                        }
                    );
                }
            }

        }

        $ionicPopover.fromTemplateUrl('app/shared/state/profile/userOptionsMenu.html', {
            scope: $scope
        }).then(function(popover) {
            $scope.popover = popover;
        });
    }
})();


================================================
FILE: mobile/www/app/shared/state/profile/profile.html
================================================
<ion-view view-title="@{{ vm.user.username }}">
    <ion-nav-buttons side="secondary">
        <button class="button ion-gear-a"
                ng-if="!vm.isCurrentUser"
                style="font-size: 30px;"
                ng-click="popover.show($event)"></button>
        <button class="button ion-person-add"
                ng-if="!vm.isCurrentUser"
                ng-class="{ 'button-calm' : vm.user.friend, 'button-stable button-outline' : !vm.user.friend }"
                style="font-size: 30px;"
                ng-click="vm.followUser()"></button>
    </ion-nav-buttons>
    <ion-content class="tatami-header tatami-footer" ng-style="{'background-color':'#f5f5f5'}">
        <ion-refresher on-refresh="vm.getNewStatuses()"></ion-refresher>
        <tatami-user-detail user="vm.user"></tatami-user-detail>
        <ion-list>
            <ion-item ng-repeat="status in vm.statuses">
                <tatami-status status="status" current-user="vm.currentUser"></tatami-status>
            </ion-item>
        </ion-list>
    </ion-content>
</ion-view>


================================================
FILE: mobile/www/app/shared/state/profile/userOptionsMenu.html
================================================
<ion-popover-view ng-style="vm.customHeight" scroll="false">
    <ion-content>
        <div class="list" ng-click="popover.hide()">
            <a class="item assertive" target="_blank" ng-click="vm.blockUser()">
                <span class="ion-close-circled padding-right"></span>
                <span translate="user.profile.options.block"></span>
            </a>
            <a class="item assertive" ng-if="vm.currentUser.isAdmin && vm.user.activated" ng-click="vm.toggleActivateUser()" >
                <span class="ion-trash-a padding-right"></span>
                <span translate="user.profile.options.deactivate"></span>
            </a>
            <a class="item calm" ng-if="vm.currentUser.isAdmin && !vm.user.activated" ng-click="vm.toggleActivateUser()" >
                <span class="ion-trash-a padding-right"></span>
                <span translate="user.profile.options.reactivate"></span>
            </a>
        </div>
    </ion-content>
</ion-popover-view>


================================================
FILE: mobile/www/app/shared/state/tag/tag.controller.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .controller('TagCtrl', tagCtrl);

    tagCtrl.$inject = ['tag', 'statuses', 'currentUser', 'TatamiStatusRefresherService'];
    function tagCtrl(tag, statuses, currentUser, TatamiStatusRefresherService) {
        var vm = this;
        vm.tag = tag;
        vm.statuses = statuses;
        vm.currentUser = currentUser;
        vm.getNewStatuses = getNewStatuses;
        vm.getOldStatuses = getOldStatuses;

        function getNewStatuses() {
            return TatamiStatusRefresherService.refreshTagTimeline(vm.tag);
        }

        getOldStatuses.$inject = ['finalStatus'];
        function getOldStatuses(finalStatus) {
            return TatamiStatusRefresherService.getOldTags(finalStatus, vm.tag)
        }
    }
})();


================================================
FILE: mobile/www/app/shared/state/tag/tag.html
================================================
<ion-view view-title="#{{ vm.tag }}">
    <tatami-status-list statuses="vm.statuses"
                        current-user="vm.currentUser"
                        tatami-refresher="vm.getNewStatuses()"
                        tatami-infinite-refresher="vm.getOldStatuses(finalStatus)"></tatami-status-list>
</ion-view>


================================================
FILE: mobile/www/app/shared/status/blockUserMenu.html
================================================
<ion-popover-view ng-style="vm.customHeight">
    <ion-content>
        <div class="list" ng-click="popover.hide()">
            <a class="item"  ng-if="vm.currentUser.isAdmin" ng-click="vm.announceStatus()" >
                <span class="ion-speakerphone padding-right"></span>
                <span class="right" translate="status.announcement.action"></span>
            </a>
            <a class="item" target="_blank" ng-click="vm.hideStatus()">
                <span class="ion-minus-round padding-right"></span>
                <span translate="status.hide.action" right></span>
            </a>
            <a class="item" target="_blank" ng-click="vm.reportStatus()">
                <span class="ion-alert padding-right"></span>
                <span class="html-editor-align-right" translate="status.block.reportStatus"></span>
            </a>
            <a class="item" target="_blank" ng-click="vm.blockUser()">
                <span class="ion-close-circled padding-right"></span>
                <span translate="status.block.blockUser"></span>
            </a>
            <a class="item assertive" ng-if="vm.currentUser.isAdmin" ng-click="vm.remove()" >
                <span class="ion-trash-a padding-right"></span>
                <span translate="status.block.delete"></span>
            </a>
        </div>
    </ion-content>
</ion-popover-view>


================================================
FILE: mobile/www/app/shared/status/list/status-list.html
================================================
<ion-content class="tatami-header tatami-footer">
    <ion-refresher ng-if="!vm.$state.includes('*.conversation')" on-refresh="vm.getNewStatuses()"></ion-refresher>
    <ion-list>
        <ion-item ng-repeat="status in vm.statuses">
            <tatami-status status="status" current-user="vm.currentUser" on-delete="vm.remove(status)"></tatami-status>
        </ion-item>
        <div class="text-center" ng-if="!vm.statuses.length" translate="status.noContent" ng-style="{'color':'#ababab','padding':'40px'}"/>
    </ion-list>
    <ion-infinite-scroll ng-if="!vm.finishedTimeline && !vm.$state.includes('*.conversation')" on-infinite="vm.getNewInfiniteScrollStatuses()"></ion-infinite-scroll>
</ion-content>


================================================
FILE: mobile/www/app/shared/status/list/status.list.directive.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .directive('tatamiStatusList', tatamiStatusList);

    function tatamiStatusList() {
        var directive = {
            restrict: 'E',
            scope: {
                statuses: '=',
                currentUser: '=',
                tatamiRefresher: '&',
                tatamiInfiniteRefresher: '&'
            },
            controller: controller,
            controllerAs: 'vm',
            templateUrl: 'app/shared/status/list/status-list.html'
        };

        return directive;
    }

    controller.$inject = ['$scope', '$state'];
    function controller($scope, $state) {
        var vm = this;
        vm.statuses = $scope.statuses;
        vm.currentUser = $scope.currentUser;
        vm.$state = $state;
        vm.getNewStatuses = getNewStatuses;
        vm.getNewInfiniteScrollStatuses = getNewInfiniteScrollStatuses;
        vm.remove = remove;
        vm.finishedTimeline = vm.statuses && vm.statuses.length < 20;

        function getNewStatuses() {
            $scope.tatamiRefresher().then(setStatuses);
        }

        function getNewInfiniteScrollStatuses() {
            if(vm.statuses && vm.statuses.length > 0) {
                var lastStatus = vm.statuses[vm.statuses.length - 1].timelineId;
                $scope.tatamiInfiniteRefresher({ finalStatus: lastStatus }).then(addNewStatuses);
            }
        }

        remove.$inject = ['status'];
        function remove(status) {
            vm.statuses.splice(vm.statuses.indexOf(status), 1);
        }

        setStatuses.$inject = ['statuses'];
        function setStatuses(statuses) {
            vm.statuses = statuses;
        }

        addNewStatuses.$inject = ['oldStatuses'];
        function addNewStatuses(oldStatuses) {
            if(oldStatuses.length === 0) {
                vm.finishedTimeline = true;
            }

            vm.statuses.push.apply(vm.statuses, oldStatuses);
        }
    }
})();


================================================
FILE: mobile/www/app/shared/status/status.directive.js
================================================
(function() {
    'use strict';

    angular.module('tatami')
        .directive('tatamiStatus', tatamiStatus);

    function tatamiStatus() {
        var directive = {
            restrict: 'E',
            scope: {
                status: '=',
                currentUser: '=',
           
Download .txt
gitextract_2urwtjut/

├── .gitignore
├── CONTRIBUTING.md
├── README.md
├── etc/
│   └── installation/
│       └── ubuntu/
│           ├── files/
│           │   └── maven/
│           │       └── settings.xml
│           ├── install.sh
│           ├── uninstall.sh
│           └── update.sh
├── jenkinsScripts/
│   ├── insertGoogleAuthKeys.sh
│   ├── restoreDatabase.sh
│   ├── saveDatabase.sh
│   ├── startTatami.sh
│   └── stopTatami.sh
├── mobile/
│   ├── .bowerrc
│   ├── .editorconfig
│   ├── .gitignore
│   ├── README.md
│   ├── bower.json
│   ├── config.xml
│   ├── gulpfile.js
│   ├── hooks/
│   │   ├── README.md
│   │   └── after_prepare/
│   │       └── 010_add_platform_class.js
│   ├── ionic.project
│   ├── karma.ci.conf.js
│   ├── package.json
│   ├── pom.xml
│   ├── resources/
│   │   ├── icon.psd
│   │   └── splash.psd
│   ├── scss/
│   │   └── ionic.app.scss
│   └── www/
│       ├── app/
│       │   ├── components/
│       │   │   ├── follow/
│       │   │   │   ├── follow.html
│       │   │   │   ├── follow.js
│       │   │   │   ├── follower/
│       │   │   │   │   ├── follower.controller.js
│       │   │   │   │   ├── follower.html
│       │   │   │   │   └── follower.js
│       │   │   │   ├── following/
│       │   │   │   │   ├── following.controller.js
│       │   │   │   │   ├── following.html
│       │   │   │   │   └── following.js
│       │   │   │   └── suggested/
│       │   │   │       ├── suggested.controller.js
│       │   │   │       ├── suggested.html
│       │   │   │       └── suggested.js
│       │   │   ├── home/
│       │   │   │   ├── favorites/
│       │   │   │   │   ├── favorites.controller.js
│       │   │   │   │   ├── favorites.html
│       │   │   │   │   └── favorites.js
│       │   │   │   ├── home.html
│       │   │   │   ├── home.js
│       │   │   │   ├── mentions/
│       │   │   │   │   ├── mentions.controller.js
│       │   │   │   │   ├── mentions.html
│       │   │   │   │   └── mentions.js
│       │   │   │   ├── more/
│       │   │   │   │   ├── all_users/
│       │   │   │   │   │   ├── all.users.controller.js
│       │   │   │   │   │   ├── all.users.html
│       │   │   │   │   │   └── all.users.js
│       │   │   │   │   ├── blocked_users/
│       │   │   │   │   │   ├── blocked.users.controller.js
│       │   │   │   │   │   ├── blocked.users.html
│       │   │   │   │   │   └── blocked.users.js
│       │   │   │   │   ├── company/
│       │   │   │   │   │   ├── company-timeline.html
│       │   │   │   │   │   ├── company.timeline.controller.js
│       │   │   │   │   │   └── company.timeline.js
│       │   │   │   │   ├── more.controller.js
│       │   │   │   │   ├── more.html
│       │   │   │   │   ├── more.js
│       │   │   │   │   ├── reportedStatus/
│       │   │   │   │   │   ├── reportedStatus.controller.js
│       │   │   │   │   │   ├── reportedStatus.html
│       │   │   │   │   │   └── reportedStatus.js
│       │   │   │   │   └── settings/
│       │   │   │   │       ├── settings.controller.js
│       │   │   │   │       ├── settings.html
│       │   │   │   │       └── settings.js
│       │   │   │   └── timeline/
│       │   │   │       ├── timeline.controller.js
│       │   │   │       ├── timeline.html
│       │   │   │       └── timeline.js
│       │   │   ├── login/
│       │   │   │   ├── login.controller.js
│       │   │   │   ├── login.html
│       │   │   │   ├── login.js
│       │   │   │   └── server/
│       │   │   │       ├── server.controller.js
│       │   │   │       ├── server.html
│       │   │   │       └── server.js
│       │   │   └── post/
│       │   │       ├── post.controller.js
│       │   │       ├── post.html
│       │   │       ├── post.js
│       │   │       └── postbar.directive.js
│       │   ├── shared/
│       │   │   ├── config/
│       │   │   │   ├── marked.config.js
│       │   │   │   ├── marked.filter.js
│       │   │   │   └── tatami.marked.js
│       │   │   ├── interceptor/
│       │   │   │   └── auth.interceptor.js
│       │   │   ├── providers/
│       │   │   │   ├── provider.js
│       │   │   │   └── tatami.state.provider.js
│       │   │   ├── services/
│       │   │   │   ├── HomeService.js
│       │   │   │   ├── ProfileService.js
│       │   │   │   ├── StatusService.js
│       │   │   │   ├── UserService.js
│       │   │   │   ├── account.service.js
│       │   │   │   ├── block.service.js
│       │   │   │   ├── localStorage.service.js
│       │   │   │   ├── path.service.js
│       │   │   │   ├── report.service.js
│       │   │   │   ├── service.js
│       │   │   │   ├── tag.service.js
│       │   │   │   └── toast.service.js
│       │   │   ├── state/
│       │   │   │   ├── conversation/
│       │   │   │   │   ├── conversation.controller.js
│       │   │   │   │   └── conversation.html
│       │   │   │   ├── profile/
│       │   │   │   │   ├── profile.controller.js
│       │   │   │   │   ├── profile.html
│       │   │   │   │   └── userOptionsMenu.html
│       │   │   │   └── tag/
│       │   │   │       ├── tag.controller.js
│       │   │   │       └── tag.html
│       │   │   ├── status/
│       │   │   │   ├── blockUserMenu.html
│       │   │   │   ├── list/
│       │   │   │   │   ├── status-list.html
│       │   │   │   │   └── status.list.directive.js
│       │   │   │   ├── status.directive.js
│       │   │   │   ├── status.html
│       │   │   │   └── status.refresher.service.js
│       │   │   └── user/
│       │   │       ├── user-detail.html
│       │   │       ├── user.detail.directive.js
│       │   │       ├── user.directive.js
│       │   │       ├── user.html
│       │   │       ├── user.refresher.service.js
│       │   │       ├── users.directive.js
│       │   │       └── users.html
│       │   ├── tatami.controller.js
│       │   ├── tatami.endpoint.js
│       │   ├── tatami.html
│       │   └── tatamiApp.js
│       ├── css/
│       │   ├── ionic.app.css
│       │   └── style.css
│       ├── i18n/
│       │   ├── en/
│       │   │   ├── conversation.json
│       │   │   ├── follow.json
│       │   │   ├── home.json
│       │   │   ├── login.json
│       │   │   ├── more.json
│       │   │   ├── post.json
│       │   │   ├── server.json
│       │   │   ├── status.json
│       │   │   └── user.json
│       │   └── fr/
│       │       ├── conversation.json
│       │       ├── follow.json
│       │       ├── home.json
│       │       ├── login.json
│       │       ├── more.json
│       │       ├── post.json
│       │       ├── server.json
│       │       ├── status.json
│       │       └── user.json
│       ├── index.html
│       └── test/
│           └── javascript/
│               └── components/
│                   └── profile/
│                       └── profile.controller.spec.js
├── pom.xml
├── scripts/
│   └── insertBuildVersion.sh
├── services/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   ├── fr/
│       │   │   │   └── ippon/
│       │   │   │       └── tatami/
│       │   │   │           ├── config/
│       │   │   │           │   ├── ApplicationConfiguration.java
│       │   │   │           │   ├── AsyncConfiguration.java
│       │   │   │           │   ├── CacheConfiguration.java
│       │   │   │           │   ├── CassandraConfiguration.java
│       │   │   │           │   ├── ColumnFamilyKeys.java
│       │   │   │           │   ├── Constants.java
│       │   │   │           │   ├── DispatcherServletConfig.java
│       │   │   │           │   ├── GroupRoles.java
│       │   │   │           │   ├── MailConfiguration.java
│       │   │   │           │   ├── MetricsConfiguration.java
│       │   │   │           │   ├── SearchConfiguration.java
│       │   │   │           │   └── metrics/
│       │   │   │           │       ├── CassandraHealthCheck.java
│       │   │   │           │       └── JavaMailHealthCheck.java
│       │   │   │           ├── domain/
│       │   │   │           │   ├── Attachment.java
│       │   │   │           │   ├── Avatar.java
│       │   │   │           │   ├── DigestType.java
│       │   │   │           │   ├── Domain.java
│       │   │   │           │   ├── DomainConfiguration.java
│       │   │   │           │   ├── Group.java
│       │   │   │           │   ├── User.java
│       │   │   │           │   ├── UserStatusStat.java
│       │   │   │           │   ├── status/
│       │   │   │           │   │   ├── AbstractStatus.java
│       │   │   │           │   │   ├── Announcement.java
│       │   │   │           │   │   ├── MentionFriend.java
│       │   │   │           │   │   ├── MentionShare.java
│       │   │   │           │   │   ├── Share.java
│       │   │   │           │   │   ├── Status.java
│       │   │   │           │   │   ├── StatusDetails.java
│       │   │   │           │   │   └── StatusType.java
│       │   │   │           │   └── validation/
│       │   │   │           │       ├── ContraintsAttachmentCreation.java
│       │   │   │           │       └── ContraintsUserCreation.java
│       │   │   │           ├── repository/
│       │   │   │           │   ├── AppleDeviceRepository.java
│       │   │   │           │   ├── AppleDeviceUserRepository.java
│       │   │   │           │   ├── AttachmentRepository.java
│       │   │   │           │   ├── AvatarRepository.java
│       │   │   │           │   ├── BlockRepository.java
│       │   │   │           │   ├── CounterRepository.java
│       │   │   │           │   ├── DaylineRepository.java
│       │   │   │           │   ├── DiscussionRepository.java
│       │   │   │           │   ├── DomainConfigurationRepository.java
│       │   │   │           │   ├── DomainRepository.java
│       │   │   │           │   ├── DomainlineRepository.java
│       │   │   │           │   ├── FavoritelineRepository.java
│       │   │   │           │   ├── FollowerRepository.java
│       │   │   │           │   ├── FriendRepository.java
│       │   │   │           │   ├── GroupCounterRepository.java
│       │   │   │           │   ├── GroupDetailsRepository.java
│       │   │   │           │   ├── GroupMembersRepository.java
│       │   │   │           │   ├── GroupRepository.java
│       │   │   │           │   ├── GrouplineRepository.java
│       │   │   │           │   ├── IdempotentRepository.java
│       │   │   │           │   ├── MailDigestRepository.java
│       │   │   │           │   ├── MentionlineRepository.java
│       │   │   │           │   ├── RegistrationRepository.java
│       │   │   │           │   ├── ResolvedReportRepository.java
│       │   │   │           │   ├── RssUidRepository.java
│       │   │   │           │   ├── SharesRepository.java
│       │   │   │           │   ├── StatusAttachmentRepository.java
│       │   │   │           │   ├── StatusReportRepository.java
│       │   │   │           │   ├── StatusRepository.java
│       │   │   │           │   ├── TagCounterRepository.java
│       │   │   │           │   ├── TagFollowerRepository.java
│       │   │   │           │   ├── TaglineRepository.java
│       │   │   │           │   ├── TimelineRepository.java
│       │   │   │           │   ├── TrendRepository.java
│       │   │   │           │   ├── UserAttachmentRepository.java
│       │   │   │           │   ├── UserGroupRepository.java
│       │   │   │           │   ├── UserRepository.java
│       │   │   │           │   ├── UserTagRepository.java
│       │   │   │           │   ├── UserTrendRepository.java
│       │   │   │           │   ├── UserlineRepository.java
│       │   │   │           │   └── cassandra/
│       │   │   │           │       ├── AbstractCassandraFollowerRepository.java
│       │   │   │           │       ├── AbstractCassandraFriendRepository.java
│       │   │   │           │       ├── AbstractCassandraLineRepository.java
│       │   │   │           │       ├── CassandraAppleDeviceRepository.java
│       │   │   │           │       ├── CassandraAppleDeviceUserRepository.java
│       │   │   │           │       ├── CassandraAttachmentRepository.java
│       │   │   │           │       ├── CassandraAvatarRepository.java
│       │   │   │           │       ├── CassandraBlockRepository.java
│       │   │   │           │       ├── CassandraCounterRepository.java
│       │   │   │           │       ├── CassandraDaylineRepository.java
│       │   │   │           │       ├── CassandraDiscussionRepository.java
│       │   │   │           │       ├── CassandraDomainConfigurationRepository.java
│       │   │   │           │       ├── CassandraDomainRepository.java
│       │   │   │           │       ├── CassandraDomainlineRepository.java
│       │   │   │           │       ├── CassandraFavoritelineRepository.java
│       │   │   │           │       ├── CassandraFollowerRepository.java
│       │   │   │           │       ├── CassandraFriendRepository.java
│       │   │   │           │       ├── CassandraGroupCounterRepository.java
│       │   │   │           │       ├── CassandraGroupDetailsRepository.java
│       │   │   │           │       ├── CassandraGroupMembersRepository.java
│       │   │   │           │       ├── CassandraGroupRepository.java
│       │   │   │           │       ├── CassandraGrouplineRepository.java
│       │   │   │           │       ├── CassandraIdempotentRepository.java
│       │   │   │           │       ├── CassandraMailDigestRepository.java
│       │   │   │           │       ├── CassandraMentionlineRepository.java
│       │   │   │           │       ├── CassandraRegistrationRepository.java
│       │   │   │           │       ├── CassandraRssUidRepository.java
│       │   │   │           │       ├── CassandraSharesRepository.java
│       │   │   │           │       ├── CassandraStatusAttachmentRepository.java
│       │   │   │           │       ├── CassandraStatusReportRepository.java
│       │   │   │           │       ├── CassandraStatusRepository.java
│       │   │   │           │       ├── CassandraTagCounterRepository.java
│       │   │   │           │       ├── CassandraTagFollowerRepository.java
│       │   │   │           │       ├── CassandraTaglineRepository.java
│       │   │   │           │       ├── CassandraTimelineRepository.java
│       │   │   │           │       ├── CassandraTrendRepository.java
│       │   │   │           │       ├── CassandraUserAttachmentRepository.java
│       │   │   │           │       ├── CassandraUserGroupRepository.java
│       │   │   │           │       ├── CassandraUserRepository.java
│       │   │   │           │       ├── CassandraUserTagRepository.java
│       │   │   │           │       ├── CassandraUserTrendRepository.java
│       │   │   │           │       └── CassandraUserlineRepository.java
│       │   │   │           ├── security/
│       │   │   │           │   ├── AjaxAuthenticationFailureHandler.java
│       │   │   │           │   ├── AjaxAuthenticationSuccessHandler.java
│       │   │   │           │   ├── AjaxLogoutSuccessHandler.java
│       │   │   │           │   ├── AuthenticationService.java
│       │   │   │           │   ├── DomainViolationException.java
│       │   │   │           │   ├── GoogleApiAuthenticationProvider.java
│       │   │   │           │   ├── GoogleAuthenticationProvider.java
│       │   │   │           │   ├── GoogleAuthenticationToken.java
│       │   │   │           │   ├── GoogleAutoRegisteringUserDetailsService.java
│       │   │   │           │   ├── Http401UnauthorizedEntryPoint.java
│       │   │   │           │   ├── OpenIdAutoRegisteringUserDetailsService.java
│       │   │   │           │   ├── TatamiAuthenticationSuccessHandler.java
│       │   │   │           │   ├── TatamiLdapAuthenticationProvider.java
│       │   │   │           │   ├── TatamiUserDetailsService.java
│       │   │   │           │   └── xauth/
│       │   │   │           │       ├── Token.java
│       │   │   │           │       ├── TokenProvider.java
│       │   │   │           │       └── XAuthTokenFilter.java
│       │   │   │           ├── service/
│       │   │   │           │   ├── AdminService.java
│       │   │   │           │   ├── ApplePushService.java
│       │   │   │           │   ├── AtmosphereService.java
│       │   │   │           │   ├── AttachmentService.java
│       │   │   │           │   ├── AvatarService.java
│       │   │   │           │   ├── BlockService.java
│       │   │   │           │   ├── CounterService.java
│       │   │   │           │   ├── FriendshipService.java
│       │   │   │           │   ├── GroupService.java
│       │   │   │           │   ├── MailDigestService.java
│       │   │   │           │   ├── MailService.java
│       │   │   │           │   ├── MentionService.java
│       │   │   │           │   ├── SearchService.java
│       │   │   │           │   ├── StatsService.java
│       │   │   │           │   ├── StatusUpdateService.java
│       │   │   │           │   ├── SuggestionService.java
│       │   │   │           │   ├── TagMembershipService.java
│       │   │   │           │   ├── TimelineService.java
│       │   │   │           │   ├── TrendService.java
│       │   │   │           │   ├── UserService.java
│       │   │   │           │   ├── dto/
│       │   │   │           │   │   ├── StatusDTO.java
│       │   │   │           │   │   ├── UserDTO.java
│       │   │   │           │   │   └── UserGroupDTO.java
│       │   │   │           │   ├── elasticsearch/
│       │   │   │           │   │   ├── ElasticsearchEngine.java
│       │   │   │           │   │   ├── ElasticsearchSearchService.java
│       │   │   │           │   │   ├── EmbeddedElasticsearchEngine.java
│       │   │   │           │   │   └── RemoteElasticsearchEngine.java
│       │   │   │           │   ├── exception/
│       │   │   │           │   │   ├── ArchivedGroupException.java
│       │   │   │           │   │   ├── ReplyStatusException.java
│       │   │   │           │   │   └── StorageSizeException.java
│       │   │   │           │   └── util/
│       │   │   │           │       ├── AnalysisUtil.java
│       │   │   │           │       ├── DomainUtil.java
│       │   │   │           │       ├── RandomUtil.java
│       │   │   │           │       └── ValueComparator.java
│       │   │   │           └── web/
│       │   │   │               ├── atmosphere/
│       │   │   │               │   └── TatamiNotification.java
│       │   │   │               ├── rest/
│       │   │   │               │   └── dto/
│       │   │   │               │       ├── ActionStatus.java
│       │   │   │               │       ├── EmailAndUsername.java
│       │   │   │               │       ├── Preferences.java
│       │   │   │               │       ├── Reply.java
│       │   │   │               │       ├── SearchResults.java
│       │   │   │               │       ├── Tag.java
│       │   │   │               │       ├── Trend.java
│       │   │   │               │       ├── UserActionStatus.java
│       │   │   │               │       └── UserPassword.java
│       │   │   │               └── syndic/
│       │   │   │                   ├── SyndicTimelineController.java
│       │   │   │                   ├── SyndicView.java
│       │   │   │                   └── UnknownRssChannelException.java
│       │   │   └── me/
│       │   │       └── prettyprint/
│       │   │           └── hom/
│       │   │               └── CassandraPersistenceProvider.java
│       │   ├── resources/
│       │   │   ├── META-INF/
│       │   │   │   ├── elasticsearch/
│       │   │   │   │   ├── elasticsearch-embedded.yml
│       │   │   │   │   ├── index/
│       │   │   │   │   │   ├── group.json
│       │   │   │   │   │   ├── status.json
│       │   │   │   │   │   └── user.json
│       │   │   │   │   └── logging.yml
│       │   │   │   ├── spring/
│       │   │   │   │   ├── applicationContext-metrics.xml
│       │   │   │   │   └── applicationContext-security.xml
│       │   │   │   └── tatami/
│       │   │   │       ├── customization.properties
│       │   │   │       ├── mails/
│       │   │   │       │   ├── common
│       │   │   │       │   ├── dailyDigestEmail
│       │   │   │       │   ├── deactivatedUserEmail
│       │   │   │       │   ├── invitationMessageEmail
│       │   │   │       │   ├── lostPasswordEmail
│       │   │   │       │   ├── messages/
│       │   │   │       │   │   ├── messages_en.properties
│       │   │   │       │   │   └── messages_fr.properties
│       │   │   │       │   ├── passwordReinitializedEmail
│       │   │   │       │   ├── registrationEmail
│       │   │   │       │   ├── reportedStatusEmail
│       │   │   │       │   ├── userMentionEmail
│       │   │   │       │   ├── userPrivateMessageEmail
│       │   │   │       │   ├── validationEmail
│       │   │   │       │   └── weeklyDigestEmail
│       │   │   │       └── tatami.properties
│       │   │   ├── ehcache.xml
│       │   │   └── logback.xml
│       │   └── webapp/
│       │       └── app/
│       │           └── shared/
│       │               └── services/
│       │                   ├── AuthenticationService.js
│       │                   ├── GeolocService.js
│       │                   ├── GroupService.js
│       │                   ├── HomeService.js
│       │                   ├── ProfileService.js
│       │                   ├── SearchService.js
│       │                   ├── StatusService.js
│       │                   ├── TagService.js
│       │                   ├── TopPostersService.js
│       │                   ├── UserService.js
│       │                   └── UserSession.js
│       └── test/
│           ├── java/
│           │   └── fr/
│           │       └── ippon/
│           │           └── tatami/
│           │               ├── AbstractCassandraTatamiTest.java
│           │               ├── repository/
│           │               │   ├── MailDigestRepositoryTest.java
│           │               │   ├── StatusReportRepositoryTest.java
│           │               │   ├── StatusRepositoryTest.java
│           │               │   ├── TagFollowerRepositoryTest.java
│           │               │   └── UserRepositoryTest.java
│           │               ├── service/
│           │               │   ├── FriendshipServiceTest.java
│           │               │   ├── GroupServiceTest.java
│           │               │   ├── MailDigestServiceTest.java
│           │               │   ├── StatsServiceTest.java
│           │               │   ├── StatusDeletionTest.java
│           │               │   ├── StatusUpdateServiceTest.java
│           │               │   ├── TagMembershipServiceTest.java
│           │               │   ├── TimelineServiceTest.java
│           │               │   ├── TrendServiceTest.java
│           │               │   ├── UserServiceTest.java
│           │               │   └── elasticsearch/
│           │               │       └── ElasticsearchSearchServiceTest.java
│           │               ├── test/
│           │               │   ├── MockUtils.java
│           │               │   └── application/
│           │               │       ├── ApplicationTestConfiguration.java
│           │               │       └── WebApplicationTestConfiguration.java
│           │               └── web/
│           │                   └── syndic/
│           │                       └── SyndicTimelineControllerTest.java
│           ├── jmeter/
│           │   ├── tatami-create-users.jmx
│           │   └── tatami-stress-test.jmx
│           └── resources/
│               ├── dataset/
│               │   └── dataset.json
│               ├── logback.xml
│               └── tatami/
│                   └── tatami-test.properties
├── src/
│   ├── integration/
│   │   ├── java/
│   │   │   ├── fr/
│   │   │   │   └── ippon/
│   │   │   │       └── tatami/
│   │   │   │           ├── test/
│   │   │   │           │   └── support/
│   │   │   │           │       ├── LdapTestServer.java
│   │   │   │           │       └── LdapTestServerJunitLauncher.java
│   │   │   │           └── uitest/
│   │   │   │               ├── AuthenticationSpec.groovy
│   │   │   │               ├── NewRegistrationSpec.groovy
│   │   │   │               └── support/
│   │   │   │                   ├── AccountUtils.groovy
│   │   │   │                   ├── CassandraAccessUtils.groovy
│   │   │   │                   ├── RegistrationUtils.groovy
│   │   │   │                   └── TatamiBaseGebSpec.groovy
│   │   │   └── pages/
│   │   │       ├── EmailVerifiedPage.groovy
│   │   │       ├── HomePage.groovy
│   │   │       ├── LoginPage.groovy
│   │   │       ├── TatamiBasePage.groovy
│   │   │       └── google/
│   │   │           ├── GoogleAuthenticationPage.groovy
│   │   │           └── GoogleOpenIdPage.groovy
│   │   └── resources/
│   │       ├── GebConfig.groovy
│   │       └── fr/
│   │           └── ippon/
│   │               └── tatami/
│   │                   └── test/
│   │                       └── support/
│   │                           └── ipponTestLdapExport.ldif
│   └── main/
│       └── cql/
│           ├── install.cql
│           └── upgrade/
│               ├── upgrade_from_1.0.27_to_2.0.0.cql
│               ├── upgrade_from_2.0.0_to_2.1.0.cql
│               ├── upgrade_from_2.1.3_to_2.2.0.cql
│               └── upgrade_from_3.0.26_to_3.0.27.cql
├── tatamibot/
│   ├── pom.xml
│   └── src/
│       ├── main/
│       │   ├── java/
│       │   │   └── fr/
│       │   │       └── ippon/
│       │   │           └── tatami/
│       │   │               ├── bot/
│       │   │               │   ├── Tatamibot.java
│       │   │               │   ├── config/
│       │   │               │   │   └── TatamibotConfiguration.java
│       │   │               │   ├── processor/
│       │   │               │   │   ├── LastUpdateDateTatamibotConfigurationUpdater.java
│       │   │               │   │   └── TatamiStatusProcessor.java
│       │   │               │   └── route/
│       │   │               │       ├── CommonRouteBuilder.java
│       │   │               │       ├── GitHubRouteBuilder.java
│       │   │               │       ├── RssRouteBuilder.java
│       │   │               │       ├── SourceRouteBuilderBase.java
│       │   │               │       └── TwitterRouteBuilder.java
│       │   │               ├── repository/
│       │   │               │   ├── TatamibotConfigurationRepository.java
│       │   │               │   └── cassandra/
│       │   │               │       └── CassandraTatamibotConfigurationRepository.java
│       │   │               └── web/
│       │   │                   └── bot/
│       │   │                       └── TatamibotController.java
│       │   └── resources/
│       │       └── META-INF/
│       │           └── spring/
│       │               └── applicationContext-tatamibot.xml
│       └── test/
│           ├── java/
│           │   └── fr/
│           │       └── ippon/
│           │           └── tatami/
│           │               ├── bot/
│           │               │   ├── TatamibotTest.java
│           │               │   └── route/
│           │               │       ├── CommonRouteBuilderTest.java
│           │               │       ├── RssRouteBuilderCamelTest.java
│           │               │       ├── RssRouteBuilderUnitTest.java
│           │               │       ├── SourceRouteBuilderBaseCamelTest.java
│           │               │       └── TwitterRouteBuilderCamelTest.java
│           │               └── test/
│           │                   └── MockUtils.java
│           └── resources/
│               └── fr/
│                   └── ippon/
│                       └── tatami/
│                           └── bot/
│                               └── route/
│                                   └── rss.xml
└── web/
    ├── gruntfile.js
    ├── karma.ci.conf.js
    ├── karma.conf.js
    ├── package.json
    ├── pom.xml
    └── src/
        ├── main/
        │   ├── java/
        │   │   └── fr/
        │   │       └── ippon/
        │   │           └── tatami/
        │   │               └── web/
        │   │                   ├── atmosphere/
        │   │                   │   └── RealtimeService.java
        │   │                   ├── controller/
        │   │                   │   ├── ErrorController.java
        │   │                   │   ├── HomeController.java
        │   │                   │   └── Pac4JSecurityCheckController.java
        │   │                   ├── fileupload/
        │   │                   │   ├── FileController.java
        │   │                   │   ├── Message.java
        │   │                   │   ├── StatusResponse.java
        │   │                   │   └── UploadedFile.java
        │   │                   ├── filter/
        │   │                   │   ├── IeRefreshWrapper.java
        │   │                   │   └── TatamiGzipFilter.java
        │   │                   ├── init/
        │   │                   │   └── WebConfigurer.java
        │   │                   └── rest/
        │   │                       ├── AccountController.java
        │   │                       ├── AttachmentController.java
        │   │                       ├── BlockController.java
        │   │                       ├── CompanyWallController.java
        │   │                       ├── FavoritesController.java
        │   │                       ├── FriendshipController.java
        │   │                       ├── GroupController.java
        │   │                       ├── MentionsController.java
        │   │                       ├── SearchController.java
        │   │                       ├── StatsController.java
        │   │                       ├── TagController.java
        │   │                       ├── TimelineController.java
        │   │                       ├── TrendController.java
        │   │                       ├── UserController.java
        │   │                       └── UserXAuthController.java
        │   └── webapp/
        │       ├── .bowerrc
        │       ├── WEB-INF/
        │       │   ├── messages/
        │       │   │   ├── messages_en.properties
        │       │   │   └── messages_fr.properties
        │       │   ├── pages/
        │       │   │   ├── errors/
        │       │   │   │   ├── 404.jsp
        │       │   │   │   ├── 500.jsp
        │       │   │   │   └── file_not_found.jsp
        │       │   │   ├── home.jsp
        │       │   │   ├── includes/
        │       │   │   │   ├── footer.jsp
        │       │   │   │   ├── header.jsp
        │       │   │   │   ├── help-home.jsp
        │       │   │   │   ├── navigation-admin.jsp
        │       │   │   │   ├── template-search-engine.jsp
        │       │   │   │   ├── templates-admin.jsp
        │       │   │   │   ├── templates.jsp
        │       │   │   │   ├── topavatar.jsp
        │       │   │   │   └── topmenu.jsp
        │       │   │   └── login.jsp
        │       │   └── web.xml
        │       ├── app/
        │       │   ├── TatamiApp.js
        │       │   ├── components/
        │       │   │   ├── about/
        │       │   │   │   ├── AboutModule.js
        │       │   │   │   ├── AboutView.html
        │       │   │   │   ├── license/
        │       │   │   │   │   ├── LicenseController.js
        │       │   │   │   │   └── LicenseView.html
        │       │   │   │   ├── presentation/
        │       │   │   │   │   └── PresentationView.html
        │       │   │   │   └── tos/
        │       │   │   │       └── ToSView.html
        │       │   │   ├── account/
        │       │   │   │   ├── AccountController.js
        │       │   │   │   ├── AccountModule.js
        │       │   │   │   ├── AccountView.html
        │       │   │   │   ├── FormController.js
        │       │   │   │   ├── FormView.html
        │       │   │   │   ├── files/
        │       │   │   │   │   ├── FilesController.js
        │       │   │   │   │   ├── FilesModule.js
        │       │   │   │   │   ├── FilesService.js
        │       │   │   │   │   └── FilesView.html
        │       │   │   │   ├── groups/
        │       │   │   │   │   ├── GroupsController.js
        │       │   │   │   │   ├── GroupsModule.js
        │       │   │   │   │   ├── GroupsView.html
        │       │   │   │   │   ├── creation/
        │       │   │   │   │   │   ├── GroupsCreateController.js
        │       │   │   │   │   │   └── GroupsCreateView.html
        │       │   │   │   │   ├── list/
        │       │   │   │   │   │   ├── GroupListController.js
        │       │   │   │   │   │   └── GroupsListView.html
        │       │   │   │   │   └── manage/
        │       │   │   │   │       ├── GroupsManageController.js
        │       │   │   │   │       └── GroupsManageView.html
        │       │   │   │   ├── password/
        │       │   │   │   │   ├── PasswordController.js
        │       │   │   │   │   ├── PasswordModule.js
        │       │   │   │   │   ├── PasswordService.js
        │       │   │   │   │   └── PasswordView.html
        │       │   │   │   ├── preferences/
        │       │   │   │   │   ├── PreferencesController.js
        │       │   │   │   │   ├── PreferencesModule.js
        │       │   │   │   │   ├── PreferencesService.js
        │       │   │   │   │   └── PreferencesView.html
        │       │   │   │   ├── profile/
        │       │   │   │   │   ├── ProfileController.js
        │       │   │   │   │   ├── ProfileModule.js
        │       │   │   │   │   └── ProfileView.html
        │       │   │   │   ├── tags/
        │       │   │   │   │   ├── TagsController.js
        │       │   │   │   │   ├── TagsModule.js
        │       │   │   │   │   └── TagsView.html
        │       │   │   │   ├── topPosters/
        │       │   │   │   │   ├── TopPostersController.js
        │       │   │   │   │   ├── TopPostersModule.js
        │       │   │   │   │   └── TopPostersView.html
        │       │   │   │   └── users/
        │       │   │   │       ├── UsersController.js
        │       │   │   │       ├── UsersModule.js
        │       │   │   │       ├── UsersView.html
        │       │   │   │       └── directives/
        │       │   │   │           ├── UserAccountController.js
        │       │   │   │           ├── UserAccountDirective.js
        │       │   │   │           └── UserAccountView.html
        │       │   │   ├── admin/
        │       │   │   │   ├── AdminController.js
        │       │   │   │   ├── AdminModule.js
        │       │   │   │   ├── AdminService.js
        │       │   │   │   └── AdminView.html
        │       │   │   ├── home/
        │       │   │   │   ├── HomeModule.js
        │       │   │   │   ├── HomeView.html
        │       │   │   │   ├── group/
        │       │   │   │   │   ├── GroupHeaderController.js
        │       │   │   │   │   └── GroupHeaderView.html
        │       │   │   │   ├── profile/
        │       │   │   │   │   ├── ProfileHeaderController.js
        │       │   │   │   │   └── ProfileHeaderView.html
        │       │   │   │   ├── search/
        │       │   │   │   │   ├── SearchHeaderController.js
        │       │   │   │   │   └── SearchHeaderView.html
        │       │   │   │   ├── status/
        │       │   │   │   │   ├── StatusController.js
        │       │   │   │   │   └── StatusView.html
        │       │   │   │   ├── tag/
        │       │   │   │   │   ├── TagHeaderController.js
        │       │   │   │   │   └── TagHeaderView.html
        │       │   │   │   ├── timeline/
        │       │   │   │   │   └── TimelineHeaderView.html
        │       │   │   │   └── welcome/
        │       │   │   │       ├── WelcomeController.js
        │       │   │   │       └── WelcomeView.html
        │       │   │   └── login/
        │       │   │       ├── LoginController.js
        │       │   │       ├── LoginModule.js
        │       │   │       ├── LoginView.html
        │       │   │       ├── RegistrationService.js
        │       │   │       ├── email/
        │       │   │       │   ├── EmailRegistration.html
        │       │   │       │   └── EmailRegistrationController.js
        │       │   │       ├── google/
        │       │   │       │   ├── GoogleLoginController.js
        │       │   │       │   └── GoogleLoginView.html
        │       │   │       ├── manual/
        │       │   │       │   ├── ManualLoginController.js
        │       │   │       │   └── ManualLoginView.html
        │       │   │       ├── recoverPassword/
        │       │   │       │   ├── RecoverPasswordController.js
        │       │   │       │   └── RecoverPasswordView.html
        │       │   │       └── register/
        │       │   │           ├── RegisterController.js
        │       │   │           └── RegisterView.html
        │       │   └── shared/
        │       │       ├── configs/
        │       │       │   ├── MarkedConfig.js
        │       │       │   ├── MomentConfig.js
        │       │       │   └── TranslateConfig.js
        │       │       ├── error/
        │       │       │   ├── 404View.html
        │       │       │   └── 500View.html
        │       │       ├── filters/
        │       │       │   ├── EmoticonFilter.js
        │       │       │   ├── MarkdownFilter.js
        │       │       │   └── PlaceholderFilter.js
        │       │       ├── footer/
        │       │       │   ├── FooterController.js
        │       │       │   ├── FooterModule.js
        │       │       │   └── FooterView.html
        │       │       ├── lists/
        │       │       │   ├── status/
        │       │       │   │   ├── withContext/
        │       │       │   │   │   ├── StatusListContextController.js
        │       │       │   │   │   └── StatusListContextView.html
        │       │       │   │   └── withoutContext/
        │       │       │   │       ├── StatusListController.js
        │       │       │   │       └── StatusListView.html
        │       │       │   └── user/
        │       │       │       ├── UserListController.js
        │       │       │       └── UserListView.html
        │       │       ├── services/
        │       │       │   ├── AuthenticationService.js
        │       │       │   ├── GeolocService.js
        │       │       │   ├── GroupService.js
        │       │       │   ├── HomeService.js
        │       │       │   ├── ProfileService.js
        │       │       │   ├── SearchService.js
        │       │       │   ├── StatusService.js
        │       │       │   ├── TagService.js
        │       │       │   ├── TopPostersService.js
        │       │       │   ├── UserService.js
        │       │       │   └── UserSession.js
        │       │       ├── sidebars/
        │       │       │   ├── home/
        │       │       │   │   ├── HomeSidebarController.js
        │       │       │   │   ├── HomeSidebarModule.js
        │       │       │   │   └── HomeSidebarView.html
        │       │       │   └── profile/
        │       │       │       ├── ProfileSidebarController.js
        │       │       │       ├── ProfileSidebarModule.js
        │       │       │       └── ProfileSidebarView.html
        │       │       └── topMenu/
        │       │           ├── SearchView.html
        │       │           ├── TopMenuController.js
        │       │           ├── TopMenuModule.js
        │       │           ├── TopMenuView.html
        │       │           └── post/
        │       │               ├── DropdownTagTemplate.html
        │       │               ├── DropdownUserTemplate.html
        │       │               ├── PostController.js
        │       │               ├── PostModule.js
        │       │               └── PostView.html
        │       ├── assets/
        │       │   ├── bower_components/
        │       │   │   ├── angular/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-csp.css
        │       │   │   │   ├── angular.min.js.gzip
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-animate/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-bootstrap/
        │       │   │   │   ├── .bower.json
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-bootstrap-tour/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── app/
        │       │   │   │   │   ├── angular-bootstrap-tour.js
        │       │   │   │   │   ├── tour_config_provider.js
        │       │   │   │   │   ├── tour_controller.js
        │       │   │   │   │   ├── tour_directive.js
        │       │   │   │   │   ├── tour_helpers.js
        │       │   │   │   │   └── tour_step_directive.js
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── demo/
        │       │   │   │   │   └── angular-bootstrap-tour.js
        │       │   │   │   ├── dist/
        │       │   │   │   │   └── angular-bootstrap-tour.js
        │       │   │   │   ├── gruntfile.js
        │       │   │   │   ├── karma.conf.js
        │       │   │   │   └── test/
        │       │   │   │       └── spec/
        │       │   │   │           └── angular-bootstrap-tour.spec.js
        │       │   │   ├── angular-cookies/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-mocks/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-mocks.js
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── ngAnimateMock.js
        │       │   │   │   ├── ngMock.js
        │       │   │   │   ├── ngMockE2E.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-moment/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── .editorconfig
        │       │   │   │   ├── .gitignore
        │       │   │   │   ├── .jshintrc
        │       │   │   │   ├── .npmignore
        │       │   │   │   ├── .travis.yml
        │       │   │   │   ├── CHANGELOG.md
        │       │   │   │   ├── CONTRIBUTING.md
        │       │   │   │   ├── Gruntfile.js
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-moment.nuspec
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── karma.conf.js
        │       │   │   │   ├── package.json
        │       │   │   │   └── tests.js
        │       │   │   ├── angular-resource/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-route/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-route.js
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-sanitize/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-touch/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── index.js
        │       │   │   │   └── package.json
        │       │   │   ├── angular-translate/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-translate-storage-cookie/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   └── bower.json
        │       │   │   ├── angular-ui-router/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── CHANGELOG.md
        │       │   │   │   ├── CONTRIBUTING.md
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── api/
        │       │   │   │   │   └── angular-ui-router.d.ts
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── release/
        │       │   │   │   │   └── angular-ui-router.js
        │       │   │   │   └── src/
        │       │   │   │       ├── common.js
        │       │   │   │       ├── resolve.js
        │       │   │   │       ├── state.js
        │       │   │   │       ├── stateDirectives.js
        │       │   │   │       ├── stateFilters.js
        │       │   │   │       ├── templateFactory.js
        │       │   │   │       ├── urlMatcherFactory.js
        │       │   │   │       ├── urlRouter.js
        │       │   │   │       ├── view.js
        │       │   │   │       ├── viewDirective.js
        │       │   │   │       └── viewScroll.js
        │       │   │   ├── bootstrap/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── DOCS-LICENSE
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── LICENSE-MIT
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── dist/
        │       │   │   │   │   ├── css/
        │       │   │   │   │   │   ├── bootstrap-theme.css
        │       │   │   │   │   │   └── bootstrap.css
        │       │   │   │   │   └── js/
        │       │   │   │   │       └── bootstrap.js
        │       │   │   │   ├── js/
        │       │   │   │   │   ├── affix.js
        │       │   │   │   │   ├── alert.js
        │       │   │   │   │   ├── button.js
        │       │   │   │   │   ├── carousel.js
        │       │   │   │   │   ├── collapse.js
        │       │   │   │   │   ├── dropdown.js
        │       │   │   │   │   ├── modal.js
        │       │   │   │   │   ├── popover.js
        │       │   │   │   │   ├── scrollspy.js
        │       │   │   │   │   ├── tab.js
        │       │   │   │   │   ├── tooltip.js
        │       │   │   │   │   └── transition.js
        │       │   │   │   └── less/
        │       │   │   │       ├── alerts.less
        │       │   │   │       ├── badges.less
        │       │   │   │       ├── bootstrap.less
        │       │   │   │       ├── breadcrumbs.less
        │       │   │   │       ├── button-groups.less
        │       │   │   │       ├── buttons.less
        │       │   │   │       ├── carousel.less
        │       │   │   │       ├── close.less
        │       │   │   │       ├── code.less
        │       │   │   │       ├── component-animations.less
        │       │   │   │       ├── dropdowns.less
        │       │   │   │       ├── forms.less
        │       │   │   │       ├── glyphicons.less
        │       │   │   │       ├── grid.less
        │       │   │   │       ├── input-groups.less
        │       │   │   │       ├── jumbotron.less
        │       │   │   │       ├── labels.less
        │       │   │   │       ├── list-group.less
        │       │   │   │       ├── media.less
        │       │   │   │       ├── mixins.less
        │       │   │   │       ├── modals.less
        │       │   │   │       ├── navbar.less
        │       │   │   │       ├── navs.less
        │       │   │   │       ├── normalize.less
        │       │   │   │       ├── pager.less
        │       │   │   │       ├── pagination.less
        │       │   │   │       ├── panels.less
        │       │   │   │       ├── popovers.less
        │       │   │   │       ├── print.less
        │       │   │   │       ├── progress-bars.less
        │       │   │   │       ├── responsive-utilities.less
        │       │   │   │       ├── scaffolding.less
        │       │   │   │       ├── tables.less
        │       │   │   │       ├── theme.less
        │       │   │   │       ├── thumbnails.less
        │       │   │   │       ├── tooltip.less
        │       │   │   │       ├── type.less
        │       │   │   │       ├── utilities.less
        │       │   │   │       ├── variables.less
        │       │   │   │       └── wells.less
        │       │   │   ├── jquery/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── MIT-LICENSE.txt
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── dist/
        │       │   │   │   │   └── jquery.js
        │       │   │   │   └── src/
        │       │   │   │       ├── ajax/
        │       │   │   │       │   ├── jsonp.js
        │       │   │   │       │   ├── load.js
        │       │   │   │       │   ├── parseJSON.js
        │       │   │   │       │   ├── parseXML.js
        │       │   │   │       │   ├── script.js
        │       │   │   │       │   ├── var/
        │       │   │   │       │   │   ├── nonce.js
        │       │   │   │       │   │   └── rquery.js
        │       │   │   │       │   └── xhr.js
        │       │   │   │       ├── ajax.js
        │       │   │   │       ├── attributes/
        │       │   │   │       │   ├── attr.js
        │       │   │   │       │   ├── classes.js
        │       │   │   │       │   ├── prop.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   └── val.js
        │       │   │   │       ├── attributes.js
        │       │   │   │       ├── callbacks.js
        │       │   │   │       ├── core/
        │       │   │   │       │   ├── access.js
        │       │   │   │       │   ├── init.js
        │       │   │   │       │   ├── parseHTML.js
        │       │   │   │       │   ├── ready.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       └── rsingleTag.js
        │       │   │   │       ├── core.js
        │       │   │   │       ├── css/
        │       │   │   │       │   ├── addGetHookIf.js
        │       │   │   │       │   ├── curCSS.js
        │       │   │   │       │   ├── defaultDisplay.js
        │       │   │   │       │   ├── hiddenVisibleSelectors.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   ├── swap.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       ├── cssExpand.js
        │       │   │   │       │       ├── isHidden.js
        │       │   │   │       │       ├── rmargin.js
        │       │   │   │       │       └── rnumnonpx.js
        │       │   │   │       ├── css.js
        │       │   │   │       ├── data.js
        │       │   │   │       ├── deferred.js
        │       │   │   │       ├── deprecated.js
        │       │   │   │       ├── dimensions.js
        │       │   │   │       ├── effects/
        │       │   │   │       │   ├── Tween.js
        │       │   │   │       │   ├── animatedSelector.js
        │       │   │   │       │   └── support.js
        │       │   │   │       ├── effects.js
        │       │   │   │       ├── event/
        │       │   │   │       │   ├── alias.js
        │       │   │   │       │   └── support.js
        │       │   │   │       ├── event.js
        │       │   │   │       ├── exports/
        │       │   │   │       │   ├── amd.js
        │       │   │   │       │   └── global.js
        │       │   │   │       ├── intro.js
        │       │   │   │       ├── jquery.js
        │       │   │   │       ├── manipulation/
        │       │   │   │       │   ├── _evalUrl.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       └── rcheckableType.js
        │       │   │   │       ├── manipulation.js
        │       │   │   │       ├── offset.js
        │       │   │   │       ├── outro.js
        │       │   │   │       ├── queue/
        │       │   │   │       │   └── delay.js
        │       │   │   │       ├── queue.js
        │       │   │   │       ├── selector-sizzle.js
        │       │   │   │       ├── selector.js
        │       │   │   │       ├── serialize.js
        │       │   │   │       ├── sizzle/
        │       │   │   │       │   └── dist/
        │       │   │   │       │       └── sizzle.js
        │       │   │   │       ├── support.js
        │       │   │   │       ├── traversing/
        │       │   │   │       │   ├── findFilter.js
        │       │   │   │       │   └── var/
        │       │   │   │       │       └── rneedsContext.js
        │       │   │   │       ├── traversing.js
        │       │   │   │       ├── var/
        │       │   │   │       │   ├── class2type.js
        │       │   │   │       │   ├── concat.js
        │       │   │   │       │   ├── deletedIds.js
        │       │   │   │       │   ├── hasOwn.js
        │       │   │   │       │   ├── indexOf.js
        │       │   │   │       │   ├── pnum.js
        │       │   │   │       │   ├── push.js
        │       │   │   │       │   ├── rnotwhite.js
        │       │   │   │       │   ├── slice.js
        │       │   │   │       │   ├── strundefined.js
        │       │   │   │       │   ├── support.js
        │       │   │   │       │   └── toString.js
        │       │   │   │       └── wrap.js
        │       │   │   ├── ment.io/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── LICENSE-MIT
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── dist/
        │       │   │   │   │   ├── mentio.js
        │       │   │   │   │   └── templates.js
        │       │   │   │   ├── gulpfile.js
        │       │   │   │   ├── karma.conf.js
        │       │   │   │   ├── ment.io/
        │       │   │   │   │   ├── index.html
        │       │   │   │   │   ├── peopledata.json
        │       │   │   │   │   ├── productdata.json
        │       │   │   │   │   ├── scripts.js
        │       │   │   │   │   ├── simplepeopledata.json
        │       │   │   │   │   └── styles.css
        │       │   │   │   ├── package.json
        │       │   │   │   └── src/
        │       │   │   │       ├── mentio-menu.tpl.html
        │       │   │   │       ├── mentio.directive.js
        │       │   │   │       └── mentio.service.js
        │       │   │   ├── moment/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── CHANGELOG.md
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── Moment.js.nuspec
        │       │   │   │   ├── README.md
        │       │   │   │   ├── benchmarks/
        │       │   │   │   │   └── clone.js
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── locale/
        │       │   │   │   │   ├── af.js
        │       │   │   │   │   ├── ar-ma.js
        │       │   │   │   │   ├── ar-sa.js
        │       │   │   │   │   ├── ar-tn.js
        │       │   │   │   │   ├── ar.js
        │       │   │   │   │   ├── az.js
        │       │   │   │   │   ├── be.js
        │       │   │   │   │   ├── bg.js
        │       │   │   │   │   ├── bn.js
        │       │   │   │   │   ├── bo.js
        │       │   │   │   │   ├── br.js
        │       │   │   │   │   ├── bs.js
        │       │   │   │   │   ├── ca.js
        │       │   │   │   │   ├── cs.js
        │       │   │   │   │   ├── cv.js
        │       │   │   │   │   ├── cy.js
        │       │   │   │   │   ├── da.js
        │       │   │   │   │   ├── de-at.js
        │       │   │   │   │   ├── de.js
        │       │   │   │   │   ├── el.js
        │       │   │   │   │   ├── en-au.js
        │       │   │   │   │   ├── en-ca.js
        │       │   │   │   │   ├── en-gb.js
        │       │   │   │   │   ├── eo.js
        │       │   │   │   │   ├── es.js
        │       │   │   │   │   ├── et.js
        │       │   │   │   │   ├── eu.js
        │       │   │   │   │   ├── fa.js
        │       │   │   │   │   ├── fi.js
        │       │   │   │   │   ├── fo.js
        │       │   │   │   │   ├── fr-ca.js
        │       │   │   │   │   ├── fr.js
        │       │   │   │   │   ├── fy.js
        │       │   │   │   │   ├── gl.js
        │       │   │   │   │   ├── he.js
        │       │   │   │   │   ├── hi.js
        │       │   │   │   │   ├── hr.js
        │       │   │   │   │   ├── hu.js
        │       │   │   │   │   ├── hy-am.js
        │       │   │   │   │   ├── id.js
        │       │   │   │   │   ├── is.js
        │       │   │   │   │   ├── it.js
        │       │   │   │   │   ├── ja.js
        │       │   │   │   │   ├── ka.js
        │       │   │   │   │   ├── km.js
        │       │   │   │   │   ├── ko.js
        │       │   │   │   │   ├── lb.js
        │       │   │   │   │   ├── lt.js
        │       │   │   │   │   ├── lv.js
        │       │   │   │   │   ├── mk.js
        │       │   │   │   │   ├── ml.js
        │       │   │   │   │   ├── mr.js
        │       │   │   │   │   ├── ms-my.js
        │       │   │   │   │   ├── my.js
        │       │   │   │   │   ├── nb.js
        │       │   │   │   │   ├── ne.js
        │       │   │   │   │   ├── nl.js
        │       │   │   │   │   ├── nn.js
        │       │   │   │   │   ├── pl.js
        │       │   │   │   │   ├── pt-br.js
        │       │   │   │   │   ├── pt.js
        │       │   │   │   │   ├── ro.js
        │       │   │   │   │   ├── ru.js
        │       │   │   │   │   ├── sk.js
        │       │   │   │   │   ├── sl.js
        │       │   │   │   │   ├── sq.js
        │       │   │   │   │   ├── sr-cyrl.js
        │       │   │   │   │   ├── sr.js
        │       │   │   │   │   ├── sv.js
        │       │   │   │   │   ├── ta.js
        │       │   │   │   │   ├── th.js
        │       │   │   │   │   ├── tl-ph.js
        │       │   │   │   │   ├── tr.js
        │       │   │   │   │   ├── tzm-latn.js
        │       │   │   │   │   ├── tzm.js
        │       │   │   │   │   ├── uk.js
        │       │   │   │   │   ├── uz.js
        │       │   │   │   │   ├── vi.js
        │       │   │   │   │   ├── zh-cn.js
        │       │   │   │   │   └── zh-tw.js
        │       │   │   │   ├── meteor/
        │       │   │   │   │   ├── README.md
        │       │   │   │   │   ├── export.js
        │       │   │   │   │   └── test.js
        │       │   │   │   ├── min/
        │       │   │   │   │   ├── locales.js
        │       │   │   │   │   ├── moment-with-locales.js
        │       │   │   │   │   └── tests.js
        │       │   │   │   ├── moment.js
        │       │   │   │   ├── scripts/
        │       │   │   │   │   └── npm_prepublish.sh
        │       │   │   │   ├── src/
        │       │   │   │   │   ├── lib/
        │       │   │   │   │   │   ├── create/
        │       │   │   │   │   │   │   ├── check-overflow.js
        │       │   │   │   │   │   │   ├── date-from-array.js
        │       │   │   │   │   │   │   ├── default-parsing-flags.js
        │       │   │   │   │   │   │   ├── from-anything.js
        │       │   │   │   │   │   │   ├── from-array.js
        │       │   │   │   │   │   │   ├── from-object.js
        │       │   │   │   │   │   │   ├── from-string-and-array.js
        │       │   │   │   │   │   │   ├── from-string-and-format.js
        │       │   │   │   │   │   │   ├── from-string.js
        │       │   │   │   │   │   │   ├── local.js
        │       │   │   │   │   │   │   ├── utc.js
        │       │   │   │   │   │   │   └── valid.js
        │       │   │   │   │   │   ├── duration/
        │       │   │   │   │   │   │   ├── abs.js
        │       │   │   │   │   │   │   ├── add-subtract.js
        │       │   │   │   │   │   │   ├── as.js
        │       │   │   │   │   │   │   ├── bubble.js
        │       │   │   │   │   │   │   ├── constructor.js
        │       │   │   │   │   │   │   ├── create.js
        │       │   │   │   │   │   │   ├── duration.js
        │       │   │   │   │   │   │   ├── get.js
        │       │   │   │   │   │   │   ├── humanize.js
        │       │   │   │   │   │   │   ├── iso-string.js
        │       │   │   │   │   │   │   └── prototype.js
        │       │   │   │   │   │   ├── format/
        │       │   │   │   │   │   │   └── format.js
        │       │   │   │   │   │   ├── locale/
        │       │   │   │   │   │   │   ├── calendar.js
        │       │   │   │   │   │   │   ├── constructor.js
        │       │   │   │   │   │   │   ├── en.js
        │       │   │   │   │   │   │   ├── formats.js
        │       │   │   │   │   │   │   ├── invalid.js
        │       │   │   │   │   │   │   ├── lists.js
        │       │   │   │   │   │   │   ├── locale.js
        │       │   │   │   │   │   │   ├── locales.js
        │       │   │   │   │   │   │   ├── ordinal.js
        │       │   │   │   │   │   │   ├── pre-post-format.js
        │       │   │   │   │   │   │   ├── prototype.js
        │       │   │   │   │   │   │   ├── relative.js
        │       │   │   │   │   │   │   └── set.js
        │       │   │   │   │   │   ├── moment/
        │       │   │   │   │   │   │   ├── add-subtract.js
        │       │   │   │   │   │   │   ├── calendar.js
        │       │   │   │   │   │   │   ├── clone.js
        │       │   │   │   │   │   │   ├── compare.js
        │       │   │   │   │   │   │   ├── constructor.js
        │       │   │   │   │   │   │   ├── diff.js
        │       │   │   │   │   │   │   ├── format.js
        │       │   │   │   │   │   │   ├── from.js
        │       │   │   │   │   │   │   ├── get-set.js
        │       │   │   │   │   │   │   ├── locale.js
        │       │   │   │   │   │   │   ├── min-max.js
        │       │   │   │   │   │   │   ├── moment.js
        │       │   │   │   │   │   │   ├── prototype.js
        │       │   │   │   │   │   │   ├── start-end-of.js
        │       │   │   │   │   │   │   ├── to-type.js
        │       │   │   │   │   │   │   └── valid.js
        │       │   │   │   │   │   ├── parse/
        │       │   │   │   │   │   │   ├── regex.js
        │       │   │   │   │   │   │   └── token.js
        │       │   │   │   │   │   ├── units/
        │       │   │   │   │   │   │   ├── aliases.js
        │       │   │   │   │   │   │   ├── constants.js
        │       │   │   │   │   │   │   ├── day-of-month.js
        │       │   │   │   │   │   │   ├── day-of-week.js
        │       │   │   │   │   │   │   ├── day-of-year.js
        │       │   │   │   │   │   │   ├── hour.js
        │       │   │   │   │   │   │   ├── millisecond.js
        │       │   │   │   │   │   │   ├── minute.js
        │       │   │   │   │   │   │   ├── month.js
        │       │   │   │   │   │   │   ├── offset.js
        │       │   │   │   │   │   │   ├── quarter.js
        │       │   │   │   │   │   │   ├── second.js
        │       │   │   │   │   │   │   ├── timestamp.js
        │       │   │   │   │   │   │   ├── timezone.js
        │       │   │   │   │   │   │   ├── units.js
        │       │   │   │   │   │   │   ├── week-year.js
        │       │   │   │   │   │   │   ├── week.js
        │       │   │   │   │   │   │   └── year.js
        │       │   │   │   │   │   └── utils/
        │       │   │   │   │   │       ├── abs-floor.js
        │       │   │   │   │   │       ├── compare-arrays.js
        │       │   │   │   │   │       ├── defaults.js
        │       │   │   │   │   │       ├── deprecate.js
        │       │   │   │   │   │       ├── extend.js
        │       │   │   │   │   │       ├── has-own-prop.js
        │       │   │   │   │   │       ├── hooks.js
        │       │   │   │   │   │       ├── is-array.js
        │       │   │   │   │   │       ├── is-date.js
        │       │   │   │   │   │       ├── map.js
        │       │   │   │   │   │       ├── to-int.js
        │       │   │   │   │   │       └── zero-fill.js
        │       │   │   │   │   ├── locale/
        │       │   │   │   │   │   ├── af.js
        │       │   │   │   │   │   ├── ar-ma.js
        │       │   │   │   │   │   ├── ar-sa.js
        │       │   │   │   │   │   ├── ar-tn.js
        │       │   │   │   │   │   ├── ar.js
        │       │   │   │   │   │   ├── az.js
        │       │   │   │   │   │   ├── be.js
        │       │   │   │   │   │   ├── bg.js
        │       │   │   │   │   │   ├── bn.js
        │       │   │   │   │   │   ├── bo.js
        │       │   │   │   │   │   ├── br.js
        │       │   │   │   │   │   ├── bs.js
        │       │   │   │   │   │   ├── ca.js
        │       │   │   │   │   │   ├── cs.js
        │       │   │   │   │   │   ├── cv.js
        │       │   │   │   │   │   ├── cy.js
        │       │   │   │   │   │   ├── da.js
        │       │   │   │   │   │   ├── de-at.js
        │       │   │   │   │   │   ├── de.js
        │       │   │   │   │   │   ├── el.js
        │       │   │   │   │   │   ├── en-au.js
        │       │   │   │   │   │   ├── en-ca.js
        │       │   │   │   │   │   ├── en-gb.js
        │       │   │   │   │   │   ├── eo.js
        │       │   │   │   │   │   ├── es.js
        │       │   │   │   │   │   ├── et.js
        │       │   │   │   │   │   ├── eu.js
        │       │   │   │   │   │   ├── fa.js
        │       │   │   │   │   │   ├── fi.js
        │       │   │   │   │   │   ├── fo.js
        │       │   │   │   │   │   ├── fr-ca.js
        │       │   │   │   │   │   ├── fr.js
        │       │   │   │   │   │   ├── fy.js
        │       │   │   │   │   │   ├── gl.js
        │       │   │   │   │   │   ├── he.js
        │       │   │   │   │   │   ├── hi.js
        │       │   │   │   │   │   ├── hr.js
        │       │   │   │   │   │   ├── hu.js
        │       │   │   │   │   │   ├── hy-am.js
        │       │   │   │   │   │   ├── id.js
        │       │   │   │   │   │   ├── is.js
        │       │   │   │   │   │   ├── it.js
        │       │   │   │   │   │   ├── ja.js
        │       │   │   │   │   │   ├── ka.js
        │       │   │   │   │   │   ├── km.js
        │       │   │   │   │   │   ├── ko.js
        │       │   │   │   │   │   ├── lb.js
        │       │   │   │   │   │   ├── lt.js
        │       │   │   │   │   │   ├── lv.js
        │       │   │   │   │   │   ├── mk.js
        │       │   │   │   │   │   ├── ml.js
        │       │   │   │   │   │   ├── mr.js
        │       │   │   │   │   │   ├── ms-my.js
        │       │   │   │   │   │   ├── my.js
        │       │   │   │   │   │   ├── nb.js
        │       │   │   │   │   │   ├── ne.js
        │       │   │   │   │   │   ├── nl.js
        │       │   │   │   │   │   ├── nn.js
        │       │   │   │   │   │   ├── pl.js
        │       │   │   │   │   │   ├── pt-br.js
        │       │   │   │   │   │   ├── pt.js
        │       │   │   │   │   │   ├── ro.js
        │       │   │   │   │   │   ├── ru.js
        │       │   │   │   │   │   ├── sk.js
        │       │   │   │   │   │   ├── sl.js
        │       │   │   │   │   │   ├── sq.js
        │       │   │   │   │   │   ├── sr-cyrl.js
        │       │   │   │   │   │   ├── sr.js
        │       │   │   │   │   │   ├── sv.js
        │       │   │   │   │   │   ├── ta.js
        │       │   │   │   │   │   ├── th.js
        │       │   │   │   │   │   ├── tl-ph.js
        │       │   │   │   │   │   ├── tr.js
        │       │   │   │   │   │   ├── tzm-latn.js
        │       │   │   │   │   │   ├── tzm.js
        │       │   │   │   │   │   ├── uk.js
        │       │   │   │   │   │   ├── uz.js
        │       │   │   │   │   │   ├── vi.js
        │       │   │   │   │   │   ├── zh-cn.js
        │       │   │   │   │   │   └── zh-tw.js
        │       │   │   │   │   └── moment.js
        │       │   │   │   └── templates/
        │       │   │   │       ├── amd-named.js
        │       │   │   │       ├── amd.js
        │       │   │   │       ├── globals.js
        │       │   │   │       ├── locale-header.js
        │       │   │   │       └── test-header.js
        │       │   │   ├── ng-file-upload/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── FileAPI.flash.swf
        │       │   │   │   ├── FileAPI.js
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── angular-file-upload-all.js
        │       │   │   │   ├── angular-file-upload-shim.js
        │       │   │   │   ├── angular-file-upload.js
        │       │   │   │   ├── bower.json
        │       │   │   │   └── ng-file-upload-all.js
        │       │   │   ├── ngInfiniteScroll/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── LICENSE
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   ├── build/
        │       │   │   │   │   └── ng-infinite-scroll.js
        │       │   │   │   ├── package.json
        │       │   │   │   └── src/
        │       │   │   │       └── infinite-scroll.coffee
        │       │   │   ├── ngtoast/
        │       │   │   │   ├── .bower.json
        │       │   │   │   ├── README.md
        │       │   │   │   ├── bower.json
        │       │   │   │   └── dist/
        │       │   │   │       ├── ngToast-animations.css
        │       │   │   │       ├── ngToast.css
        │       │   │   │       └── ngToast.js
        │       │   │   └── openlayers/
        │       │   │       ├── .bower.json
        │       │   │       ├── .gitignore
        │       │   │       ├── apidoc_config/
        │       │   │       │   ├── Languages.txt
        │       │   │       │   ├── Menu.txt
        │       │   │       │   ├── OL.css
        │       │   │       │   └── Topics.txt
        │       │   │       ├── authors.txt
        │       │   │       ├── build/
        │       │   │       │   ├── README.txt
        │       │   │       │   ├── build.py
        │       │   │       │   ├── buildUncompressed.py
        │       │   │       │   ├── closure-compiler/
        │       │   │       │   │   └── Externs.js
        │       │   │       │   ├── full.cfg
        │       │   │       │   ├── license.txt
        │       │   │       │   ├── light.cfg
        │       │   │       │   ├── lite.cfg
        │       │   │       │   ├── mobile.cfg
        │       │   │       │   └── tests.cfg
        │       │   │       ├── doc_config/
        │       │   │       │   ├── Languages.txt
        │       │   │       │   ├── Menu.txt
        │       │   │       │   ├── OL.css
        │       │   │       │   └── Topics.txt
        │       │   │       ├── lib/
        │       │   │       │   ├── Firebug/
        │       │   │       │   │   ├── firebug.css
        │       │   │       │   │   ├── firebug.html
        │       │   │       │   │   ├── firebug.js
        │       │   │       │   │   ├── firebugx.js
        │       │   │       │   │   ├── license.txt
        │       │   │       │   │   └── readme.txt
        │       │   │       │   ├── OpenLayers/
        │       │   │       │   │   ├── Animation.js
        │       │   │       │   │   ├── BaseTypes/
        │       │   │       │   │   │   ├── Bounds.js
        │       │   │       │   │   │   ├── Class.js
        │       │   │       │   │   │   ├── Date.js
        │       │   │       │   │   │   ├── Element.js
        │       │   │       │   │   │   ├── LonLat.js
        │       │   │       │   │   │   ├── Pixel.js
        │       │   │       │   │   │   └── Size.js
        │       │   │       │   │   ├── BaseTypes.js
        │       │   │       │   │   ├── Console.js
        │       │   │       │   │   ├── Control/
        │       │   │       │   │   │   ├── ArgParser.js
        │       │   │       │   │   │   ├── Attribution.js
        │       │   │       │   │   │   ├── Button.js
        │       │   │       │   │   │   ├── CacheRead.js
        │       │   │       │   │   │   ├── CacheWrite.js
        │       │   │       │   │   │   ├── DragFeature.js
        │       │   │       │   │   │   ├── DragPan.js
        │       │   │       │   │   │   ├── DrawFeature.js
        │       │   │       │   │   │   ├── EditingToolbar.js
        │       │   │       │   │   │   ├── Geolocate.js
        │       │   │       │   │   │   ├── GetFeature.js
        │       │   │       │   │   │   ├── Graticule.js
        │       │   │       │   │   │   ├── KeyboardDefaults.js
        │       │   │       │   │   │   ├── LayerSwitcher.js
        │       │   │       │   │   │   ├── Measure.js
        │       │   │       │   │   │   ├── ModifyFeature/
        │       │   │       │   │   │   │   └── BySegment.js
        │       │   │       │   │   │   ├── ModifyFeature.js
        │       │   │       │   │   │   ├── MousePosition.js
        │       │   │       │   │   │   ├── NavToolbar.js
        │       │   │       │   │   │   ├── Navigation.js
        │       │   │       │   │   │   ├── NavigationHistory.js
        │       │   │       │   │   │   ├── OverviewMap.js
        │       │   │       │   │   │   ├── Pan.js
        │       │   │       │   │   │   ├── PanPanel.js
        │       │   │       │   │   │   ├── PanZoom.js
        │       │   │       │   │   │   ├── PanZoomBar.js
        │       │   │       │   │   │   ├── Panel.js
        │       │   │       │   │   │   ├── Permalink.js
        │       │   │       │   │   │   ├── PinchZoom.js
        │       │   │       │   │   │   ├── SLDSelect.js
        │       │   │       │   │   │   ├── Scale.js
        │       │   │       │   │   │   ├── ScaleLine.js
        │       │   │       │   │   │   ├── SelectFeature.js
        │       │   │       │   │   │   ├── Snapping.js
        │       │   │       │   │   │   ├── Split.js
        │       │   │       │   │   │   ├── TextButtonPanel.js
        │       │   │       │   │   │   ├── TouchNavigation.js
        │       │   │       │   │   │   ├── TransformFeature.js
        │       │   │       │   │   │   ├── UTFGrid.js
        │       │   │       │   │   │   ├── WMSGetFeatureInfo.js
        │       │   │       │   │   │   ├── WMTSGetFeatureInfo.js
        │       │   │       │   │   │   ├── Zoom.js
        │       │   │       │   │   │   ├── ZoomBox.js
        │       │   │       │   │   │   ├── ZoomIn.js
        │       │   │       │   │   │   ├── ZoomOut.js
        │       │   │       │   │   │   ├── ZoomPanel.js
        │       │   │       │   │   │   └── ZoomToMaxExtent.js
        │       │   │       │   │   ├── Control.js
        │       │   │       │   │   ├── Events/
        │       │   │       │   │   │   ├── buttonclick.js
        │       │   │       │   │   │   └── featureclick.js
        │       │   │       │   │   ├── Events.js
        │       │   │       │   │   ├── Feature/
        │       │   │       │   │   │   └── Vector.js
        │       │   │       │   │   ├── Feature.js
        │       │   │       │   │   ├── Filter/
        │       │   │       │   │   │   ├── Comparison.js
        │       │   │       │   │   │   ├── FeatureId.js
        │       │   │       │   │   │   ├── Function.js
        │       │   │       │   │   │   ├── Logical.js
        │       │   │       │   │   │   └── Spatial.js
        │       │   │       │   │   ├── Filter.js
        │       │   │       │   │   ├── Format/
        │       │   │       │   │   │   ├── ArcXML/
        │       │   │       │   │   │   │   └── Features.js
        │       │   │       │   │   │   ├── ArcXML.js
        │       │   │       │   │   │   ├── Atom.js
        │       │   │       │   │   │   ├── CQL.js
        │       │   │       │   │   │   ├── CSWGetDomain/
        │       │   │       │   │   │   │   └── v2_0_2.js
        │       │   │       │   │   │   ├── CSWGetDomain.js
        │       │   │       │   │   │   ├── CSWGetRecords/
        │       │   │       │   │   │   │   └── v2_0_2.js
        │       │   │       │   │   │   ├── CSWGetRecords.js
        │       │   │       │   │   │   ├── Context.js
        │       │   │       │   │   │   ├── EncodedPolyline.js
        │       │   │       │   │   │   ├── Filter/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   ├── v2.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   ├── Filter.js
        │       │   │       │   │   │   ├── GML/
        │       │   │       │   │   │   │   ├── Base.js
        │       │   │       │   │   │   │   ├── v2.js
        │       │   │       │   │   │   │   └── v3.js
        │       │   │       │   │   │   ├── GML.js
        │       │   │       │   │   │   ├── GPX.js
        │       │   │       │   │   │   ├── GeoJSON.js
        │       │   │       │   │   │   ├── GeoRSS.js
        │       │   │       │   │   │   ├── JSON.js
        │       │   │       │   │   │   ├── KML.js
        │       │   │       │   │   │   ├── OGCExceptionReport.js
        │       │   │       │   │   │   ├── OSM.js
        │       │   │       │   │   │   ├── OWSCommon/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── OWSCommon.js
        │       │   │       │   │   │   ├── OWSContext/
        │       │   │       │   │   │   │   └── v0_3_1.js
        │       │   │       │   │   │   ├── OWSContext.js
        │       │   │       │   │   │   ├── QueryStringFilter.js
        │       │   │       │   │   │   ├── SLD/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_0_0_GeoServer.js
        │       │   │       │   │   │   ├── SLD.js
        │       │   │       │   │   │   ├── SOSCapabilities/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── SOSCapabilities.js
        │       │   │       │   │   │   ├── SOSGetFeatureOfInterest.js
        │       │   │       │   │   │   ├── SOSGetObservation.js
        │       │   │       │   │   │   ├── TMSCapabilities.js
        │       │   │       │   │   │   ├── Text.js
        │       │   │       │   │   │   ├── WCSCapabilities/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── WCSCapabilities.js
        │       │   │       │   │   │   ├── WCSDescribeCoverage/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── WCSDescribeCoverage.js
        │       │   │       │   │   │   ├── WCSGetCoverage.js
        │       │   │       │   │   │   ├── WFS.js
        │       │   │       │   │   │   ├── WFSCapabilities/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   ├── WFSCapabilities.js
        │       │   │       │   │   │   ├── WFSDescribeFeatureType.js
        │       │   │       │   │   │   ├── WFST/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   ├── WFST.js
        │       │   │       │   │   │   ├── WKT.js
        │       │   │       │   │   │   ├── WMC/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── WMC.js
        │       │   │       │   │   │   ├── WMSCapabilities/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_1.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   ├── v1_1_1.js
        │       │   │       │   │   │   │   ├── v1_1_1_WMSC.js
        │       │   │       │   │   │   │   ├── v1_3.js
        │       │   │       │   │   │   │   └── v1_3_0.js
        │       │   │       │   │   │   ├── WMSCapabilities.js
        │       │   │       │   │   │   ├── WMSDescribeLayer/
        │       │   │       │   │   │   │   └── v1_1.js
        │       │   │       │   │   │   ├── WMSDescribeLayer.js
        │       │   │       │   │   │   ├── WMSGetFeatureInfo.js
        │       │   │       │   │   │   ├── WMTSCapabilities/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── WMTSCapabilities.js
        │       │   │       │   │   │   ├── WPSCapabilities/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── WPSCapabilities.js
        │       │   │       │   │   │   ├── WPSDescribeProcess/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── WPSDescribeProcess.js
        │       │   │       │   │   │   ├── WPSExecute.js
        │       │   │       │   │   │   ├── XLS/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   └── v1_1_0.js
        │       │   │       │   │   │   ├── XLS.js
        │       │   │       │   │   │   ├── XML/
        │       │   │       │   │   │   │   └── VersionedOGC.js
        │       │   │       │   │   │   └── XML.js
        │       │   │       │   │   ├── Format.js
        │       │   │       │   │   ├── Geometry/
        │       │   │       │   │   │   ├── Collection.js
        │       │   │       │   │   │   ├── Curve.js
        │       │   │       │   │   │   ├── LineString.js
        │       │   │       │   │   │   ├── LinearRing.js
        │       │   │       │   │   │   ├── MultiLineString.js
        │       │   │       │   │   │   ├── MultiPoint.js
        │       │   │       │   │   │   ├── MultiPolygon.js
        │       │   │       │   │   │   ├── Point.js
        │       │   │       │   │   │   └── Polygon.js
        │       │   │       │   │   ├── Geometry.js
        │       │   │       │   │   ├── Handler/
        │       │   │       │   │   │   ├── Box.js
        │       │   │       │   │   │   ├── Click.js
        │       │   │       │   │   │   ├── Drag.js
        │       │   │       │   │   │   ├── Feature.js
        │       │   │       │   │   │   ├── Hover.js
        │       │   │       │   │   │   ├── Keyboard.js
        │       │   │       │   │   │   ├── MouseWheel.js
        │       │   │       │   │   │   ├── Path.js
        │       │   │       │   │   │   ├── Pinch.js
        │       │   │       │   │   │   ├── Point.js
        │       │   │       │   │   │   ├── Polygon.js
        │       │   │       │   │   │   └── RegularPolygon.js
        │       │   │       │   │   ├── Handler.js
        │       │   │       │   │   ├── Icon.js
        │       │   │       │   │   ├── Kinetic.js
        │       │   │       │   │   ├── Lang/
        │       │   │       │   │   │   ├── ar.js
        │       │   │       │   │   │   ├── be-tarask.js
        │       │   │       │   │   │   ├── bg.js
        │       │   │       │   │   │   ├── br.js
        │       │   │       │   │   │   ├── ca.js
        │       │   │       │   │   │   ├── cs-CZ.js
        │       │   │       │   │   │   ├── da-DK.js
        │       │   │       │   │   │   ├── de.js
        │       │   │       │   │   │   ├── el.js
        │       │   │       │   │   │   ├── en-CA.js
        │       │   │       │   │   │   ├── en.js
        │       │   │       │   │   │   ├── es.js
        │       │   │       │   │   │   ├── fi.js
        │       │   │       │   │   │   ├── fr.js
        │       │   │       │   │   │   ├── fur.js
        │       │   │       │   │   │   ├── gl.js
        │       │   │       │   │   │   ├── gsw.js
        │       │   │       │   │   │   ├── hr.js
        │       │   │       │   │   │   ├── hsb.js
        │       │   │       │   │   │   ├── hu.js
        │       │   │       │   │   │   ├── ia.js
        │       │   │       │   │   │   ├── id.js
        │       │   │       │   │   │   ├── io.js
        │       │   │       │   │   │   ├── is.js
        │       │   │       │   │   │   ├── it.js
        │       │   │       │   │   │   ├── ja.js
        │       │   │       │   │   │   ├── km.js
        │       │   │       │   │   │   ├── ksh.js
        │       │   │       │   │   │   ├── lt.js
        │       │   │       │   │   │   ├── nb.js
        │       │   │       │   │   │   ├── nds.js
        │       │   │       │   │   │   ├── nl.js
        │       │   │       │   │   │   ├── nn.js
        │       │   │       │   │   │   ├── oc.js
        │       │   │       │   │   │   ├── pl.js
        │       │   │       │   │   │   ├── pt-BR.js
        │       │   │       │   │   │   ├── pt.js
        │       │   │       │   │   │   ├── ro.js
        │       │   │       │   │   │   ├── ru.js
        │       │   │       │   │   │   ├── sk.js
        │       │   │       │   │   │   ├── sv-SE.js
        │       │   │       │   │   │   ├── te.js
        │       │   │       │   │   │   ├── vi.js
        │       │   │       │   │   │   ├── zh-CN.js
        │       │   │       │   │   │   └── zh-TW.js
        │       │   │       │   │   ├── Lang.js
        │       │   │       │   │   ├── Layer/
        │       │   │       │   │   │   ├── ArcGIS93Rest.js
        │       │   │       │   │   │   ├── ArcGISCache.js
        │       │   │       │   │   │   ├── ArcIMS.js
        │       │   │       │   │   │   ├── Bing.js
        │       │   │       │   │   │   ├── Boxes.js
        │       │   │       │   │   │   ├── EventPane.js
        │       │   │       │   │   │   ├── FixedZoomLevels.js
        │       │   │       │   │   │   ├── GeoRSS.js
        │       │   │       │   │   │   ├── Google/
        │       │   │       │   │   │   │   └── v3.js
        │       │   │       │   │   │   ├── Google.js
        │       │   │       │   │   │   ├── Grid.js
        │       │   │       │   │   │   ├── HTTPRequest.js
        │       │   │       │   │   │   ├── Image.js
        │       │   │       │   │   │   ├── KaMap.js
        │       │   │       │   │   │   ├── KaMapCache.js
        │       │   │       │   │   │   ├── MapGuide.js
        │       │   │       │   │   │   ├── MapServer.js
        │       │   │       │   │   │   ├── Markers.js
        │       │   │       │   │   │   ├── OSM.js
        │       │   │       │   │   │   ├── PointGrid.js
        │       │   │       │   │   │   ├── PointTrack.js
        │       │   │       │   │   │   ├── SphericalMercator.js
        │       │   │       │   │   │   ├── TMS.js
        │       │   │       │   │   │   ├── Text.js
        │       │   │       │   │   │   ├── TileCache.js
        │       │   │       │   │   │   ├── UTFGrid.js
        │       │   │       │   │   │   ├── Vector/
        │       │   │       │   │   │   │   └── RootContainer.js
        │       │   │       │   │   │   ├── Vector.js
        │       │   │       │   │   │   ├── WMS.js
        │       │   │       │   │   │   ├── WMTS.js
        │       │   │       │   │   │   ├── WorldWind.js
        │       │   │       │   │   │   ├── XYZ.js
        │       │   │       │   │   │   └── Zoomify.js
        │       │   │       │   │   ├── Layer.js
        │       │   │       │   │   ├── Map.js
        │       │   │       │   │   ├── Marker/
        │       │   │       │   │   │   └── Box.js
        │       │   │       │   │   ├── Marker.js
        │       │   │       │   │   ├── Popup/
        │       │   │       │   │   │   ├── Anchored.js
        │       │   │       │   │   │   ├── Framed.js
        │       │   │       │   │   │   └── FramedCloud.js
        │       │   │       │   │   ├── Popup.js
        │       │   │       │   │   ├── Projection.js
        │       │   │       │   │   ├── Protocol/
        │       │   │       │   │   │   ├── CSW/
        │       │   │       │   │   │   │   └── v2_0_2.js
        │       │   │       │   │   │   ├── CSW.js
        │       │   │       │   │   │   ├── HTTP.js
        │       │   │       │   │   │   ├── SOS/
        │       │   │       │   │   │   │   └── v1_0_0.js
        │       │   │       │   │   │   ├── SOS.js
        │       │   │       │   │   │   ├── Script.js
        │       │   │       │   │   │   ├── WFS/
        │       │   │       │   │   │   │   ├── v1.js
        │       │   │       │   │   │   │   ├── v1_0_0.js
        │       │   │       │   │   │   │   ├── v1_1_0.js
        │       │   │       │   │   │   │   └── v2_0_0.js
        │       │   │       │   │   │   └── WFS.js
        │       │   │       │   │   ├── Protocol.js
        │       │   │       │   │   ├── Renderer/
        │       │   │       │   │   │   ├── Canvas.js
        │       │   │       │   │   │   ├── Elements.js
        │       │   │       │   │   │   ├── SVG.js
        │       │   │       │   │   │   └── VML.js
        │       │   │       │   │   ├── Renderer.js
        │       │   │       │   │   ├── Request/
        │       │   │       │   │   │   └── XMLHttpRequest.js
        │       │   │       │   │   ├── Request.js
        │       │   │       │   │   ├── Rule.js
        │       │   │       │   │   ├── SingleFile.js
        │       │   │       │   │   ├── Spherical.js
        │       │   │       │   │   ├── Strategy/
        │       │   │       │   │   │   ├── BBOX.js
        │       │   │       │   │   │   ├── Cluster.js
        │       │   │       │   │   │   ├── Filter.js
        │       │   │       │   │   │   ├── Fixed.js
        │       │   │       │   │   │   ├── Paging.js
        │       │   │       │   │   │   ├── Refresh.js
        │       │   │       │   │   │   └── Save.js
        │       │   │       │   │   ├── Strategy.js
        │       │   │       │   │   ├── Style.js
        │       │   │       │   │   ├── Style2.js
        │       │   │       │   │   ├── StyleMap.js
        │       │   │       │   │   ├── Symbolizer/
        │       │   │       │   │   │   ├── Line.js
        │       │   │       │   │   │   ├── Point.js
        │       │   │       │   │   │   ├── Polygon.js
        │       │   │       │   │   │   ├── Raster.js
        │       │   │       │   │   │   └── Text.js
        │       │   │       │   │   ├── Symbolizer.js
        │       │   │       │   │   ├── Tile/
        │       │   │       │   │   │   ├── Image/
        │       │   │       │   │   │   │   └── IFrame.js
        │       │   │       │   │   │   ├── Image.js
        │       │   │       │   │   │   └── UTFGrid.js
        │       │   │       │   │   ├── Tile.js
        │       │   │       │   │   ├── TileManager.js
        │       │   │       │   │   ├── Tween.js
        │       │   │       │   │   ├── Util/
        │       │   │       │   │   │   └── vendorPrefix.js
        │       │   │       │   │   ├── Util.js
        │       │   │       │   │   ├── WPSClient.js
        │       │   │       │   │   └── WPSProcess.js
        │       │   │       │   ├── OpenLayers.js
        │       │   │       │   ├── Rico/
        │       │   │       │   │   ├── Color.js
        │       │   │       │   │   ├── Corner.js
        │       │   │       │   │   └── license.js
        │       │   │       │   └── deprecated.js
        │       │   │       ├── license.txt
        │       │   │       ├── licenses/
        │       │   │       │   ├── APACHE-2.0.txt
        │       │   │       │   ├── BSD-LICENSE.txt
        │       │   │       │   └── MIT-LICENSE.txt
        │       │   │       ├── notes/
        │       │   │       │   ├── 2.12.md
        │       │   │       │   ├── 2.13.md
        │       │   │       │   └── 2.14.md
        │       │   │       ├── readme.md
        │       │   │       ├── tests/
        │       │   │       │   ├── Animation.html
        │       │   │       │   ├── BaseTypes/
        │       │   │       │   │   ├── Bounds.html
        │       │   │       │   │   ├── Class.html
        │       │   │       │   │   ├── Date.html
        │       │   │       │   │   ├── Element.html
        │       │   │       │   │   ├── LonLat.html
        │       │   │       │   │   ├── Pixel.html
        │       │   │       │   │   └── Size.html
        │       │   │       │   ├── BaseTypes.html
        │       │   │       │   ├── Console.html
        │       │   │       │   ├── Control/
        │       │   │       │   │   ├── ArgParser.html
        │       │   │       │   │   ├── Attribution.html
        │       │   │       │   │   ├── Button.html
        │       │   │       │   │   ├── CacheRead.html
        │       │   │       │   │   ├── CacheWrite.html
        │       │   │       │   │   ├── DragFeature.html
        │       │   │       │   │   ├── DragPan.html
        │       │   │       │   │   ├── DrawFeature.html
        │       │   │       │   │   ├── EditingToolbar.html
        │       │   │       │   │   ├── Geolocate.html
        │       │   │       │   │   ├── GetFeature.html
        │       │   │       │   │   ├── Graticule.html
        │       │   │       │   │   ├── KeyboardDefaults.html
        │       │   │       │   │   ├── LayerSwitcher.html
        │       │   │       │   │   ├── Measure.html
        │       │   │       │   │   ├── ModifyFeature/
        │       │   │       │   │   │   └── BySegment.html
        │       │   │       │   │   ├── ModifyFeature.html
        │       │   │       │   │   ├── MousePosition.html
        │       │   │       │   │   ├── NavToolbar.html
        │       │   │       │   │   ├── Navigation.html
        │       │   │       │   │   ├── NavigationHistory.html
        │       │   │       │   │   ├── OverviewMap.html
        │       │   │       │   │   ├── Pan.html
        │       │   │       │   │   ├── PanPanel.html
        │       │   │       │   │   ├── PanZoom.html
        │       │   │       │   │   ├── PanZoomBar.html
        │       │   │       │   │   ├── Panel.html
        │       │   │       │   │   ├── Permalink.html
        │       │   │       │   │   ├── PinchZoom.html
        │       │   │       │   │   ├── SLDSelect.html
        │       │   │       │   │   ├── Scale.html
        │       │   │       │   │   ├── ScaleLine.html
        │       │   │       │   │   ├── SelectFeature.html
        │       │   │       │   │   ├── Snapping.html
        │       │   │       │   │   ├── Split.html
        │       │   │       │   │   ├── TextButtonPanel.html
        │       │   │       │   │   ├── TouchNavigation.html
        │       │   │       │   │   ├── TransformFeature.html
        │       │   │       │   │   ├── UTFGrid.html
        │       │   │       │   │   ├── WMSGetFeatureInfo.html
        │       │   │       │   │   ├── WMTSGetFeatureInfo.html
        │       │   │       │   │   ├── Zoom.html
        │       │   │       │   │   ├── ZoomBox.html
        │       │   │       │   │   ├── ZoomIn.html
        │       │   │       │   │   ├── ZoomOut.html
        │       │   │       │   │   └── ZoomToMaxExtent.html
        │       │   │       │   ├── Control.html
        │       │   │       │   ├── Events/
        │       │   │       │   │   ├── buttonclick.html
        │       │   │       │   │   └── featureclick.html
        │       │   │       │   ├── Events.html
        │       │   │       │   ├── Extras.html
        │       │   │       │   ├── Feature/
        │       │   │       │   │   └── Vector.html
        │       │   │       │   ├── Feature.html
        │       │   │       │   ├── Filter/
        │       │   │       │   │   ├── Comparison.html
        │       │   │       │   │   ├── FeatureId.html
        │       │   │       │   │   ├── Logical.html
        │       │   │       │   │   └── Spatial.html
        │       │   │       │   ├── Filter.html
        │       │   │       │   ├── Format/
        │       │   │       │   │   ├── ArcXML/
        │       │   │       │   │   │   └── Features.html
        │       │   │       │   │   ├── ArcXML.html
        │       │   │       │   │   ├── Atom.html
        │       │   │       │   │   ├── CQL.html
        │       │   │       │   │   ├── CSWGetDomain/
        │       │   │       │   │   │   ├── v2_0_2.html
        │       │   │       │   │   │   └── v2_0_2.js
        │       │   │       │   │   ├── CSWGetDomain.html
        │       │   │       │   │   ├── CSWGetRecords/
        │       │   │       │   │   │   ├── v2_0_2.html
        │       │   │       │   │   │   └── v2_0_2.js
        │       │   │       │   │   ├── CSWGetRecords.html
        │       │   │       │   │   ├── EncodedPolyline.html
        │       │   │       │   │   ├── Filter/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   ├── v1_1_0.html
        │       │   │       │   │   │   └── v2_0_0.html
        │       │   │       │   │   ├── Filter.html
        │       │   │       │   │   ├── GML/
        │       │   │       │   │   │   ├── cases.js
        │       │   │       │   │   │   ├── v2.html
        │       │   │       │   │   │   └── v3.html
        │       │   │       │   │   ├── GML.html
        │       │   │       │   │   ├── GPX.html
        │       │   │       │   │   ├── GeoJSON.html
        │       │   │       │   │   ├── GeoRSS.html
        │       │   │       │   │   ├── JSON.html
        │       │   │       │   │   ├── KML.html
        │       │   │       │   │   ├── OGCExceptionReport.html
        │       │   │       │   │   ├── OSM.html
        │       │   │       │   │   ├── OWSCommon/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_1_0.html
        │       │   │       │   │   ├── OWSContext/
        │       │   │       │   │   │   └── v0_3_1.html
        │       │   │       │   │   ├── QueryStringFilter.html
        │       │   │       │   │   ├── SLD/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_0_0_GeoServer.html
        │       │   │       │   │   ├── SLD.html
        │       │   │       │   │   ├── SOSCapabilities/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_0_0.js
        │       │   │       │   │   ├── SOSGetFeatureOfInterest.html
        │       │   │       │   │   ├── SOSGetObservation.html
        │       │   │       │   │   ├── TMSCapabilities.html
        │       │   │       │   │   ├── Text.html
        │       │   │       │   │   ├── WCSCapabilities/
        │       │   │       │   │   │   └── v1.html
        │       │   │       │   │   ├── WCSCapabilities.html
        │       │   │       │   │   ├── WCSDescribeCoverage/
        │       │   │       │   │   │   └── v1.html
        │       │   │       │   │   ├── WCSDescribeCoverage.html
        │       │   │       │   │   ├── WCSGetCoverage.html
        │       │   │       │   │   ├── WFS.html
        │       │   │       │   │   ├── WFSCapabilities/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   └── v2.html
        │       │   │       │   │   ├── WFSCapabilities.html
        │       │   │       │   │   ├── WFSDescribeFeatureType.html
        │       │   │       │   │   ├── WFST/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   ├── v1_1_0.html
        │       │   │       │   │   │   └── v2_0_0.html
        │       │   │       │   │   ├── WFST.html
        │       │   │       │   │   ├── WKT.html
        │       │   │       │   │   ├── WMC/
        │       │   │       │   │   │   ├── v1.html
        │       │   │       │   │   │   └── v1_1_0.html
        │       │   │       │   │   ├── WMC.html
        │       │   │       │   │   ├── WMSCapabilities/
        │       │   │       │   │   │   ├── v1_1_1.html
        │       │   │       │   │   │   ├── v1_1_1_WMSC.html
        │       │   │       │   │   │   └── v1_3_0.html
        │       │   │       │   │   ├── WMSCapabilities.html
        │       │   │       │   │   ├── WMSDescribeLayer.html
        │       │   │       │   │   ├── WMSGetFeatureInfo.html
        │       │   │       │   │   ├── WMTSCapabilities/
        │       │   │       │   │   │   └── v1_0_0.html
        │       │   │       │   │   ├── WMTSCapabilities.html
        │       │   │       │   │   ├── WPSCapabilities/
        │       │   │       │   │   │   ├── v1_0_0.html
        │       │   │       │   │   │   └── v1_0_0.js
        │       │   │       │   │   ├── WPSDescribeProcess.html
        │       │   │       │   │   ├── WPSExecute.html
        │       │   │       │   │   ├── XLS/
        │       │   │       │   │   │   └── v1_1_0.html
        │       │   │       │   │   ├── XML/
        │       │   │       │   │   │   └── VersionedOGC.html
        │       │   │       │   │   └── XML.html
        │       │   │       │   ├── Format.html
        │       │   │       │   ├── Geometry/
        │       │   │       │   │   ├── Collection.html
        │       │   │       │   │   ├── Curve.html
        │       │   │       │   │   ├── LineString.html
        │       │   │       │   │   ├── LinearRing.html
        │       │   │       │   │   ├── MultiLineString.html
        │       │   │       │   │   ├── MultiPoint.html
        │       │   │       │   │   ├── MultiPolygon.html
        │       │   │       │   │   ├── Point.html
        │       │   │       │   │   └── Polygon.html
        │       │   │       │   ├── Geometry.html
        │       │   │       │   ├── Handler/
        │       │   │       │   │   ├── Box.html
        │       │   │       │   │   ├── Click.html
        │       │   │       │   │   ├── Drag.html
        │       │   │       │   │   ├── Feature.html
        │       │   │       │   │   ├── Hover.html
        │       │   │       │   │   ├── Keyboard.html
        │       │   │       │   │   ├── MouseWheel.html
        │       │   │       │   │   ├── Path.html
        │       │   │       │   │   ├── Pinch.html
        │       │   │       │   │   ├── Point.html
        │       │   │       │   │   ├── Polygon.html
        │       │   │       │   │   └── RegularPolygon.html
        │       │   │       │   ├── Handler.html
        │       │   │       │   ├── Icon.html
        │       │   │       │   ├── Kinetic.html
        │       │   │       │   ├── Lang.html
        │       │   │       │   ├── Layer/
        │       │   │       │   │   ├── ArcGIS93Rest.html
        │       │   │       │   │   ├── ArcGISCache.html
        │       │   │       │   │   ├── ArcGISCache.json
        │       │   │       │   │   ├── ArcIMS.html
        │       │   │       │   │   ├── Bing.html
        │       │   │       │   │   ├── EventPane.html
        │       │   │       │   │   ├── FixedZoomLevels.html
        │       │   │       │   │   ├── GeoRSS.html
        │       │   │       │   │   ├── Google/
        │       │   │       │   │   │   └── v3.html
        │       │   │       │   │   ├── Grid.html
        │       │   │       │   │   ├── HTTPRequest.html
        │       │   │       │   │   ├── Image.html
        │       │   │       │   │   ├── KaMap.html
        │       │   │       │   │   ├── MapGuide.html
        │       │   │       │   │   ├── MapServer.html
        │       │   │       │   │   ├── Markers.html
        │       │   │       │   │   ├── OSM.html
        │       │   │       │   │   ├── PointGrid.html
        │       │   │       │   │   ├── PointTrack.html
        │       │   │       │   │   ├── SphericalMercator.html
        │       │   │       │   │   ├── TMS.html
        │       │   │       │   │   ├── Text.html
        │       │   │       │   │   ├── TileCache.html
        │       │   │       │   │   ├── UTFGrid.html
        │       │   │       │   │   ├── Vector/
        │       │   │       │   │   │   └── RootContainer.html
        │       │   │       │   │   ├── Vector.html
        │       │   │       │   │   ├── WMS.html
        │       │   │       │   │   ├── WMTS.html
        │       │   │       │   │   ├── WrapDateLine.html
        │       │   │       │   │   ├── XYZ.html
        │       │   │       │   │   ├── atom-1.0.xml
        │       │   │       │   │   ├── data_Layer_Text_textfile.txt
        │       │   │       │   │   ├── data_Layer_Text_textfile_2.txt
        │       │   │       │   │   ├── data_Layer_Text_textfile_overflow.txt
        │       │   │       │   │   └── georss.txt
        │       │   │       │   ├── Layer.html
        │       │   │       │   ├── Map.html
        │       │   │       │   ├── Marker/
        │       │   │       │   │   └── Box.html
        │       │   │       │   ├── Marker.html
        │       │   │       │   ├── OLLoader.js
        │       │   │       │   ├── OpenLayers1.html
        │       │   │       │   ├── OpenLayers2.html
        │       │   │       │   ├── OpenLayers3.html
        │       │   │       │   ├── OpenLayers4.html
        │       │   │       │   ├── OpenLayersJsFiles.html
        │       │   │       │   ├── Popup/
        │       │   │       │   │   ├── Anchored.html
        │       │   │       │   │   └── FramedCloud.html
        │       │   │       │   ├── Popup.html
        │       │   │       │   ├── Projection.html
        │       │   │       │   ├── Protocol/
        │       │   │       │   │   ├── CSW.html
        │       │   │       │   │   ├── HTTP.html
        │       │   │       │   │   ├── SOS.html
        │       │   │       │   │   ├── Script.html
        │       │   │       │   │   └── WFS.html
        │       │   │       │   ├── Protocol.html
        │       │   │       │   ├── README.txt
        │       │   │       │   ├── Renderer/
        │       │   │       │   │   ├── Canvas.html
        │       │   │       │   │   ├── Elements.html
        │       │   │       │   │   ├── SVG.html
        │       │   │       │   │   └── VML.html
        │       │   │       │   ├── Renderer.html
        │       │   │       │   ├── Request/
        │       │   │       │   │   └── XMLHttpRequest.html
        │       │   │       │   ├── Request.html
        │       │   │       │   ├── Rule.html
        │       │   │       │   ├── SingleFile1.html
        │       │   │       │   ├── SingleFile2.html
        │       │   │       │   ├── SingleFile3.html
        │       │   │       │   ├── Strategy/
        │       │   │       │   │   ├── BBOX.html
        │       │   │       │   │   ├── Cluster.html
        │       │   │       │   │   ├── Filter.html
        │       │   │       │   │   ├── Fixed.html
        │       │   │       │   │   ├── Paging.html
        │       │   │       │   │   ├── Refresh.html
        │       │   │       │   │   └── Save.html
        │       │   │       │   ├── Strategy.html
        │       │   │       │   ├── Style.html
        │       │   │       │   ├── Style2.html
        │       │   │       │   ├── StyleMap.html
        │       │   │       │   ├── Symbolizer/
        │       │   │       │   │   ├── Line.html
        │       │   │       │   │   ├── Point.html
        │       │   │       │   │   ├── Polygon.html
        │       │   │       │   │   ├── Raster.html
        │       │   │       │   │   └── Text.html
        │       │   │       │   ├── Symbolizer.html
        │       │   │       │   ├── Test.AnotherWay.baseadditions.js
        │       │   │       │   ├── Test.AnotherWay.css
        │       │   │       │   ├── Test.AnotherWay.geom_eq.js
        │       │   │       │   ├── Test.AnotherWay.js
        │       │   │       │   ├── Test.AnotherWay.xml_eq.js
        │       │   │       │   ├── Tile/
        │       │   │       │   │   ├── Image/
        │       │   │       │   │   │   └── IFrame.html
        │       │   │       │   │   ├── Image.html
        │       │   │       │   │   └── UTFGrid.html
        │       │   │       │   ├── Tile.html
        │       │   │       │   ├── TileManager.html
        │       │   │       │   ├── Tween.html
        │       │   │       │   ├── Util/
        │       │   │       │   │   └── vendorPrefix.html
        │       │   │       │   ├── Util.html
        │       │   │       │   ├── Util_common.js
        │       │   │       │   ├── Util_w3c.html
        │       │   │       │   ├── WPSClient.html
        │       │   │       │   ├── WPSProcess.html
        │       │   │       │   ├── atom-1.0.xml
        │       │   │       │   ├── auto-tests.html
        │       │   │       │   ├── data_Layer_Text_textfile.txt
        │       │   │       │   ├── data_Layer_Text_textfile_2.txt
        │       │   │       │   ├── data_Layer_Text_textfile_overflow.txt
        │       │   │       │   ├── deprecated/
        │       │   │       │   │   ├── Ajax.html
        │       │   │       │   │   ├── BaseTypes/
        │       │   │       │   │   │   ├── Class.html
        │       │   │       │   │   │   └── Element.html
        │       │   │       │   │   ├── Control/
        │       │   │       │   │   │   └── MouseToolbar.html
        │       │   │       │   │   ├── Geometry/
        │       │   │       │   │   │   └── Rectangle.html
        │       │   │       │   │   ├── Layer/
        │       │   │       │   │   │   ├── GML.html
        │       │   │       │   │   │   ├── MapServer/
        │       │   │       │   │   │   │   └── Untiled.html
        │       │   │       │   │   │   ├── MapServer.html
        │       │   │       │   │   │   ├── WFS.html
        │       │   │       │   │   │   ├── WMS/
        │       │   │       │   │   │   │   └── Post.html
        │       │   │       │   │   │   ├── WMS.html
        │       │   │       │   │   │   ├── Yahoo.html
        │       │   │       │   │   │   ├── mice.xml
        │       │   │       │   │   │   └── owls.xml
        │       │   │       │   │   ├── Popup/
        │       │   │       │   │   │   └── AnchoredBubble.html
        │       │   │       │   │   ├── Protocol/
        │       │   │       │   │   │   ├── SQL/
        │       │   │       │   │   │   │   └── Gears.html
        │       │   │       │   │   │   └── SQL.html
        │       │   │       │   │   ├── Renderer/
        │       │   │       │   │   │   └── SVG2.html
        │       │   │       │   │   ├── Tile/
        │       │   │       │   │   │   └── WFS.html
        │       │   │       │   │   └── Util.html
        │       │   │       │   ├── georss.txt
        │       │   │       │   ├── grid_inittiles.html
        │       │   │       │   ├── index.html
        │       │   │       │   ├── list-tests.html
        │       │   │       │   ├── manual/
        │       │   │       │   │   ├── ajax.html
        │       │   │       │   │   ├── ajax.txt
        │       │   │       │   │   ├── alloverlays-mixed.html
        │       │   │       │   │   ├── arcims-2117.html
        │       │   │       │   │   ├── arkansas.rss
        │       │   │       │   │   ├── big-georss.html
        │       │   │       │   │   ├── box-quirks.html
        │       │   │       │   │   ├── box-strict.html
        │       │   │       │   │   ├── clip-features-svg.html
        │       │   │       │   │   ├── dateline-sketch.html
        │       │   │       │   │   ├── dateline-smallextent.html
        │       │   │       │   │   ├── draw-feature.html
        │       │   │       │   │   ├── feature-handler.html
        │       │   │       │   │   ├── geodesic.html
        │       │   │       │   │   ├── geojson-geomcoll-reprojection.html
        │       │   │       │   │   ├── google-fullscreen-overlay.html
        │       │   │       │   │   ├── google-panning.html
        │       │   │       │   │   ├── google-resize.html
        │       │   │       │   │   ├── google-tilt.html
        │       │   │       │   │   ├── google-v3-resize.html
        │       │   │       │   │   ├── loadend.html
        │       │   │       │   │   ├── map-events.html
        │       │   │       │   │   ├── memory/
        │       │   │       │   │   │   ├── Marker-2258.html
        │       │   │       │   │   │   ├── PanZoom-2323.html
        │       │   │       │   │   │   ├── RemoveChild-2170.html
        │       │   │       │   │   │   └── VML-2170.html
        │       │   │       │   │   ├── multiple-google-layers.html
        │       │   │       │   │   ├── overviewmap-projection.html
        │       │   │       │   │   ├── page-position.html
        │       │   │       │   │   ├── pan-redraw-svg.html
        │       │   │       │   │   ├── popup-keepInMap.html
        │       │   │       │   │   ├── reflow.html
        │       │   │       │   │   ├── renderedDimensions.html
        │       │   │       │   │   ├── select-feature-right-click.html
        │       │   │       │   │   ├── select-feature.html
        │       │   │       │   │   ├── tiles-loading.html
        │       │   │       │   │   ├── tween.html
        │       │   │       │   │   ├── vector-features-performance.html
        │       │   │       │   │   └── vector-layer-zindex.html
        │       │   │       │   ├── mice.xml
        │       │   │       │   ├── node.js/
        │       │   │       │   │   ├── mockdom.js
        │       │   │       │   │   ├── node-tests.cfg
        │       │   │       │   │   ├── node.js
        │       │   │       │   │   ├── run-test.js
        │       │   │       │   │   └── run.sh
        │       │   │       │   ├── owls.xml
        │       │   │       │   ├── run-tests.html
        │       │   │       │   ├── selenium/
        │       │   │       │   │   └── remotecontrol/
        │       │   │       │   │       ├── config.cfg
        │       │   │       │   │       ├── selenium.py
        │       │   │       │   │       ├── setup.txt
        │       │   │       │   │       └── test_ol.py
        │       │   │       │   ├── speed/
        │       │   │       │   │   ├── geometry.html
        │       │   │       │   │   ├── string_format.html
        │       │   │       │   │   ├── vector-renderers.html
        │       │   │       │   │   ├── vector-renderers.js
        │       │   │       │   │   ├── wmc_speed.html
        │       │   │       │   │   ├── wmscaps.html
        │       │   │       │   │   ├── wmscaps.js
        │       │   │       │   │   └── wmscaps.xml
        │       │   │       │   └── throws.js
        │       │   │       ├── theme/
        │       │   │       │   └── default/
        │       │   │       │       ├── google.css
        │       │   │       │       ├── ie6-style.css
        │       │   │       │       ├── style.css
        │       │   │       │       └── style.mobile.css
        │       │   │       └── tools/
        │       │   │           ├── BeautifulSoup.py
        │       │   │           ├── README.txt
        │       │   │           ├── closure_library_jscompiler.py
        │       │   │           ├── closure_ws.py
        │       │   │           ├── exampleparser.py
        │       │   │           ├── jsmin.c
        │       │   │           ├── jsmin.py
        │       │   │           ├── mergejs.py
        │       │   │           ├── minimize.py
        │       │   │           ├── oldot.py
        │       │   │           ├── release.sh
        │       │   │           ├── shrinksafe.py
        │       │   │           ├── toposort.py
        │       │   │           ├── uglify_js.py
        │       │   │           └── update_dev_dir.sh
        │       │   ├── css/
        │       │   │   ├── ie-only.css
        │       │   │   └── tatami.css
        │       │   └── vendor/
        │       │       ├── backgroundsize.min.htc
        │       │       ├── css/
        │       │       │   └── bootstrap/
        │       │       │       ├── css/
        │       │       │       │   └── bootstrap.css
        │       │       │       ├── fonts/
        │       │       │       │   └── glyphiconshalflings-regular.otf
        │       │       │       └── js/
        │       │       │           └── bootstrap.js
        │       │       └── js/
        │       │           ├── marked/
        │       │           │   └── marked.js
        │       │           └── respond/
        │       │               └── respond.js
        │       ├── css/
        │       │   ├── ie-only.css
        │       │   ├── tatami.css
        │       │   └── vendor/
        │       │       ├── backgroundsize.min.htc
        │       │       ├── css/
        │       │       │   ├── bootstrap.css
        │       │       │   └── jQueryjGrowl.css
        │       │       └── fonts/
        │       │           └── glyphiconshalflings-regular.otf
        │       ├── index.html
        │       ├── index.html.tpl
        │       ├── index.jsp
        │       ├── robots.txt
        │       └── sitemap.xml
        └── test/
            ├── java/
            │   └── fr/
            │       └── ippon/
            │           └── tatami/
            │               └── web/
            │                   └── rest/
            │                       ├── GroupControllerTest.java
            │                       ├── TagControllerTest.java
            │                       ├── TimelineControllerTest.java
            │                       └── UserControllerTest.java
            └── javascript/
                └── webapp/
                    └── app/
                        └── components/
                            ├── about/
                            │   └── license/
                            │       └── LicenseController_spec.js
                            ├── account/
                            │   ├── PasswordModule_spec.js
                            │   └── preferences/
                            │       └── Preferences_spec.js
                            └── home/
                                └── status/
                                    └── StatusController_spec.js
Copy disabled (too large) Download .json
Condensed preview — 1921 files, each showing path, character count, and a content snippet. Download the .json file for the full structured content (14,377K chars).
[
  {
    "path": ".gitignore",
    "chars": 492,
    "preview": "data\n.idea\n*.iml\ntatami.iml\ntatami.ipr\ntatami.iws\n.classpath\n.project\n.settings\ntarget\nnode_modules/\nweb/node_modules/\ns"
  },
  {
    "path": "CONTRIBUTING.md",
    "chars": 1482,
    "preview": "Contributing to Tatami\n=========================\n\nOpen Source\n------------------\n\nTatami is an Open Source project, whic"
  },
  {
    "path": "README.md",
    "chars": 7622,
    "preview": "Tatami\n================\n\nPresentation\n------------------\n\nTatami is an Open Source enterprise social network.\n\nA public "
  },
  {
    "path": "etc/installation/ubuntu/files/maven/settings.xml",
    "chars": 756,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n\n<settings xmlns=\"http://maven.apache.org/SETTINGS/1.0.0\"\n          xmlns:xsi=\"ht"
  },
  {
    "path": "etc/installation/ubuntu/install.sh",
    "chars": 5351,
    "preview": "#!/bin/sh\n#\n# description: Installs Tatami on Ubuntu\n# This script must be run by the \"root\" user.\n# Run this script dir"
  },
  {
    "path": "etc/installation/ubuntu/uninstall.sh",
    "chars": 475,
    "preview": "#!/bin/sh\n#\n# description: Uninstalls Tatami on Ubuntu\n# This script must be run by the \"root\" user.\n#\n# Run this script"
  },
  {
    "path": "etc/installation/ubuntu/update.sh",
    "chars": 663,
    "preview": "#!/bin/sh\n#\n# description: Updates Tatami from Git\n# This script must be run by the \"tatami\" user, who must be a sudoer."
  },
  {
    "path": "jenkinsScripts/insertGoogleAuthKeys.sh",
    "chars": 612,
    "preview": "#!/bin/bash\n\n#Insert google auth variables into the build. \ngoogleKey=$1\ngoogleSecret=$2\nnewServer=$3\n\n\nusage='startTata"
  },
  {
    "path": "jenkinsScripts/restoreDatabase.sh",
    "chars": 183,
    "preview": "#!/bin/bash\n\nrm -rf ../target/cassandra || true\nrm -rf ./target/elasticsearch || true\n\ntar -zxvf save.tar.gz -C ../targe"
  },
  {
    "path": "jenkinsScripts/saveDatabase.sh",
    "chars": 122,
    "preview": "#!/bin/bash\n\ntar -zcvf save.tar.gz ../target/cassandra ../target/elasticsearch\ntar -zcvf db.tar.gz ./target/elasticsearc"
  },
  {
    "path": "jenkinsScripts/startTatami.sh",
    "chars": 322,
    "preview": "#!/bin/bash\n\n#Insert google Authentication keys.\n./insertGoogleAuthKeys.sh $1 $2 $3\n\nif [ $? -ne 0 ]; then\n    exit 1\nfi"
  },
  {
    "path": "jenkinsScripts/stopTatami.sh",
    "chars": 68,
    "preview": "#!/bin/bash\ncat tatamiPID | xargs kill || true\nrm tatamiPID || true\n"
  },
  {
    "path": "mobile/.bowerrc",
    "chars": 29,
    "preview": "{\n  \"directory\": \"www/lib\"\n}\n"
  },
  {
    "path": "mobile/.editorconfig",
    "chars": 242,
    "preview": "# http://editorconfig.org\nroot = true\n\n[*]\ncharset = utf-8\nindent_style = space\nindent_size = 4\nend_of_line = lf\ninsert_"
  },
  {
    "path": "mobile/.gitignore",
    "chars": 147,
    "preview": "# Specifies intentionally untracked files to ignore when using Git\n# http://git-scm.com/docs/gitignore\n\nwww/lib/\nnode_mo"
  },
  {
    "path": "mobile/README.md",
    "chars": 702,
    "preview": "Tatami Mobile Beta\n==================\n\nIf interested in the mobile beta, follow these steps:\n\nPrepare Project\n----------"
  },
  {
    "path": "mobile/bower.json",
    "chars": 645,
    "preview": "{\n  \"name\": \"tatami\",\n  \"private\": \"true\",\n  \"devDependencies\": {\n    \"ionic\": \"~1.2.4\",\n    \"angular-mocks\": \"1.4.3\",\n "
  },
  {
    "path": "mobile/config.xml",
    "chars": 4903,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?>\n<widget id=\"com.ippon.tatami.mobile\" version=\"1.0.1\" xmlns=\"http"
  },
  {
    "path": "mobile/gulpfile.js",
    "chars": 2574,
    "preview": "var gulp = require('gulp');\nvar gutil = require('gulp-util');\nvar bower = require('bower');\nvar concat = require('gulp-c"
  },
  {
    "path": "mobile/hooks/README.md",
    "chars": 3018,
    "preview": "<!--\n#\n# Licensed to the Apache Software Foundation (ASF) under one\n# or more contributor license agreements.  See the N"
  },
  {
    "path": "mobile/hooks/after_prepare/010_add_platform_class.js",
    "chars": 2735,
    "preview": "#!/usr/bin/env node\n\n// Add Platform Class\n// v1.0\n// Automatically adds the platform class to the body tag\n// after the"
  },
  {
    "path": "mobile/ionic.project",
    "chars": 393,
    "preview": "{\n    \"name\": \"mobile\",\n    \"app_id\": \"\",\n    \"proxies\": [\n        {\n            \"path\": \"/tatami\",\n            \"proxyUr"
  },
  {
    "path": "mobile/karma.ci.conf.js",
    "chars": 2287,
    "preview": "// Karma configuration\n// Generated on Wed May 06 2015 15:23:11 GMT-0400 (EDT)\n\nmodule.exports = function (config) {\n   "
  },
  {
    "path": "mobile/package.json",
    "chars": 1319,
    "preview": "{\n  \"name\": \"mobile\",\n  \"version\": \"1.1.1\",\n  \"description\": \"mobile: An Ionic project\",\n  \"dependencies\": {\n    \"gulp\":"
  },
  {
    "path": "mobile/pom.xml",
    "chars": 7491,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "mobile/scss/ionic.app.scss",
    "chars": 1552,
    "preview": "/*\nTo customize the look and feel of Ionic, you can override the variables\nin ionic's _variables.scss file.\n\nFor example"
  },
  {
    "path": "mobile/www/app/components/follow/follow.html",
    "chars": 767,
    "preview": "<ion-view>\n    <ion-tabs class=\"tabs-icon-top tabs-color-active-positive\">\n\n        <ion-tab title=\"{{ 'tab.suggested.ti"
  },
  {
    "path": "mobile/www/app/components/follow/follow.js",
    "chars": 1036,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(followConfig);\n\n    followConfig.$inject ="
  },
  {
    "path": "mobile/www/app/components/follow/follower/follower.controller.js",
    "chars": 659,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('FollowerCtrl', followerCtrl);\n\n    fo"
  },
  {
    "path": "mobile/www/app/components/follow/follower/follower.html",
    "chars": 423,
    "preview": "<ion-view view-title=\"{{ 'tab.follower' | translate }}\">\n    <ion-content class=\"tatami-header tatami-footer\" ng-style=\""
  },
  {
    "path": "mobile/www/app/components/follow/follower/follower.js",
    "chars": 1186,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/follow/following/following.controller.js",
    "chars": 666,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('FollowingCtrl', FollowingCtrl);\n\n    "
  },
  {
    "path": "mobile/www/app/components/follow/following/following.html",
    "chars": 424,
    "preview": "<ion-view view-title=\"{{ 'tab.following' | translate }}\">\n    <ion-content class=\"tatami-header tatami-footer\" ng-style="
  },
  {
    "path": "mobile/www/app/components/follow/following/following.js",
    "chars": 1204,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/follow/suggested/suggested.controller.js",
    "chars": 645,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('SuggestedCtrl', suggestedCtrl);\n\n    "
  },
  {
    "path": "mobile/www/app/components/follow/suggested/suggested.html",
    "chars": 428,
    "preview": "<ion-view view-title=\"{{ 'tab.suggested.who' | translate }}\">\n    <ion-content class=\"tatami-header tatami-footer\" ng-st"
  },
  {
    "path": "mobile/www/app/components/follow/suggested/suggested.js",
    "chars": 1144,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/favorites/favorites.controller.js",
    "chars": 803,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('FavoritesCtrl', favoritesCtrl);\n\n    "
  },
  {
    "path": "mobile/www/app/components/home/favorites/favorites.html",
    "chars": 376,
    "preview": "<ion-view view-title=\"{{ 'tab.favorites' | translate }}\" ng-style=\"{'background-color':'#f5f5f5'}\">\n    <tatami-status-l"
  },
  {
    "path": "mobile/www/app/components/home/favorites/favorites.js",
    "chars": 1139,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/home.html",
    "chars": 1112,
    "preview": "<ion-tabs class=\"tabs-icon-top tabs-color-active-positive\">\n    <!-- Dashboard Tab -->\n    <ion-tab title=\"{{ 'tab.timel"
  },
  {
    "path": "mobile/www/app/components/home/home.js",
    "chars": 1092,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(homeConfig);\n\n    homeConfig.$inject = ['$"
  },
  {
    "path": "mobile/www/app/components/home/mentions/mentions.controller.js",
    "chars": 959,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('MentionsCtrl', mentionsCtrl);\n\n    me"
  },
  {
    "path": "mobile/www/app/components/home/mentions/mentions.html",
    "chars": 381,
    "preview": "<ion-view view-title=\"{{ 'tab.mentions' | translate }}\" ng-style=\"{'background-color':'#f5f5f5'}\">\n    <tatami-status-li"
  },
  {
    "path": "mobile/www/app/components/home/mentions/mentions.js",
    "chars": 1115,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/more/all_users/all.users.controller.js",
    "chars": 948,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('AllUsersController', allUsersControll"
  },
  {
    "path": "mobile/www/app/components/home/more/all_users/all.users.html",
    "chars": 510,
    "preview": "<ion-view view-title=\"{{ 'more.allUsers' | translate }}\">\n    <ion-content class=\"tatami-header tatami-footer\" ng-style="
  },
  {
    "path": "mobile/www/app/components/home/more/all_users/all.users.js",
    "chars": 905,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/more/blocked_users/blocked.users.controller.js",
    "chars": 1109,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('BlockedUsersController', blockedUsers"
  },
  {
    "path": "mobile/www/app/components/home/more/blocked_users/blocked.users.html",
    "chars": 639,
    "preview": "<ion-view view-title=\"{{ 'more.blockedUsers.title' | translate }}\">\n    <ion-content ng-style=\"{'background-color':'#f5f"
  },
  {
    "path": "mobile/www/app/components/home/more/blocked_users/blocked.users.js",
    "chars": 937,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/more/company/company-timeline.html",
    "chars": 380,
    "preview": "<ion-view view-title=\"{{ 'more.company' | translate }}\" ng-style=\"{'background-color':'#f5f5f5'}\">\n    <tatami-status-li"
  },
  {
    "path": "mobile/www/app/components/home/more/company/company.timeline.controller.js",
    "chars": 822,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('CompanyTimelineCtrl', companyTimeline"
  },
  {
    "path": "mobile/www/app/components/home/more/company/company.timeline.js",
    "chars": 1167,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/more/more.controller.js",
    "chars": 1154,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('MoreController', moreController);\n\n  "
  },
  {
    "path": "mobile/www/app/components/home/more/more.html",
    "chars": 1959,
    "preview": "<ion-view view-title=\"{{ 'tab.more' | translate }}\">\n    <ion-content class=\"tatami-header tatami-footer\" ng-style=\"{'ba"
  },
  {
    "path": "mobile/www/app/components/home/more/more.js",
    "chars": 1154,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(moreConfig);\n\n    moreConfig.$inject = ['$"
  },
  {
    "path": "mobile/www/app/components/home/more/reportedStatus/reportedStatus.controller.js",
    "chars": 3199,
    "preview": "/**\n * Created by emilyklein on 7/11/16.\n */\n(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .cont"
  },
  {
    "path": "mobile/www/app/components/home/more/reportedStatus/reportedStatus.html",
    "chars": 1028,
    "preview": "<ion-view view-title=\"{{ 'more.reportedStatus.title' | translate }}\">\n    <ion-content class=\"tatami-header tatami-foote"
  },
  {
    "path": "mobile/www/app/components/home/more/reportedStatus/reportedStatus.js",
    "chars": 1026,
    "preview": "/**\n * Created by emilyklein on 7/11/16.\n */\n(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .conf"
  },
  {
    "path": "mobile/www/app/components/home/more/settings/settings.controller.js",
    "chars": 879,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('SettingsController', settingsControll"
  },
  {
    "path": "mobile/www/app/components/home/more/settings/settings.html",
    "chars": 515,
    "preview": "<ion-view view-title=\"{{ 'more.settings' | translate }}\">\n    <ion-content ng-style=\"{'background-color':'#f5f5f5'}\">\n  "
  },
  {
    "path": "mobile/www/app/components/home/more/settings/settings.js",
    "chars": 903,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/home/timeline/timeline.controller.js",
    "chars": 788,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('TimelineCtrl', timelineCtrl);\n\n    ti"
  },
  {
    "path": "mobile/www/app/components/home/timeline/timeline.html",
    "chars": 380,
    "preview": "<ion-view view-title=\"{{ 'tab.timeline' | translate }}\" ng-style=\"{'background-color':'#f5f5f5'}\">\n    <tatami-status-li"
  },
  {
    "path": "mobile/www/app/components/home/timeline/timeline.js",
    "chars": 1146,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/login/login.controller.js",
    "chars": 4601,
    "preview": "(function () {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('LoginCtrl', loginCtrl);\n\n    loginCt"
  },
  {
    "path": "mobile/www/app/components/login/login.html",
    "chars": 2467,
    "preview": "<ion-view name=\"login-view\" view-title=\"{{ 'login.title' | translate }}\" hide-back-button=\"true\">\n    <ion-content class"
  },
  {
    "path": "mobile/www/app/components/login/login.js",
    "chars": 844,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/login/server/server.controller.js",
    "chars": 1984,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('ServerController', serverController);"
  },
  {
    "path": "mobile/www/app/components/login/server/server.html",
    "chars": 1568,
    "preview": "<ion-view view-title=\"\">\n    <ion-content ng-style=\"{'background-color':'#f5f5f5'}\">\n        <ion-list>\n            <ion"
  },
  {
    "path": "mobile/www/app/components/login/server/server.js",
    "chars": 976,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(config);\n\n    config.$inject = ['$statePro"
  },
  {
    "path": "mobile/www/app/components/post/post.controller.js",
    "chars": 6994,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('PostCtrl', postCtrl);\n\n    postCtrl.$"
  },
  {
    "path": "mobile/www/app/components/post/post.html",
    "chars": 2570,
    "preview": "<ion-view view-title=\"{{ 'post.title' | translate }}\" hide-back-button=\"true\">\n    <ion-nav-buttons side=\"secondary\">\n  "
  },
  {
    "path": "mobile/www/app/components/post/post.js",
    "chars": 1167,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(postConfig);\n\n    postConfig.$inject = ['$"
  },
  {
    "path": "mobile/www/app/components/post/postbar.directive.js",
    "chars": 2062,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .directive('tatamiPostBarAttach', tatamiPostBar);\n"
  },
  {
    "path": "mobile/www/app/shared/config/marked.config.js",
    "chars": 2997,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .config(markedConfig);\n\n    markedConfig.$inject ="
  },
  {
    "path": "mobile/www/app/shared/config/marked.filter.js",
    "chars": 274,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .filter('markdown', markdown);\n\n    markdown.$inje"
  },
  {
    "path": "mobile/www/app/shared/config/tatami.marked.js",
    "chars": 32688,
    "preview": "/**\n * marked - a markdown parser\n * Copyright (c) 2011-2013, Christopher Jeffrey. (MIT Licensed)\n * https://github.com/"
  },
  {
    "path": "mobile/www/app/shared/interceptor/auth.interceptor.js",
    "chars": 2735,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .factory('authInterceptor', authInterceptor)\n     "
  },
  {
    "path": "mobile/www/app/shared/providers/provider.js",
    "chars": 84,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.providers', []);\n\n})();\n"
  },
  {
    "path": "mobile/www/app/shared/providers/tatami.state.provider.js",
    "chars": 6921,
    "preview": "(function() {\n    'use strict';\n\n    // This will dynamically create any tab substates inside the current tab. If in the"
  },
  {
    "path": "mobile/www/app/shared/services/HomeService.js",
    "chars": 1627,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('HomeService', homeService);\n\n  "
  },
  {
    "path": "mobile/www/app/shared/services/ProfileService.js",
    "chars": 955,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('ProfileService', profileService"
  },
  {
    "path": "mobile/www/app/shared/services/StatusService.js",
    "chars": 4368,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('StatusService', statusService);"
  },
  {
    "path": "mobile/www/app/shared/services/UserService.js",
    "chars": 2968,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('UserService', userService);\n\n  "
  },
  {
    "path": "mobile/www/app/shared/services/account.service.js",
    "chars": 319,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('AccountService', accountService"
  },
  {
    "path": "mobile/www/app/shared/services/block.service.js",
    "chars": 1310,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('BlockService', blockService);\n\n"
  },
  {
    "path": "mobile/www/app/shared/services/localStorage.service.js",
    "chars": 1128,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('$localStorage', localStorage);\n"
  },
  {
    "path": "mobile/www/app/shared/services/path.service.js",
    "chars": 830,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('PathService', avatarService);\n\n"
  },
  {
    "path": "mobile/www/app/shared/services/report.service.js",
    "chars": 1329,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('ReportService', reportService);"
  },
  {
    "path": "mobile/www/app/shared/services/service.js",
    "chars": 83,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services', []);\n\n})();\n"
  },
  {
    "path": "mobile/www/app/shared/services/tag.service.js",
    "chars": 1649,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('TagService', tagService);\n\n    "
  },
  {
    "path": "mobile/www/app/shared/services/toast.service.js",
    "chars": 716,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('ToastService', ToastService);\n\n"
  },
  {
    "path": "mobile/www/app/shared/state/conversation/conversation.controller.js",
    "chars": 1177,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('ConversationCtrl', conversationCtrl);"
  },
  {
    "path": "mobile/www/app/shared/state/conversation/conversation.html",
    "chars": 210,
    "preview": "<ion-view view-title=\"{{ 'conversation.title' | translate }}\">\n        <tatami-status-list statuses=\"vm.conversation\"\n  "
  },
  {
    "path": "mobile/www/app/shared/state/profile/profile.controller.js",
    "chars": 3479,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('ProfileCtrl', profileCtrl);\n\n    prof"
  },
  {
    "path": "mobile/www/app/shared/state/profile/profile.html",
    "chars": 1066,
    "preview": "<ion-view view-title=\"@{{ vm.user.username }}\">\n    <ion-nav-buttons side=\"secondary\">\n        <button class=\"button ion"
  },
  {
    "path": "mobile/www/app/shared/state/profile/userOptionsMenu.html",
    "chars": 983,
    "preview": "<ion-popover-view ng-style=\"vm.customHeight\" scroll=\"false\">\n    <ion-content>\n        <div class=\"list\" ng-click=\"popov"
  },
  {
    "path": "mobile/www/app/shared/state/tag/tag.controller.js",
    "chars": 801,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('TagCtrl', tagCtrl);\n\n    tagCtrl.$inj"
  },
  {
    "path": "mobile/www/app/shared/state/tag/tag.html",
    "chars": 319,
    "preview": "<ion-view view-title=\"#{{ vm.tag }}\">\n    <tatami-status-list statuses=\"vm.statuses\"\n                        current-use"
  },
  {
    "path": "mobile/www/app/shared/status/blockUserMenu.html",
    "chars": 1370,
    "preview": "<ion-popover-view ng-style=\"vm.customHeight\">\n    <ion-content>\n        <div class=\"list\" ng-click=\"popover.hide()\">\n   "
  },
  {
    "path": "mobile/www/app/shared/status/list/status-list.html",
    "chars": 710,
    "preview": "<ion-content class=\"tatami-header tatami-footer\">\n    <ion-refresher ng-if=\"!vm.$state.includes('*.conversation')\" on-re"
  },
  {
    "path": "mobile/www/app/shared/status/list/status.list.directive.js",
    "chars": 1985,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .directive('tatamiStatusList', tatamiStatusList);\n"
  },
  {
    "path": "mobile/www/app/shared/status/status.directive.js",
    "chars": 6592,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .directive('tatamiStatus', tatamiStatus);\n\n    fun"
  },
  {
    "path": "mobile/www/app/shared/status/status.html",
    "chars": 3913,
    "preview": "<span>\n    <div class=\"item-avatar item-text-wrap tatami-avatar\">\n        <img ng-src=\"{{ vm.status.avatarURL }}\"/>\n    "
  },
  {
    "path": "mobile/www/app/shared/status/status.refresher.service.js",
    "chars": 3197,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .factory('TatamiStatusRefresherService', tatamiSta"
  },
  {
    "path": "mobile/www/app/shared/user/user-detail.html",
    "chars": 383,
    "preview": "<ion-item>\n    <div class=\"row\">\n        <div class=\"col\">\n            <img ng-src=\"{{ vm.user.avatarURL }}\" class=\"cent"
  },
  {
    "path": "mobile/www/app/shared/user/user.detail.directive.js",
    "chars": 580,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .directive('tatamiUserDetail', tatamiUserDetail);\n"
  },
  {
    "path": "mobile/www/app/shared/user/user.directive.js",
    "chars": 3285,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .directive('tatamiUser', tatamiUser);\n\n    tatamiU"
  },
  {
    "path": "mobile/www/app/shared/user/user.html",
    "chars": 1656,
    "preview": "<ion-item class=\"item-remove-animate item-avatar item-icon-right\" ng-click=\"vm.goToProfile(vm.user.username)\">\n    <img "
  },
  {
    "path": "mobile/www/app/shared/user/user.refresher.service.js",
    "chars": 1744,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami.services')\n        .factory('TatamiUserRefresherService', ta"
  },
  {
    "path": "mobile/www/app/shared/user/users.directive.js",
    "chars": 922,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .directive('tatamiUser', tatamiUser);\n\n    tatamiU"
  },
  {
    "path": "mobile/www/app/shared/user/users.html",
    "chars": 716,
    "preview": "<ion-item class=\"item-remove-animate item-avatar item-icon-right\" ui-sref=\"profile({ username: vm.user.username })\">\n   "
  },
  {
    "path": "mobile/www/app/tatami.controller.js",
    "chars": 244,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami')\n        .controller('TatamiCtrl', tatamiCtrl);\n\n    tatami"
  },
  {
    "path": "mobile/www/app/tatami.endpoint.js",
    "chars": 1172,
    "preview": "(function() {\n    'use strict';\n    var defaultEndpoint = {url: 'http://tatami.ippon.fr'};\n    var endpoint;\n\n    angula"
  },
  {
    "path": "mobile/www/app/tatami.html",
    "chars": 1017,
    "preview": "<ion-header-bar align-title=\"center\" class=\"bar-header bar-dark\">\n    <div class=\"buttons\" ng-if=\"!vm.$state.includes('l"
  },
  {
    "path": "mobile/www/app/tatamiApp.js",
    "chars": 6116,
    "preview": "(function() {\n    'use strict';\n\n    angular.module('tatami', [\n        'ionic',\n        'tatami.services',\n        'tat"
  },
  {
    "path": "mobile/www/css/ionic.app.css",
    "chars": 243731,
    "preview": "@charset \"UTF-8\";\n/*\nTo customize the look and feel of Ionic, you can override the variables\nin ionic's _variables.scss "
  },
  {
    "path": "mobile/www/css/style.css",
    "chars": 1081,
    "preview": "/* General classes */\n.pull-right {\n    float:right;\n}\n.clearfix {\n    clear:both;\n}\n.subheading, .date {\n    font-size:"
  },
  {
    "path": "mobile/www/i18n/en/conversation.json",
    "chars": 64,
    "preview": "{\n    \"conversation\": {\n        \"title\": \"Conversation\"\n    }\n}\n"
  },
  {
    "path": "mobile/www/i18n/en/follow.json",
    "chars": 192,
    "preview": "{\n    \"tab\": {\n        \"follower\": \"Followers\",\n        \"following\": \"Following\",\n        \"suggested\": {\n            \"ti"
  },
  {
    "path": "mobile/www/i18n/en/home.json",
    "chars": 183,
    "preview": "{\n    \"tab\": {\n        \"timeline\": \"Timeline\",\n        \"mentions\": \"Mentions\",\n        \"favorites\": \"Favorites\",\n       "
  },
  {
    "path": "mobile/www/i18n/en/login.json",
    "chars": 499,
    "preview": "{\n    \"login\": {\n        \"title\": \"Login\",\n        \"email\": \"E-mail\",\n        \"password\": \"Password\",\n        \"google\": "
  },
  {
    "path": "mobile/www/i18n/en/more.json",
    "chars": 586,
    "preview": "{\n    \"more\": {\n        \"title\": \"More Options\",\n        \"company\": \"Company Timeline\",\n        \"settings\": \"Settings\",\n"
  },
  {
    "path": "mobile/www/i18n/en/post.json",
    "chars": 680,
    "preview": "{\n    \"post\": {\n        \"title\": \"Post\",\n        \"message\": \"Post Here...\",\n        \"progress\": \"Post in progress...\",\n "
  },
  {
    "path": "mobile/www/i18n/en/server.json",
    "chars": 646,
    "preview": "{\n    \"server\": {\n        \"success\": \"Logged In!\",\n        \"failed\": \"Failed to log in!\",\n        \"progress\": \"Login in "
  },
  {
    "path": "mobile/www/i18n/en/status.json",
    "chars": 1726,
    "preview": "{\n    \"status\": {\n        \"share\": {\n            \"title\": \"shared\",\n            \"mention\": \"Your status has been shared\""
  },
  {
    "path": "mobile/www/i18n/en/user.json",
    "chars": 1005,
    "preview": "{\n    \"user\": {\n        \"profile\": {\n            \"title\": \"Profile\",\n            \"options\": {\n                \"block\": \""
  },
  {
    "path": "mobile/www/i18n/fr/conversation.json",
    "chars": 64,
    "preview": "{\n    \"conversation\": {\n        \"title\": \"Conversation\"\n    }\n}\n"
  },
  {
    "path": "mobile/www/i18n/fr/follow.json",
    "chars": 189,
    "preview": "{\n    \"tab\": {\n        \"follower\": \"Abonnés\",\n        \"following\": \"Abonnement\",\n        \"suggested\": {\n            \"tit"
  },
  {
    "path": "mobile/www/i18n/fr/home.json",
    "chars": 199,
    "preview": "{\n    \"tab\": {\n        \"timeline\": \"Timeline\",\n        \"mentions\": \"Mentions\",\n        \"favorites\": \"Favoris\",\n        \""
  },
  {
    "path": "mobile/www/i18n/fr/login.json",
    "chars": 536,
    "preview": "{\n    \"login\": {\n        \"title\": \"Login\",\n        \"email\": \"E-mail\",\n        \"password\": \"Mot de passe\",\n        \"googl"
  },
  {
    "path": "mobile/www/i18n/fr/more.json",
    "chars": 628,
    "preview": "{\n    \"more\": {\n        \"title\": \"Plus d'options\",\n        \"company\": \"Timeline de l'entreprise\",\n        \"settings\": \"P"
  },
  {
    "path": "mobile/www/i18n/fr/post.json",
    "chars": 724,
    "preview": "{\n    \"post\": {\n        \"title\": \"Post\",\n        \"message\": \"Ecrivez votre message ici...\",\n        \"progress\": \"Publica"
  },
  {
    "path": "mobile/www/i18n/fr/server.json",
    "chars": 691,
    "preview": "{\n    \"server\": {\n        \"success\": \"Connexion effectuée !\",\n        \"failed\": \"Echec de connexion\",\n        \"progress\""
  },
  {
    "path": "mobile/www/i18n/fr/status.json",
    "chars": 1725,
    "preview": "{\n    \"status\": {\n        \"share\": {\n            \"title\": \"a partagé\",\n            \"mention\": \"Votre statut a été partag"
  },
  {
    "path": "mobile/www/i18n/fr/user.json",
    "chars": 1077,
    "preview": "{\n    \"user\": {\n        \"profile\": {\n            \"title\": \"Profil\",\n            \"options\": {\n                \"block\": \"B"
  },
  {
    "path": "mobile/www/index.html",
    "chars": 6398,
    "preview": "<!DOCTYPE html>\n<html>\n    <head>\n        <meta charset=\"utf-8\">\n        <meta name=\"viewport\" content=\"initial-scale=1,"
  },
  {
    "path": "mobile/www/test/javascript/components/profile/profile.controller.spec.js",
    "chars": 220,
    "preview": "describe(\"License controller test\", function() {\n\n    beforeEach(inject(function(_$controller_) {\n        $controller = "
  },
  {
    "path": "pom.xml",
    "chars": 51279,
    "preview": "<project xmlns=\"http://maven.apache.org/POM/4.0.0\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\"\n    xsi:schemaL"
  },
  {
    "path": "scripts/insertBuildVersion.sh",
    "chars": 573,
    "preview": "#!/bin/bash\n\ndarwin=false;\n\ncase \"`uname`\" in\n    Darwin*) darwin=true ;;\nesac\n\nif $darwin; then\n    sedi=\"sed -i .sed.d"
  },
  {
    "path": "services/pom.xml",
    "chars": 1837,
    "preview": "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n<project xmlns=\"http://maven.apache.org/POM/4.0.0\"\n         xmlns:xsi=\"http://www"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/ApplicationConfiguration.java",
    "chars": 2303,
    "preview": "package fr.ippon.tatami.config;\n\nimport org.apache.thrift.transport.TTransportException;\nimport org.slf4j.Logger;\nimport"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/AsyncConfiguration.java",
    "chars": 1346,
    "preview": "package fr.ippon.tatami.config;\n\nimport fr.ippon.tatami.service.SearchService;\nimport fr.ippon.tatami.service.elasticsea"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/CacheConfiguration.java",
    "chars": 3195,
    "preview": "package fr.ippon.tatami.config;\n\nimport com.yammer.metrics.ehcache.InstrumentedEhcache;\nimport net.sf.ehcache.Cache;\nimp"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/CassandraConfiguration.java",
    "chars": 9296,
    "preview": "package fr.ippon.tatami.config;\n\nimport me.prettyprint.cassandra.connection.HOpTimer;\nimport me.prettyprint.cassandra.co"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/ColumnFamilyKeys.java",
    "chars": 2854,
    "preview": "package fr.ippon.tatami.config;\n\n/**\n * @author Julien Dubois\n */\npublic class ColumnFamilyKeys {\n\n    private ColumnFam"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/Constants.java",
    "chars": 851,
    "preview": "package fr.ippon.tatami.config;\n\n/**\n * Application constants.\n */\npublic class Constants {\n\n    private Constants() {\n "
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/DispatcherServletConfig.java",
    "chars": 6875,
    "preview": "package fr.ippon.tatami.config;\r\n\r\nimport fr.ippon.tatami.web.syndic.SyndicView;\r\nimport org.apache.commons.lang.CharEnc"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/GroupRoles.java",
    "chars": 234,
    "preview": "package fr.ippon.tatami.config;\n\n/**\n * Constants for groupe roles.\n */\npublic class GroupRoles {\n\n    private GroupRole"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/MailConfiguration.java",
    "chars": 2333,
    "preview": "package fr.ippon.tatami.config;\n\nimport org.apache.commons.lang.CharEncoding;\nimport org.apache.velocity.app.VelocityEng"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/MetricsConfiguration.java",
    "chars": 1832,
    "preview": "package fr.ippon.tatami.config;\n\nimport com.yammer.metrics.HealthChecks;\nimport com.yammer.metrics.reporting.GraphiteRep"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/SearchConfiguration.java",
    "chars": 1577,
    "preview": "package fr.ippon.tatami.config;\n\nimport fr.ippon.tatami.service.elasticsearch.ElasticsearchEngine;\nimport fr.ippon.tatam"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/metrics/CassandraHealthCheck.java",
    "chars": 1281,
    "preview": "package fr.ippon.tatami.config.metrics;\n\nimport com.yammer.metrics.core.HealthCheck;\nimport me.prettyprint.cassandra.ser"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/config/metrics/JavaMailHealthCheck.java",
    "chars": 655,
    "preview": "package fr.ippon.tatami.config.metrics;\n\nimport com.yammer.metrics.core.HealthCheck;\nimport fr.ippon.tatami.service.Mail"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/Attachment.java",
    "chars": 3118,
    "preview": "package fr.ippon.tatami.domain;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport org.joda.time.DateTime;\nimpo"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/Avatar.java",
    "chars": 1499,
    "preview": "package fr.ippon.tatami.domain;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\n\nimport java.io.Serializable;\nimpor"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/DigestType.java",
    "chars": 398,
    "preview": "package fr.ippon.tatami.domain;\n\n/**\n * @author Pierre Rust\n */\npublic enum DigestType {\n\n    WEEKLY_DIGEST(\"WEEKLY\"),\n "
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/Domain.java",
    "chars": 1251,
    "preview": "package fr.ippon.tatami.domain;\n\nimport java.io.Serializable;\n\n/**\n * A domain is a domain name (e.g. \"ippon.fr\"), and r"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/DomainConfiguration.java",
    "chars": 4220,
    "preview": "package fr.ippon.tatami.domain;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.Serializable;\nim"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/Group.java",
    "chars": 3393,
    "preview": "package fr.ippon.tatami.domain;\n\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\n\nimport java.io.Serializable;\n\n/**"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/User.java",
    "chars": 7241,
    "preview": "package fr.ippon.tatami.domain;\n\nimport com.fasterxml.jackson.annotation.JsonIgnore;\nimport fr.ippon.tatami.domain.valid"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/UserStatusStat.java",
    "chars": 1370,
    "preview": "package fr.ippon.tatami.domain;\n\nimport java.io.Serializable;\n\npublic class UserStatusStat implements Comparable<UserSta"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/AbstractStatus.java",
    "chars": 2704,
    "preview": "package fr.ippon.tatami.domain.status;\n\nimport javax.validation.constraints.NotNull;\nimport java.io.Serializable;\nimport"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/Announcement.java",
    "chars": 113,
    "preview": "package fr.ippon.tatami.domain.status;\n\n/**\n * An announcement.\n */\npublic class Announcement extends Share {\n\n}\n"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/MentionFriend.java",
    "chars": 561,
    "preview": "package fr.ippon.tatami.domain.status;\n\n/**\n * Mention a user that someone started following him.\n */\npublic class Menti"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/MentionShare.java",
    "chars": 148,
    "preview": "package fr.ippon.tatami.domain.status;\n\n/**\n * Mention a user that one of his statuses was shared.\n */\npublic class Ment"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/Share.java",
    "chars": 546,
    "preview": "package fr.ippon.tatami.domain.status;\n\n/**\n * A status that is shared.\n */\npublic class Share extends AbstractStatus {\n"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/Status.java",
    "chars": 3469,
    "preview": "package fr.ippon.tatami.domain.status;\n\nimport fr.ippon.tatami.domain.Attachment;\nimport org.hibernate.validator.constra"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/StatusDetails.java",
    "chars": 1389,
    "preview": "package fr.ippon.tatami.domain.status;\n\nimport fr.ippon.tatami.domain.User;\nimport fr.ippon.tatami.service.dto.StatusDTO"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/status/StatusType.java",
    "chars": 146,
    "preview": "package fr.ippon.tatami.domain.status;\n\npublic enum StatusType {\n    STATUS,\n    SHARE,\n    ANNOUNCEMENT,\n    MENTION_FR"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/validation/ContraintsAttachmentCreation.java",
    "chars": 94,
    "preview": "package fr.ippon.tatami.domain.validation;\n\npublic interface ContraintsAttachmentCreation {\n\n}"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/domain/validation/ContraintsUserCreation.java",
    "chars": 190,
    "preview": "package fr.ippon.tatami.domain.validation;\n\n/**\n * Bean Validation group used to validate the creation of a user.\n *\n * "
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/AppleDeviceRepository.java",
    "chars": 287,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\n\npublic interface AppleDeviceRepository {\n\n    void cr"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/AppleDeviceUserRepository.java",
    "chars": 256,
    "preview": "package fr.ippon.tatami.repository;\n\npublic interface AppleDeviceUserRepository {\n\n    void createAppleDeviceForUser(Str"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/AttachmentRepository.java",
    "chars": 643,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.Attachment;\n\npublic interface AttachmentRepository {\n"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/AvatarRepository.java",
    "chars": 240,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.Avatar;\n\npublic interface AvatarRepository {\n\n    voi"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/BlockRepository.java",
    "chars": 541,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.User;\n\nimport java.util.Collection;\n\n/**\n *This repos"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/CounterRepository.java",
    "chars": 744,
    "preview": "package fr.ippon.tatami.repository;\n\n/**\n * The Counter Repository.\n *\n * @author Julien Dubois\n */\npublic interface Cou"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/DaylineRepository.java",
    "chars": 588,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.UserStatusStat;\nimport fr.ippon.tatami.domain.status."
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/DiscussionRepository.java",
    "chars": 373,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\n\n/**\n * The StatusDetails Repository.\n *\n * @author Ju"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/DomainConfigurationRepository.java",
    "chars": 366,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.DomainConfiguration;\n\n/**\n * The DomainConfiguraiton "
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/DomainRepository.java",
    "chars": 550,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.Domain;\n\nimport java.util.List;\nimport java.util.Set;"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/DomainlineRepository.java",
    "chars": 726,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * The Domainline Reposito"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/FavoritelineRepository.java",
    "chars": 564,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.List;\n\n/**\n * The Favoriteline Repository.\n *\n * @author Julien Du"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/FollowerRepository.java",
    "chars": 353,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\n\n/**\n * The Follower Repository.\n *\n * @author Julien "
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/FriendRepository.java",
    "chars": 326,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.List;\n\n/**\n * The Friend Repository.\n *\n * @author Julien Dubois\n "
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/GroupCounterRepository.java",
    "chars": 397,
    "preview": "package fr.ippon.tatami.repository;\n\n/**\n * The Group Counter Repository.\n *\n * @author Julien Dubois\n */\npublic interfa"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/GroupDetailsRepository.java",
    "chars": 432,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.Group;\n\n/**\n * The Group Details Repository.\n *\n * @a"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/GroupMembersRepository.java",
    "chars": 382,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Map;\n\n/**\n * The Group members Repository.\n *\n * @author Julien Du"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/GroupRepository.java",
    "chars": 269,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.Group;\n\n/**\n * The Group Repository.\n *\n * @author Ju"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/GrouplineRepository.java",
    "chars": 723,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * The Groupline Repositor"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/IdempotentRepository.java",
    "chars": 325,
    "preview": "package fr.ippon.tatami.repository;\n\n/**\n * Used to de-deplucate Camel messages.\n */\npublic interface IdempotentReposito"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/MailDigestRepository.java",
    "chars": 862,
    "preview": "package fr.ippon.tatami.repository;\n\nimport fr.ippon.tatami.domain.DigestType;\n\nimport java.util.List;\n\n/**\n * Provide a"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/MentionlineRepository.java",
    "chars": 751,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\nimport java.util.List;\n\n/**\n * The Mentionline Reposit"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/RegistrationRepository.java",
    "chars": 398,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Map;\n\n/**\n * The Registration Repository.\n *\n * @author Julien Dub"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/ResolvedReportRepository.java",
    "chars": 407,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\n\n/**\n * Created by emilyklein on 7/13/16.\n */\npublic i"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/RssUidRepository.java",
    "chars": 388,
    "preview": "package fr.ippon.tatami.repository;\r\n\r\n/**\r\n * The Rss Uid Repository.\r\n * </p>\r\n * The RSS uid is used to build an anon"
  },
  {
    "path": "services/src/main/java/fr/ippon/tatami/repository/SharesRepository.java",
    "chars": 354,
    "preview": "package fr.ippon.tatami.repository;\n\nimport java.util.Collection;\n\n/**\n * The StatusDetails Repository.\n *\n * @author Ju"
  }
]

// ... and 1721 more files (download for full content)

About this extraction

This page contains the full source code of the ippontech/tatami GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 1921 files (12.9 MB), approximately 3.5M tokens. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.

Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.

Copied to clipboard!