Compare commits

...

No commits in common. "weblate-0.1" and "main-chapril-rebranding" have entirely different histories.

766 changed files with 253135 additions and 5065 deletions

270
.eslintrc.json Normal file
View File

@ -0,0 +1,270 @@
{
"parser": "@typescript-eslint/parser",
"parserOptions": {
"ecmaVersion": 2020,
"sourceType": "module",
"allowImportExportEverywhere": true
},
"env": {
"browser": true,
"jasmine": true,
"es6": true
},
"plugins": ["@typescript-eslint"],
"extends": [
"eslint:recommended",
"plugin:@typescript-eslint/eslint-recommended",
"plugin:@typescript-eslint/recommended"
],
"globals": {
"Uint8Array": true,
"Promise": true,
"define": true,
"require": true,
"sinon": true,
"window": true
},
"rules": {
"accessor-pairs": "error",
"array-bracket-spacing": "off",
"array-callback-return": "error",
"arrow-body-style": "off",
"arrow-parens": "off",
"arrow-spacing": "error",
"block-scoped-var": "off",
"block-spacing": "off",
"brace-style": "off",
"callback-return": "off",
"camelcase": "off",
"capitalized-comments": "off",
"class-methods-use-this": "error",
"comma-dangle": "off",
"comma-spacing": "off",
"comma-style": "off",
"complexity": "off",
"computed-property-spacing": [
"error",
"never"
],
"consistent-return": "off",
"consistent-this": "off",
"curly": "off",
"default-case": "off",
"dot-location": [
"error",
"property"
],
"dot-notation": [
"off",
{
"allowKeywords": true
}
],
"eol-last": "error",
"eqeqeq": "off",
"func-call-spacing": "off",
"no-spaced-func": "off",
"no-redeclare": "off",
"func-name-matching": "error",
"func-names": "off",
"func-style": "off",
"generator-star-spacing": "error",
"global-require": "off",
"guard-for-in": "error",
"handle-callback-err": "error",
"id-blacklist": "error",
"id-length": "off",
"id-match": "error",
"indent": "off",
"init-declarations": "off",
"jsx-quotes": "error",
"key-spacing": "off",
"keyword-spacing": "off",
"line-comment-position": "off",
"linebreak-style": [
"error",
"unix"
],
"lines-around-comment": "off",
"lines-around-directive": "off",
"max-depth": "error",
"max-len": "off",
"max-lines": "off",
"max-nested-callbacks": "off",
"max-params": "off",
"max-statements": "off",
"max-statements-per-line": "off",
"multiline-ternary": "off",
"new-parens": "error",
"newline-after-var": "off",
"newline-before-return": "off",
"newline-per-chained-call": "off",
"no-alert": "off",
"no-array-constructor": "error",
"no-await-in-loop": "off",
"no-bitwise": "off",
"no-caller": "error",
"no-console": "off",
"no-catch-shadow": "off",
"no-cond-assign": [
"off",
"except-parens"
],
"no-confusing-arrow": "off",
"no-continue": "off",
"no-div-regex": "error",
"no-duplicate-imports": "error",
"no-else-return": "off",
"no-empty-function": "off",
"no-eq-null": "error",
"no-eval": "error",
"no-extend-native": "off",
"no-extra-bind": "off",
"no-extra-label": "error",
"no-extra-parens": "off",
"no-floating-decimal": "error",
"no-implicit-globals": "off",
"no-implied-eval": "error",
"no-inline-comments": "off",
"no-inner-declarations": [
"error",
"functions"
],
"no-invalid-this": "off",
"no-iterator": "error",
"no-label-var": "error",
"no-labels": "error",
"no-lone-blocks": "error",
"no-lonely-if": "off",
"no-loop-func": "error",
"no-magic-numbers": "off",
"no-mixed-operators": "off",
"no-mixed-requires": "error",
"no-multi-assign": "off",
"no-multi-spaces": "off",
"no-multi-str": "error",
"no-multiple-empty-lines": "error",
"no-native-reassign": "error",
"no-negated-condition": "off",
"no-negated-in-lhs": "error",
"no-nested-ternary": "off",
"no-new": "off",
"no-new-func": "error",
"no-new-object": "error",
"no-new-require": "error",
"no-new-wrappers": "error",
"no-octal-escape": "error",
"no-param-reassign": "off",
"no-path-concat": "error",
"no-plusplus": "off",
"no-process-env": "off",
"no-process-exit": "error",
"no-proto": "error",
"no-prototype-builtins": "error",
"no-restricted-globals": "error",
"no-restricted-imports": "error",
"no-restricted-modules": "error",
"no-restricted-properties": "error",
"no-restricted-syntax": "error",
"no-return-assign": "error",
"no-return-await": "error",
"no-script-url": "error",
"no-self-compare": "error",
"no-sequences": "error",
"no-shadow": "off",
"no-shadow-restricted-names": "error",
"no-sync": "error",
"no-tabs": "error",
"no-template-curly-in-string": "error",
"no-ternary": "off",
"no-throw-literal": "error",
"no-trailing-spaces": "off",
"no-undef-init": "error",
"no-undefined": "off",
"no-underscore-dangle": "off",
"no-unmodified-loop-condition": "error",
"no-unneeded-ternary": "off",
"no-unused-vars": "error",
"no-unused-expressions": "off",
"no-use-before-define": "off",
"no-useless-call": "error",
"no-useless-catch": "off",
"no-useless-computed-key": "error",
"no-useless-concat": "off",
"no-useless-constructor": "error",
"no-useless-escape": "off",
"no-useless-rename": "error",
"no-useless-return": "off",
"no-var": "off",
"no-void": "error",
"no-warning-comments": "off",
"no-whitespace-before-property": "error",
"no-with": "error",
"object-curly-newline": "off",
"object-curly-spacing": "off",
"object-property-newline": [
"off",
{
"allowMultiplePropertiesPerLine": true
}
],
"object-shorthand": "off",
"one-var": "off",
"one-var-declaration-per-line": "off",
"operator-assignment": "off",
"operator-linebreak": "off",
"padded-blocks": "off",
"prefer-arrow-callback": "off",
"prefer-const": "error",
"prefer-destructuring": [
"error",
{
"array": false,
"object": false
}
],
"prefer-numeric-literals": "error",
"prefer-promise-reject-errors": "off",
"prefer-reflect": "off",
"prefer-rest-params": "off",
"prefer-spread": "off",
"prefer-template": "off",
"quote-props": "off",
"quotes": "off",
"radix": [
"error",
"always"
],
"require-atomic-updates": "off",
"require-await": "error",
"require-jsdoc": "off",
"rest-spread-spacing": "error",
"semi": "off",
"semi-spacing": "off",
"sort-imports": "off",
"sort-keys": "off",
"sort-vars": "off",
"space-before-blocks": "off",
"space-before-function-paren": "off",
"space-in-parens": "off",
"space-infix-ops": "off",
"space-unary-ops": "off",
"spaced-comment": "off",
"strict": "off",
"symbol-description": "error",
"template-curly-spacing": "off",
"unicode-bom": [
"error",
"never"
],
"valid-jsdoc": "off",
"vars-on-top": "off",
"wrap-iife": [
"error",
"any"
],
"wrap-regex": "error",
"yield-star-spacing": "error",
"yoda": "off"
}
}

28
.github/CONTRIBUTING.md vendored Normal file
View File

@ -0,0 +1,28 @@
# Contribution Guidelines
Thanks for contributing to [Converse.js](https://conversejs.org)
## Support questions
The Github issue tracker is used for bug reports and feature requests, not for general tech support.
For support, you can join our [XMPP webchat](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org).
Instead of the webchat, you can also open the room in your XMPP client, [click here](xmpp://discuss@conference.conversejs.org?join).
You can also ask questions on [StackOverflow](https://stackoverflow.com/questions/tagged/converse.js)
## Contributing Code
Please follow the usual Github workflow. Create a fork of this repository, make your changes and then submit a pull request.
### Before submitting a pull request
Please read the [style guide](https://conversejs.org/docs/html/style_guide.html) and make sure that your code follows it.
### Add tests for your bugfix or feature
Add a test for any bug fixed or feature added.
Tests can be found in various `./tests` folders in the Converse source code.
To run the tests, you can run `make check` on Linux and Mac, or `./node_modules/bin/karma start karma.conf` on Windows.

4
.github/FUNDING.yml vendored Normal file
View File

@ -0,0 +1,4 @@
# These are supported funding model platforms
patreon: jcbrand
liberapay: jcbrand

32
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@ -0,0 +1,32 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ''
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Expected behavior**
A clear and concise description of what you expected to happen.
**Screenshots**
If applicable, add screenshots to help explain your problem.
**Environment (please complete the following information):**
- Desktop or Mobile?
- Browser [e.g. Chrome, Firefox]
- Converse.js version [e.g. 4.2.0]
**Additional context**
Add any other context about the problem here.

View File

@ -0,0 +1,20 @@
---
name: Feature request
about: Suggest an idea for this project
title: ''
labels: ''
assignees: ''
---
**Is your feature request related to a problem? Please describe.**
A clear and concise description of what the problem is. Ex. I'm always frustrated when [...]
**Describe the solution you'd like**
A clear and concise description of what you want to happen.
**Describe alternatives you've considered**
A clear and concise description of any alternative solutions or features you've considered.
**Additional context**
Add any other context or screenshots about the feature request here.

10
.github/PULL_REQUEST_TEMPLATE.md vendored Normal file
View File

@ -0,0 +1,10 @@
Thanks for making a pull request to converse.js!
Before submitting your request, please make sure the following conditions are met:
- [ ] Add a changelog entry for your change in `CHANGES.md`
- [ ] When adding a configuration variable, please make sure to
document it in `docs/source/configuration.rst`
- [ ] Please add a test for your change. Tests can be run in the commandline
with `make check` or you can run them in the browser by running `make serve`
and then opening `http://localhost:8000/tests.html`.

2
.github/codeql-config.yml vendored Normal file
View File

@ -0,0 +1,2 @@
paths-ignore:
- '**/tests/*.js'

61
.github/dependabot.yml vendored Normal file
View File

@ -0,0 +1,61 @@
version: 2
updates:
- package-ecosystem: npm
directory: "/"
schedule:
interval: daily
open-pull-requests-limit: 10
ignore:
- dependency-name: mini-css-extract-plugin
versions:
- 1.3.5
- 1.3.6
- 1.3.7
- 1.3.8
- 1.3.9
- 1.4.0
- 1.4.1
- 1.5.0
- dependency-name: css-loader
versions:
- 5.0.1
- 5.0.2
- 5.1.0
- 5.1.1
- 5.1.2
- 5.1.3
- 5.2.0
- 5.2.1
- dependency-name: y18n
versions:
- 4.0.2
- dependency-name: sinon
versions:
- 10.0.0
- 9.2.4
- dependency-name: bootstrap
versions:
- 4.6.0
- dependency-name: "@babel/plugin-proposal-nullish-coalescing-operator"
versions:
- 7.12.1
- 7.12.13
- 7.13.0
- 7.13.8
- dependency-name: webpack-cli
versions:
- 4.4.0
- 4.5.0
- dependency-name: webpack-merge
versions:
- 5.7.3
- dependency-name: xmldom
versions:
- 0.5.0
- dependency-name: urijs
versions:
- 1.19.4
- 1.19.6
- dependency-name: sass-loader
versions:
- 10.1.1

43
.github/workflows/codeql.yml vendored Normal file
View File

@ -0,0 +1,43 @@
name: "CodeQL"
on:
push:
branches: [ "master" ]
pull_request:
branches: [ "master" ]
schedule:
- cron: "11 18 * * 6"
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ javascript ]
steps:
- name: Checkout
uses: actions/checkout@v3
- name: Initialize CodeQL
uses: github/codeql-action/init@v2
with:
config-file: ./.github/codeql-config.yml
languages: ${{ matrix.language }}
queries: +security-and-quality
- name: Autobuild
uses: github/codeql-action/autobuild@v2
if: ${{ matrix.language == 'javascript' }}
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v2
with:
category: "/language:${{ matrix.language }}"

34
.github/workflows/karma-tests.yml vendored Normal file
View File

@ -0,0 +1,34 @@
# This workflow will do a clean installation of node dependencies, cache/restore them, build the source code and run tests across different versions of node
# For more information see: https://help.github.com/actions/language-and-framework-guides/using-nodejs-with-github-actions
name: CI Tests
on:
push:
branches: [ master ]
pull_request:
branches: [ master ]
workflow_dispatch:
jobs:
build:
runs-on: ubuntu-latest
env:
DISPLAY: :99.0
strategy:
matrix:
node-version: [18.x]
# See supported Node.js release schedule at https://nodejs.org/en/about/releases/
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v2
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Run Karma tests
uses: GabrielBB/xvfb-action@v1
with:
run: make check ARGS=--single-run

68
.gitignore vendored
View File

@ -1,4 +1,66 @@
*.pyc
*.swp
repos/
# Distribution directory
dist
# conversejs/media repo checkout
media
# Editor fluff
*~
.sw?
*.mo
*.kpf
.*.sw?
.hg/
.bzr/
.svn/
.project
.pydevproject
.idea
.su?
.sass-cache
pip-selfcheck.json
3rdparty/libsignal-protocol-javascript/
*.map
locale.zip
sounds.zip
analytics.js
# virtualenv/python/buildout
.*.cfg
eggs
.Python
build
share
parts
*.pyc
*.egg-info
lib
lib64
include
bin
develop-eggs
pyvenv.cfg
converse-logs/*.html
Backbone.Overview
tags
transpile
# Sphinx
docs/html
docs/doctrees
# Node.js
node_modules
# OSX
.DS_Store
# Builds
.sv?
/vendor/

1
.nvmrc Normal file
View File

@ -0,0 +1 @@
v18.15.0

7
.prettierrc Normal file
View File

@ -0,0 +1,7 @@
{
"printWidth": 120,
"quoteProps": "preserve",
"singleQuote": true,
"spaceBeforeFunctionParen": true,
"tabWidth": 4
}

36541
3rdparty/libsignal-protocol.js vendored Normal file

File diff suppressed because one or more lines are too long

1
3rdparty/libsignal-protocol.min.js vendored Normal file

File diff suppressed because one or more lines are too long

1857
CHANGES.md Normal file

File diff suppressed because it is too large Load Diff

674
COPYING
View File

@ -1,674 +0,0 @@
GNU GENERAL PUBLIC LICENSE
Version 3, 29 June 2007
Copyright (C) 2007 Free Software Foundation, Inc. <http://fsf.org/>
Everyone is permitted to copy and distribute verbatim copies
of this license document, but changing it is not allowed.
Preamble
The GNU General Public License is a free, copyleft license for
software and other kinds of works.
The licenses for most software and other practical works are designed
to take away your freedom to share and change the works. By contrast,
the GNU General Public License is intended to guarantee your freedom to
share and change all versions of a program--to make sure it remains free
software for all its users. We, the Free Software Foundation, use the
GNU General Public License for most of our software; it applies also to
any other work released this way by its authors. You can apply it to
your programs, too.
When we speak of free software, we are referring to freedom, not
price. Our General Public Licenses are designed to make sure that you
have the freedom to distribute copies of free software (and charge for
them if you wish), that you receive source code or can get it if you
want it, that you can change the software or use pieces of it in new
free programs, and that you know you can do these things.
To protect your rights, we need to prevent others from denying you
these rights or asking you to surrender the rights. Therefore, you have
certain responsibilities if you distribute copies of the software, or if
you modify it: responsibilities to respect the freedom of others.
For example, if you distribute copies of such a program, whether
gratis or for a fee, you must pass on to the recipients the same
freedoms that you received. You must make sure that they, too, receive
or can get the source code. And you must show them these terms so they
know their rights.
Developers that use the GNU GPL protect your rights with two steps:
(1) assert copyright on the software, and (2) offer you this License
giving you legal permission to copy, distribute and/or modify it.
For the developers' and authors' protection, the GPL clearly explains
that there is no warranty for this free software. For both users' and
authors' sake, the GPL requires that modified versions be marked as
changed, so that their problems will not be attributed erroneously to
authors of previous versions.
Some devices are designed to deny users access to install or run
modified versions of the software inside them, although the manufacturer
can do so. This is fundamentally incompatible with the aim of
protecting users' freedom to change the software. The systematic
pattern of such abuse occurs in the area of products for individuals to
use, which is precisely where it is most unacceptable. Therefore, we
have designed this version of the GPL to prohibit the practice for those
products. If such problems arise substantially in other domains, we
stand ready to extend this provision to those domains in future versions
of the GPL, as needed to protect the freedom of users.
Finally, every program is threatened constantly by software patents.
States should not allow patents to restrict development and use of
software on general-purpose computers, but in those that do, we wish to
avoid the special danger that patents applied to a free program could
make it effectively proprietary. To prevent this, the GPL assures that
patents cannot be used to render the program non-free.
The precise terms and conditions for copying, distribution and
modification follow.
TERMS AND CONDITIONS
0. Definitions.
"This License" refers to version 3 of the GNU General Public License.
"Copyright" also means copyright-like laws that apply to other kinds of
works, such as semiconductor masks.
"The Program" refers to any copyrightable work licensed under this
License. Each licensee is addressed as "you". "Licensees" and
"recipients" may be individuals or organizations.
To "modify" a work means to copy from or adapt all or part of the work
in a fashion requiring copyright permission, other than the making of an
exact copy. The resulting work is called a "modified version" of the
earlier work or a work "based on" the earlier work.
A "covered work" means either the unmodified Program or a work based
on the Program.
To "propagate" a work means to do anything with it that, without
permission, would make you directly or secondarily liable for
infringement under applicable copyright law, except executing it on a
computer or modifying a private copy. Propagation includes copying,
distribution (with or without modification), making available to the
public, and in some countries other activities as well.
To "convey" a work means any kind of propagation that enables other
parties to make or receive copies. Mere interaction with a user through
a computer network, with no transfer of a copy, is not conveying.
An interactive user interface displays "Appropriate Legal Notices"
to the extent that it includes a convenient and prominently visible
feature that (1) displays an appropriate copyright notice, and (2)
tells the user that there is no warranty for the work (except to the
extent that warranties are provided), that licensees may convey the
work under this License, and how to view a copy of this License. If
the interface presents a list of user commands or options, such as a
menu, a prominent item in the list meets this criterion.
1. Source Code.
The "source code" for a work means the preferred form of the work
for making modifications to it. "Object code" means any non-source
form of a work.
A "Standard Interface" means an interface that either is an official
standard defined by a recognized standards body, or, in the case of
interfaces specified for a particular programming language, one that
is widely used among developers working in that language.
The "System Libraries" of an executable work include anything, other
than the work as a whole, that (a) is included in the normal form of
packaging a Major Component, but which is not part of that Major
Component, and (b) serves only to enable use of the work with that
Major Component, or to implement a Standard Interface for which an
implementation is available to the public in source code form. A
"Major Component", in this context, means a major essential component
(kernel, window system, and so on) of the specific operating system
(if any) on which the executable work runs, or a compiler used to
produce the work, or an object code interpreter used to run it.
The "Corresponding Source" for a work in object code form means all
the source code needed to generate, install, and (for an executable
work) run the object code and to modify the work, including scripts to
control those activities. However, it does not include the work's
System Libraries, or general-purpose tools or generally available free
programs which are used unmodified in performing those activities but
which are not part of the work. For example, Corresponding Source
includes interface definition files associated with source files for
the work, and the source code for shared libraries and dynamically
linked subprograms that the work is specifically designed to require,
such as by intimate data communication or control flow between those
subprograms and other parts of the work.
The Corresponding Source need not include anything that users
can regenerate automatically from other parts of the Corresponding
Source.
The Corresponding Source for a work in source code form is that
same work.
2. Basic Permissions.
All rights granted under this License are granted for the term of
copyright on the Program, and are irrevocable provided the stated
conditions are met. This License explicitly affirms your unlimited
permission to run the unmodified Program. The output from running a
covered work is covered by this License only if the output, given its
content, constitutes a covered work. This License acknowledges your
rights of fair use or other equivalent, as provided by copyright law.
You may make, run and propagate covered works that you do not
convey, without conditions so long as your license otherwise remains
in force. You may convey covered works to others for the sole purpose
of having them make modifications exclusively for you, or provide you
with facilities for running those works, provided that you comply with
the terms of this License in conveying all material for which you do
not control copyright. Those thus making or running the covered works
for you must do so exclusively on your behalf, under your direction
and control, on terms that prohibit them from making any copies of
your copyrighted material outside their relationship with you.
Conveying under any other circumstances is permitted solely under
the conditions stated below. Sublicensing is not allowed; section 10
makes it unnecessary.
3. Protecting Users' Legal Rights From Anti-Circumvention Law.
No covered work shall be deemed part of an effective technological
measure under any applicable law fulfilling obligations under article
11 of the WIPO copyright treaty adopted on 20 December 1996, or
similar laws prohibiting or restricting circumvention of such
measures.
When you convey a covered work, you waive any legal power to forbid
circumvention of technological measures to the extent such circumvention
is effected by exercising rights under this License with respect to
the covered work, and you disclaim any intention to limit operation or
modification of the work as a means of enforcing, against the work's
users, your or third parties' legal rights to forbid circumvention of
technological measures.
4. Conveying Verbatim Copies.
You may convey verbatim copies of the Program's source code as you
receive it, in any medium, provided that you conspicuously and
appropriately publish on each copy an appropriate copyright notice;
keep intact all notices stating that this License and any
non-permissive terms added in accord with section 7 apply to the code;
keep intact all notices of the absence of any warranty; and give all
recipients a copy of this License along with the Program.
You may charge any price or no price for each copy that you convey,
and you may offer support or warranty protection for a fee.
5. Conveying Modified Source Versions.
You may convey a work based on the Program, or the modifications to
produce it from the Program, in the form of source code under the
terms of section 4, provided that you also meet all of these conditions:
a) The work must carry prominent notices stating that you modified
it, and giving a relevant date.
b) The work must carry prominent notices stating that it is
released under this License and any conditions added under section
7. This requirement modifies the requirement in section 4 to
"keep intact all notices".
c) You must license the entire work, as a whole, under this
License to anyone who comes into possession of a copy. This
License will therefore apply, along with any applicable section 7
additional terms, to the whole of the work, and all its parts,
regardless of how they are packaged. This License gives no
permission to license the work in any other way, but it does not
invalidate such permission if you have separately received it.
d) If the work has interactive user interfaces, each must display
Appropriate Legal Notices; however, if the Program has interactive
interfaces that do not display Appropriate Legal Notices, your
work need not make them do so.
A compilation of a covered work with other separate and independent
works, which are not by their nature extensions of the covered work,
and which are not combined with it such as to form a larger program,
in or on a volume of a storage or distribution medium, is called an
"aggregate" if the compilation and its resulting copyright are not
used to limit the access or legal rights of the compilation's users
beyond what the individual works permit. Inclusion of a covered work
in an aggregate does not cause this License to apply to the other
parts of the aggregate.
6. Conveying Non-Source Forms.
You may convey a covered work in object code form under the terms
of sections 4 and 5, provided that you also convey the
machine-readable Corresponding Source under the terms of this License,
in one of these ways:
a) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by the
Corresponding Source fixed on a durable physical medium
customarily used for software interchange.
b) Convey the object code in, or embodied in, a physical product
(including a physical distribution medium), accompanied by a
written offer, valid for at least three years and valid for as
long as you offer spare parts or customer support for that product
model, to give anyone who possesses the object code either (1) a
copy of the Corresponding Source for all the software in the
product that is covered by this License, on a durable physical
medium customarily used for software interchange, for a price no
more than your reasonable cost of physically performing this
conveying of source, or (2) access to copy the
Corresponding Source from a network server at no charge.
c) Convey individual copies of the object code with a copy of the
written offer to provide the Corresponding Source. This
alternative is allowed only occasionally and noncommercially, and
only if you received the object code with such an offer, in accord
with subsection 6b.
d) Convey the object code by offering access from a designated
place (gratis or for a charge), and offer equivalent access to the
Corresponding Source in the same way through the same place at no
further charge. You need not require recipients to copy the
Corresponding Source along with the object code. If the place to
copy the object code is a network server, the Corresponding Source
may be on a different server (operated by you or a third party)
that supports equivalent copying facilities, provided you maintain
clear directions next to the object code saying where to find the
Corresponding Source. Regardless of what server hosts the
Corresponding Source, you remain obligated to ensure that it is
available for as long as needed to satisfy these requirements.
e) Convey the object code using peer-to-peer transmission, provided
you inform other peers where the object code and Corresponding
Source of the work are being offered to the general public at no
charge under subsection 6d.
A separable portion of the object code, whose source code is excluded
from the Corresponding Source as a System Library, need not be
included in conveying the object code work.
A "User Product" is either (1) a "consumer product", which means any
tangible personal property which is normally used for personal, family,
or household purposes, or (2) anything designed or sold for incorporation
into a dwelling. In determining whether a product is a consumer product,
doubtful cases shall be resolved in favor of coverage. For a particular
product received by a particular user, "normally used" refers to a
typical or common use of that class of product, regardless of the status
of the particular user or of the way in which the particular user
actually uses, or expects or is expected to use, the product. A product
is a consumer product regardless of whether the product has substantial
commercial, industrial or non-consumer uses, unless such uses represent
the only significant mode of use of the product.
"Installation Information" for a User Product means any methods,
procedures, authorization keys, or other information required to install
and execute modified versions of a covered work in that User Product from
a modified version of its Corresponding Source. The information must
suffice to ensure that the continued functioning of the modified object
code is in no case prevented or interfered with solely because
modification has been made.
If you convey an object code work under this section in, or with, or
specifically for use in, a User Product, and the conveying occurs as
part of a transaction in which the right of possession and use of the
User Product is transferred to the recipient in perpetuity or for a
fixed term (regardless of how the transaction is characterized), the
Corresponding Source conveyed under this section must be accompanied
by the Installation Information. But this requirement does not apply
if neither you nor any third party retains the ability to install
modified object code on the User Product (for example, the work has
been installed in ROM).
The requirement to provide Installation Information does not include a
requirement to continue to provide support service, warranty, or updates
for a work that has been modified or installed by the recipient, or for
the User Product in which it has been modified or installed. Access to a
network may be denied when the modification itself materially and
adversely affects the operation of the network or violates the rules and
protocols for communication across the network.
Corresponding Source conveyed, and Installation Information provided,
in accord with this section must be in a format that is publicly
documented (and with an implementation available to the public in
source code form), and must require no special password or key for
unpacking, reading or copying.
7. Additional Terms.
"Additional permissions" are terms that supplement the terms of this
License by making exceptions from one or more of its conditions.
Additional permissions that are applicable to the entire Program shall
be treated as though they were included in this License, to the extent
that they are valid under applicable law. If additional permissions
apply only to part of the Program, that part may be used separately
under those permissions, but the entire Program remains governed by
this License without regard to the additional permissions.
When you convey a copy of a covered work, you may at your option
remove any additional permissions from that copy, or from any part of
it. (Additional permissions may be written to require their own
removal in certain cases when you modify the work.) You may place
additional permissions on material, added by you to a covered work,
for which you have or can give appropriate copyright permission.
Notwithstanding any other provision of this License, for material you
add to a covered work, you may (if authorized by the copyright holders of
that material) supplement the terms of this License with terms:
a) Disclaiming warranty or limiting liability differently from the
terms of sections 15 and 16 of this License; or
b) Requiring preservation of specified reasonable legal notices or
author attributions in that material or in the Appropriate Legal
Notices displayed by works containing it; or
c) Prohibiting misrepresentation of the origin of that material, or
requiring that modified versions of such material be marked in
reasonable ways as different from the original version; or
d) Limiting the use for publicity purposes of names of licensors or
authors of the material; or
e) Declining to grant rights under trademark law for use of some
trade names, trademarks, or service marks; or
f) Requiring indemnification of licensors and authors of that
material by anyone who conveys the material (or modified versions of
it) with contractual assumptions of liability to the recipient, for
any liability that these contractual assumptions directly impose on
those licensors and authors.
All other non-permissive additional terms are considered "further
restrictions" within the meaning of section 10. If the Program as you
received it, or any part of it, contains a notice stating that it is
governed by this License along with a term that is a further
restriction, you may remove that term. If a license document contains
a further restriction but permits relicensing or conveying under this
License, you may add to a covered work material governed by the terms
of that license document, provided that the further restriction does
not survive such relicensing or conveying.
If you add terms to a covered work in accord with this section, you
must place, in the relevant source files, a statement of the
additional terms that apply to those files, or a notice indicating
where to find the applicable terms.
Additional terms, permissive or non-permissive, may be stated in the
form of a separately written license, or stated as exceptions;
the above requirements apply either way.
8. Termination.
You may not propagate or modify a covered work except as expressly
provided under this License. Any attempt otherwise to propagate or
modify it is void, and will automatically terminate your rights under
this License (including any patent licenses granted under the third
paragraph of section 11).
However, if you cease all violation of this License, then your
license from a particular copyright holder is reinstated (a)
provisionally, unless and until the copyright holder explicitly and
finally terminates your license, and (b) permanently, if the copyright
holder fails to notify you of the violation by some reasonable means
prior to 60 days after the cessation.
Moreover, your license from a particular copyright holder is
reinstated permanently if the copyright holder notifies you of the
violation by some reasonable means, this is the first time you have
received notice of violation of this License (for any work) from that
copyright holder, and you cure the violation prior to 30 days after
your receipt of the notice.
Termination of your rights under this section does not terminate the
licenses of parties who have received copies or rights from you under
this License. If your rights have been terminated and not permanently
reinstated, you do not qualify to receive new licenses for the same
material under section 10.
9. Acceptance Not Required for Having Copies.
You are not required to accept this License in order to receive or
run a copy of the Program. Ancillary propagation of a covered work
occurring solely as a consequence of using peer-to-peer transmission
to receive a copy likewise does not require acceptance. However,
nothing other than this License grants you permission to propagate or
modify any covered work. These actions infringe copyright if you do
not accept this License. Therefore, by modifying or propagating a
covered work, you indicate your acceptance of this License to do so.
10. Automatic Licensing of Downstream Recipients.
Each time you convey a covered work, the recipient automatically
receives a license from the original licensors, to run, modify and
propagate that work, subject to this License. You are not responsible
for enforcing compliance by third parties with this License.
An "entity transaction" is a transaction transferring control of an
organization, or substantially all assets of one, or subdividing an
organization, or merging organizations. If propagation of a covered
work results from an entity transaction, each party to that
transaction who receives a copy of the work also receives whatever
licenses to the work the party's predecessor in interest had or could
give under the previous paragraph, plus a right to possession of the
Corresponding Source of the work from the predecessor in interest, if
the predecessor has it or can get it with reasonable efforts.
You may not impose any further restrictions on the exercise of the
rights granted or affirmed under this License. For example, you may
not impose a license fee, royalty, or other charge for exercise of
rights granted under this License, and you may not initiate litigation
(including a cross-claim or counterclaim in a lawsuit) alleging that
any patent claim is infringed by making, using, selling, offering for
sale, or importing the Program or any portion of it.
11. Patents.
A "contributor" is a copyright holder who authorizes use under this
License of the Program or a work on which the Program is based. The
work thus licensed is called the contributor's "contributor version".
A contributor's "essential patent claims" are all patent claims
owned or controlled by the contributor, whether already acquired or
hereafter acquired, that would be infringed by some manner, permitted
by this License, of making, using, or selling its contributor version,
but do not include claims that would be infringed only as a
consequence of further modification of the contributor version. For
purposes of this definition, "control" includes the right to grant
patent sublicenses in a manner consistent with the requirements of
this License.
Each contributor grants you a non-exclusive, worldwide, royalty-free
patent license under the contributor's essential patent claims, to
make, use, sell, offer for sale, import and otherwise run, modify and
propagate the contents of its contributor version.
In the following three paragraphs, a "patent license" is any express
agreement or commitment, however denominated, not to enforce a patent
(such as an express permission to practice a patent or covenant not to
sue for patent infringement). To "grant" such a patent license to a
party means to make such an agreement or commitment not to enforce a
patent against the party.
If you convey a covered work, knowingly relying on a patent license,
and the Corresponding Source of the work is not available for anyone
to copy, free of charge and under the terms of this License, through a
publicly available network server or other readily accessible means,
then you must either (1) cause the Corresponding Source to be so
available, or (2) arrange to deprive yourself of the benefit of the
patent license for this particular work, or (3) arrange, in a manner
consistent with the requirements of this License, to extend the patent
license to downstream recipients. "Knowingly relying" means you have
actual knowledge that, but for the patent license, your conveying the
covered work in a country, or your recipient's use of the covered work
in a country, would infringe one or more identifiable patents in that
country that you have reason to believe are valid.
If, pursuant to or in connection with a single transaction or
arrangement, you convey, or propagate by procuring conveyance of, a
covered work, and grant a patent license to some of the parties
receiving the covered work authorizing them to use, propagate, modify
or convey a specific copy of the covered work, then the patent license
you grant is automatically extended to all recipients of the covered
work and works based on it.
A patent license is "discriminatory" if it does not include within
the scope of its coverage, prohibits the exercise of, or is
conditioned on the non-exercise of one or more of the rights that are
specifically granted under this License. You may not convey a covered
work if you are a party to an arrangement with a third party that is
in the business of distributing software, under which you make payment
to the third party based on the extent of your activity of conveying
the work, and under which the third party grants, to any of the
parties who would receive the covered work from you, a discriminatory
patent license (a) in connection with copies of the covered work
conveyed by you (or copies made from those copies), or (b) primarily
for and in connection with specific products or compilations that
contain the covered work, unless you entered into that arrangement,
or that patent license was granted, prior to 28 March 2007.
Nothing in this License shall be construed as excluding or limiting
any implied license or other defenses to infringement that may
otherwise be available to you under applicable patent law.
12. No Surrender of Others' Freedom.
If conditions are imposed on you (whether by court order, agreement or
otherwise) that contradict the conditions of this License, they do not
excuse you from the conditions of this License. If you cannot convey a
covered work so as to satisfy simultaneously your obligations under this
License and any other pertinent obligations, then as a consequence you may
not convey it at all. For example, if you agree to terms that obligate you
to collect a royalty for further conveying from those to whom you convey
the Program, the only way you could satisfy both those terms and this
License would be to refrain entirely from conveying the Program.
13. Use with the GNU Affero General Public License.
Notwithstanding any other provision of this License, you have
permission to link or combine any covered work with a work licensed
under version 3 of the GNU Affero General Public License into a single
combined work, and to convey the resulting work. The terms of this
License will continue to apply to the part which is the covered work,
but the special requirements of the GNU Affero General Public License,
section 13, concerning interaction through a network will apply to the
combination as such.
14. Revised Versions of this License.
The Free Software Foundation may publish revised and/or new versions of
the GNU General Public License from time to time. Such new versions will
be similar in spirit to the present version, but may differ in detail to
address new problems or concerns.
Each version is given a distinguishing version number. If the
Program specifies that a certain numbered version of the GNU General
Public License "or any later version" applies to it, you have the
option of following the terms and conditions either of that numbered
version or of any later version published by the Free Software
Foundation. If the Program does not specify a version number of the
GNU General Public License, you may choose any version ever published
by the Free Software Foundation.
If the Program specifies that a proxy can decide which future
versions of the GNU General Public License can be used, that proxy's
public statement of acceptance of a version permanently authorizes you
to choose that version for the Program.
Later license versions may give you additional or different
permissions. However, no additional obligations are imposed on any
author or copyright holder as a result of your choosing to follow a
later version.
15. Disclaimer of Warranty.
THERE IS NO WARRANTY FOR THE PROGRAM, TO THE EXTENT PERMITTED BY
APPLICABLE LAW. EXCEPT WHEN OTHERWISE STATED IN WRITING THE COPYRIGHT
HOLDERS AND/OR OTHER PARTIES PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY
OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING, BUT NOT LIMITED TO,
THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
PURPOSE. THE ENTIRE RISK AS TO THE QUALITY AND PERFORMANCE OF THE PROGRAM
IS WITH YOU. SHOULD THE PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF
ALL NECESSARY SERVICING, REPAIR OR CORRECTION.
16. Limitation of Liability.
IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING
WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MODIFIES AND/OR CONVEYS
THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, INCLUDING ANY
GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THE
USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED TO LOSS OF
DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY YOU OR THIRD
PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER PROGRAMS),
EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE POSSIBILITY OF
SUCH DAMAGES.
17. Interpretation of Sections 15 and 16.
If the disclaimer of warranty and limitation of liability provided
above cannot be given local legal effect according to their terms,
reviewing courts shall apply local law that most closely approximates
an absolute waiver of all civil liability in connection with the
Program, unless a warranty or assumption of liability accompanies a
copy of the Program in return for a fee.
END OF TERMS AND CONDITIONS
How to Apply These Terms to Your New Programs
If you develop a new program, and you want it to be of the greatest
possible use to the public, the best way to achieve this is to make it
free software which everyone can redistribute and change under these terms.
To do so, attach the following notices to the program. It is safest
to attach them to the start of each source file to most effectively
state the exclusion of warranty; and each file should have at least
the "copyright" line and a pointer to where the full notice is found.
<one line to give the program's name and a brief idea of what it does.>
Copyright (C) <year> <name of author>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short
notice like this when it starts in an interactive mode:
<program> Copyright (C) <year> <name of author>
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it
under certain conditions; type `show c' for details.
The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License. Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".
You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.
The GNU General Public License does not permit incorporating your program
into proprietary programs. If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library. If this is what you want to do, use the GNU Lesser General
Public License instead of this License. But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.

12
COPYRIGHT Normal file
View File

@ -0,0 +1,12 @@
/** Converse.js
*
* An XMPP chat client that runs in the browser.
*
* Version: 10.1.6
*
* Copyright: JC Brand 2013-2018
* Except for 3rd party dependencies.
* Please refer to the unminified version of this file for details.
*
* You can download it at: https://github.com/conversejs/converse.js/releases
*/

View File

@ -1,6 +0,0 @@
weblate 0.1
-----------
Relased on February 6th 2012.
Initial release.

373
LICENSE Normal file
View File

@ -0,0 +1,373 @@
Mozilla Public License Version 2.0
==================================
1. Definitions
--------------
1.1. "Contributor"
means each individual or legal entity that creates, contributes to
the creation of, or owns Covered Software.
1.2. "Contributor Version"
means the combination of the Contributions of others (if any) used
by a Contributor and that particular Contributor's Contribution.
1.3. "Contribution"
means Covered Software of a particular Contributor.
1.4. "Covered Software"
means Source Code Form to which the initial Contributor has attached
the notice in Exhibit A, the Executable Form of such Source Code
Form, and Modifications of such Source Code Form, in each case
including portions thereof.
1.5. "Incompatible With Secondary Licenses"
means
(a) that the initial Contributor has attached the notice described
in Exhibit B to the Covered Software; or
(b) that the Covered Software was made available under the terms of
version 1.1 or earlier of the License, but not also under the
terms of a Secondary License.
1.6. "Executable Form"
means any form of the work other than Source Code Form.
1.7. "Larger Work"
means a work that combines Covered Software with other material, in
a separate file or files, that is not Covered Software.
1.8. "License"
means this document.
1.9. "Licensable"
means having the right to grant, to the maximum extent possible,
whether at the time of the initial grant or subsequently, any and
all of the rights conveyed by this License.
1.10. "Modifications"
means any of the following:
(a) any file in Source Code Form that results from an addition to,
deletion from, or modification of the contents of Covered
Software; or
(b) any new file in Source Code Form that contains any Covered
Software.
1.11. "Patent Claims" of a Contributor
means any patent claim(s), including without limitation, method,
process, and apparatus claims, in any patent Licensable by such
Contributor that would be infringed, but for the grant of the
License, by the making, using, selling, offering for sale, having
made, import, or transfer of either its Contributions or its
Contributor Version.
1.12. "Secondary License"
means either the GNU General Public License, Version 2.0, the GNU
Lesser General Public License, Version 2.1, the GNU Affero General
Public License, Version 3.0, or any later versions of those
licenses.
1.13. "Source Code Form"
means the form of the work preferred for making modifications.
1.14. "You" (or "Your")
means an individual or a legal entity exercising rights under this
License. For legal entities, "You" includes any entity that
controls, is controlled by, or is under common control with You. For
purposes of this definition, "control" means (a) the power, direct
or indirect, to cause the direction or management of such entity,
whether by contract or otherwise, or (b) ownership of more than
fifty percent (50%) of the outstanding shares or beneficial
ownership of such entity.
2. License Grants and Conditions
--------------------------------
2.1. Grants
Each Contributor hereby grants You a world-wide, royalty-free,
non-exclusive license:
(a) under intellectual property rights (other than patent or trademark)
Licensable by such Contributor to use, reproduce, make available,
modify, display, perform, distribute, and otherwise exploit its
Contributions, either on an unmodified basis, with Modifications, or
as part of a Larger Work; and
(b) under Patent Claims of such Contributor to make, use, sell, offer
for sale, have made, import, and otherwise transfer either its
Contributions or its Contributor Version.
2.2. Effective Date
The licenses granted in Section 2.1 with respect to any Contribution
become effective for each Contribution on the date the Contributor first
distributes such Contribution.
2.3. Limitations on Grant Scope
The licenses granted in this Section 2 are the only rights granted under
this License. No additional rights or licenses will be implied from the
distribution or licensing of Covered Software under this License.
Notwithstanding Section 2.1(b) above, no patent license is granted by a
Contributor:
(a) for any code that a Contributor has removed from Covered Software;
or
(b) for infringements caused by: (i) Your and any other third party's
modifications of Covered Software, or (ii) the combination of its
Contributions with other software (except as part of its Contributor
Version); or
(c) under Patent Claims infringed by Covered Software in the absence of
its Contributions.
This License does not grant any rights in the trademarks, service marks,
or logos of any Contributor (except as may be necessary to comply with
the notice requirements in Section 3.4).
2.4. Subsequent Licenses
No Contributor makes additional grants as a result of Your choice to
distribute the Covered Software under a subsequent version of this
License (see Section 10.2) or under the terms of a Secondary License (if
permitted under the terms of Section 3.3).
2.5. Representation
Each Contributor represents that the Contributor believes its
Contributions are its original creation(s) or it has sufficient rights
to grant the rights to its Contributions conveyed by this License.
2.6. Fair Use
This License is not intended to limit any rights You have under
applicable copyright doctrines of fair use, fair dealing, or other
equivalents.
2.7. Conditions
Sections 3.1, 3.2, 3.3, and 3.4 are conditions of the licenses granted
in Section 2.1.
3. Responsibilities
-------------------
3.1. Distribution of Source Form
All distribution of Covered Software in Source Code Form, including any
Modifications that You create or to which You contribute, must be under
the terms of this License. You must inform recipients that the Source
Code Form of the Covered Software is governed by the terms of this
License, and how they can obtain a copy of this License. You may not
attempt to alter or restrict the recipients' rights in the Source Code
Form.
3.2. Distribution of Executable Form
If You distribute Covered Software in Executable Form then:
(a) such Covered Software must also be made available in Source Code
Form, as described in Section 3.1, and You must inform recipients of
the Executable Form how they can obtain a copy of such Source Code
Form by reasonable means in a timely manner, at a charge no more
than the cost of distribution to the recipient; and
(b) You may distribute such Executable Form under the terms of this
License, or sublicense it under different terms, provided that the
license for the Executable Form does not attempt to limit or alter
the recipients' rights in the Source Code Form under this License.
3.3. Distribution of a Larger Work
You may create and distribute a Larger Work under terms of Your choice,
provided that You also comply with the requirements of this License for
the Covered Software. If the Larger Work is a combination of Covered
Software with a work governed by one or more Secondary Licenses, and the
Covered Software is not Incompatible With Secondary Licenses, this
License permits You to additionally distribute such Covered Software
under the terms of such Secondary License(s), so that the recipient of
the Larger Work may, at their option, further distribute the Covered
Software under the terms of either this License or such Secondary
License(s).
3.4. Notices
You may not remove or alter the substance of any license notices
(including copyright notices, patent notices, disclaimers of warranty,
or limitations of liability) contained within the Source Code Form of
the Covered Software, except that You may alter any license notices to
the extent required to remedy known factual inaccuracies.
3.5. Application of Additional Terms
You may choose to offer, and to charge a fee for, warranty, support,
indemnity or liability obligations to one or more recipients of Covered
Software. However, You may do so only on Your own behalf, and not on
behalf of any Contributor. You must make it absolutely clear that any
such warranty, support, indemnity, or liability obligation is offered by
You alone, and You hereby agree to indemnify every Contributor for any
liability incurred by such Contributor as a result of warranty, support,
indemnity or liability terms You offer. You may include additional
disclaimers of warranty and limitations of liability specific to any
jurisdiction.
4. Inability to Comply Due to Statute or Regulation
---------------------------------------------------
If it is impossible for You to comply with any of the terms of this
License with respect to some or all of the Covered Software due to
statute, judicial order, or regulation then You must: (a) comply with
the terms of this License to the maximum extent possible; and (b)
describe the limitations and the code they affect. Such description must
be placed in a text file included with all distributions of the Covered
Software under this License. Except to the extent prohibited by statute
or regulation, such description must be sufficiently detailed for a
recipient of ordinary skill to be able to understand it.
5. Termination
--------------
5.1. The rights granted under this License will terminate automatically
if You fail to comply with any of its terms. However, if You become
compliant, then the rights granted under this License from a particular
Contributor are reinstated (a) provisionally, unless and until such
Contributor explicitly and finally terminates Your grants, and (b) on an
ongoing basis, if such Contributor fails to notify You of the
non-compliance by some reasonable means prior to 60 days after You have
come back into compliance. Moreover, Your grants from a particular
Contributor are reinstated on an ongoing basis if such Contributor
notifies You of the non-compliance by some reasonable means, this is the
first time You have received notice of non-compliance with this License
from such Contributor, and You become compliant prior to 30 days after
Your receipt of the notice.
5.2. If You initiate litigation against any entity by asserting a patent
infringement claim (excluding declaratory judgment actions,
counter-claims, and cross-claims) alleging that a Contributor Version
directly or indirectly infringes any patent, then the rights granted to
You by any and all Contributors for the Covered Software under Section
2.1 of this License shall terminate.
5.3. In the event of termination under Sections 5.1 or 5.2 above, all
end user license agreements (excluding distributors and resellers) which
have been validly granted by You or Your distributors under this License
prior to termination shall survive termination.
************************************************************************
* *
* 6. Disclaimer of Warranty *
* ------------------------- *
* *
* Covered Software is provided under this License on an "as is" *
* basis, without warranty of any kind, either expressed, implied, or *
* statutory, including, without limitation, warranties that the *
* Covered Software is free of defects, merchantable, fit for a *
* particular purpose or non-infringing. The entire risk as to the *
* quality and performance of the Covered Software is with You. *
* Should any Covered Software prove defective in any respect, You *
* (not any Contributor) assume the cost of any necessary servicing, *
* repair, or correction. This disclaimer of warranty constitutes an *
* essential part of this License. No use of any Covered Software is *
* authorized under this License except under this disclaimer. *
* *
************************************************************************
************************************************************************
* *
* 7. Limitation of Liability *
* -------------------------- *
* *
* Under no circumstances and under no legal theory, whether tort *
* (including negligence), contract, or otherwise, shall any *
* Contributor, or anyone who distributes Covered Software as *
* permitted above, be liable to You for any direct, indirect, *
* special, incidental, or consequential damages of any character *
* including, without limitation, damages for lost profits, loss of *
* goodwill, work stoppage, computer failure or malfunction, or any *
* and all other commercial damages or losses, even if such party *
* shall have been informed of the possibility of such damages. This *
* limitation of liability shall not apply to liability for death or *
* personal injury resulting from such party's negligence to the *
* extent applicable law prohibits such limitation. Some *
* jurisdictions do not allow the exclusion or limitation of *
* incidental or consequential damages, so this exclusion and *
* limitation may not apply to You. *
* *
************************************************************************
8. Litigation
-------------
Any litigation relating to this License may be brought only in the
courts of a jurisdiction where the defendant maintains its principal
place of business and such litigation shall be governed by laws of that
jurisdiction, without reference to its conflict-of-law provisions.
Nothing in this Section shall prevent a party's ability to bring
cross-claims or counter-claims.
9. Miscellaneous
----------------
This License represents the complete agreement concerning the subject
matter hereof. If any provision of this License is held to be
unenforceable, such provision shall be reformed only to the extent
necessary to make it enforceable. Any law or regulation which provides
that the language of a contract shall be construed against the drafter
shall not be used to construe this License against a Contributor.
10. Versions of the License
---------------------------
10.1. New Versions
Mozilla Foundation is the license steward. Except as provided in Section
10.3, no one other than the license steward has the right to modify or
publish new versions of this License. Each version will be given a
distinguishing version number.
10.2. Effect of New Versions
You may distribute the Covered Software under the terms of the version
of the License under which You originally received the Covered Software,
or under the terms of any subsequent version published by the license
steward.
10.3. Modified Versions
If you create software not governed by this License, and you want to
create a new license for such software, you may create and use a
modified version of this License if you rename the license and remove
any references to the name of the license steward (except to note that
such modified license differs from this License).
10.4. Distributing Source Code Form that is Incompatible With Secondary
Licenses
If You choose to distribute Source Code Form that is Incompatible With
Secondary Licenses under the terms of this version of the License, the
notice described in Exhibit B of this License must be attached.
Exhibit A - Source Code Form License Notice
-------------------------------------------
This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/.
If it is not possible or desirable to put the notice in a particular
file, then You may include the notice in a location (such as a LICENSE
file in a relevant directory) where a recipient would be likely to look
for such a notice.
You may add additional accurate notices of copyright ownership.
Exhibit B - "Incompatible With Secondary Licenses" Notice
---------------------------------------------------------
This Source Code Form is "Incompatible With Secondary Licenses", as
defined by the Mozilla Public License, v. 2.0.

269
Makefile Normal file
View File

@ -0,0 +1,269 @@
# You can set these variables from the command line.
BOOTSTRAP = ./node_modules/
BUILDDIR = ./docs
KARMA ?= ./node_modules/.bin/karma
CLEANCSS ?= ./node_modules/clean-css-cli/bin/cleancss
HTTPSERVE ?= ./node_modules/.bin/http-server
HTTPSERVE_PORT ?= 8000
INKSCAPE ?= inkscape
INSTALL ?= install
JSDOC ?= ./node_modules/.bin/jsdoc
OXIPNG ?= oxipng
PAPER =
RJS ?= ./node_modules/.bin/r.js
NPX ?= ./node_modules/.bin/npx
SASS ?= ./node_modules/.bin/sass
SED ?= sed
SPHINXBUILD ?= ./bin/sphinx-build
SPHINXOPTS =
XGETTEXT = xgettext
# Internal variables.
ALLSPHINXOPTS = -d $(BUILDDIR)/doctrees $(PAPEROPT_$(PAPER)) $(SPHINXOPTS) ./docs/source
VERSION_FORMAT = [0-9]+\.[0-9]+\.[0-9]+
.PHONY: all
all: node_modules dist
.PHONY: help
help:
@echo "Please use \`make <target>' where <target> is one of the following:"
@echo ""
@echo " all Set up dev environment and create all builds"
@echo " dist Create minified builds of converse.js and all its dependencies."
@echo " clean Remove all NPM packages."
@echo " check Run all tests."
@echo " dev Set up the development environment and build unminified resources. To force a fresh start, run 'make clean' first."
@echo " devserver Set up the development environment and start the webpack dev server."
@echo " doc Make standalone HTML files of the documentation."
@echo " po Generate gettext PO files for each i18n language."
@echo " pot Generate a gettext POT file to be used for translations."
@echo " release Prepare a new release of converse.js. E.g. make release VERSION=0.9.5"
@echo " serve Serve this directory via a webserver on port 8000."
@echo " serve_bg Same as \"serve\", but do it in the background"
@echo " node_modules Install NPM dependencies"
@echo " watch Watch for changes on JS and scss files and automatically update the generated files."
@echo " logo Generate PNG logos of multiple sizes."
########################################################################
## Miscellaneous
.PHONY: serve
serve: node_modules dist
$(HTTPSERVE) -p $(HTTPSERVE_PORT) -c-1
.PHONY: serve_bg
serve_bg: node_modules
$(HTTPSERVE) -p $(HTTPSERVE_PORT) -c-1 -s &
certs:
mkdir certs
cd certs && openssl req -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out chat.example.org.crt -keyout chat.example.org.key
########################################################################
## Translation machinery
GETTEXT = $(XGETTEXT) --from-code=UTF-8 --language=JavaScript --keyword=__ --keyword=___ --keyword=i18n_ --force-po --output=src/i18n/converse.pot --package-name=Converse.js --copyright-holder="Jan-Carel Brand" --package-version=10.1.6 dist/converse-no-dependencies.js -c
src/i18n/converse.pot: dist/converse-no-dependencies.js
$(GETTEXT) 2>&1 > /dev/null; exit $$?;
rm dist/converse-no-dependencies.js
rm dist/tmp.css
.PHONY: pot
pot: src/i18n/converse.pot
.PHONY: po
po:
find ./src/i18n -maxdepth 1 -mindepth 1 -type d -exec msgmerge {}/LC_MESSAGES/converse.po ./src/i18n/converse.pot -U \;
########################################################################
## Release management
.PHONY: version
version:
$(SED) -i '/^export const VERSION_NAME =/s/=.*/= "v$(VERSION)";/' src/headless/shared/constants.js
$(SED) -i '/Version:/s/:.*/: $(VERSION)/' COPYRIGHT
$(SED) -i '/Project-Id-Version:/s/:.*/: Converse.js $(VERSION)\n"/' src/i18n/converse.pot
$(SED) -i '/"version":/s/:.*/: "$(VERSION)",/' manifest.json
$(SED) -i '/"version":/s/:.*/: "$(VERSION)",/' package.json
$(SED) -i '/"version":/s/:.*/: "$(VERSION)",/' src/headless/package.json
$(SED) -ri 's/--package-version=$(VERSION_FORMAT)/--package-version=$(VERSION)/' Makefile
$(SED) -i -e "/version =/s/=.*/= '$(VERSION)'/" -e "/release =/s/=.*/= '$(VERSION)'/" docs/source/conf.py
$(SED) -i "s/[Uu]nreleased/`date +%Y-%m-%d`/" CHANGES.md
$(SED) -ri 's,cdn.conversejs.org/$(VERSION_FORMAT),cdn.conversejs.org/$(VERSION),' docs/source/quickstart.rst
$(SED) -ri 's,cdn.conversejs.org/$(VERSION_FORMAT),cdn.conversejs.org/$(VERSION),' *.html
$(SED) -ri 's,cdn.conversejs.org/$(VERSION_FORMAT),cdn.conversejs.org/$(VERSION),' demo/*.html
make pot
make po
make dist
release-checkout:
git clone git@github.com:conversejs/converse.js.git --depth 1 --branch $(BRANCH) release-$(BRANCH)
cd release-$(BRANCH) && make dist
.PHONY: publish
publish:
make release-checkout
cd release-$(BRANCH) && npm pack && npm publish
cd release-$(BRANCH)/src/headless && npm pack && npm publish
find ./release-$(BRANCH)/ -name "converse.js-*.tgz" -exec mv {} . \;
find ./release-$(BRANCH)/src/headless -name "converse-headless-*.tgz" -exec mv {} . \;
rm -rf release-$(BRANCH)
.PHONY: postrelease
postrelease:
$(SED) -i '/^export const VERSION_NAME =/s/=.*/= "v$(VERSION)dev";/' src/headless/shared/constants.js
.PHONY: deploy
deploy:
git clone --branch v$(VERSION) git@github.com:conversejs/converse.js.git --depth 1 $(VERSION)
cd $(VERSION) && make node && ASSET_PATH=https://cdn.conversejs.org/$(VERSION)/dist/ make dist && make doc
cd .. && git pull && make node && ASSET_PATH=https://cdn.conversejs.org/dist/ make dist && make doc
########################################################################
## Install dependencies
${NVM_DIR}/nvm.sh:
wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
source ~/.bashrc
.PHONY: nvm
nvm: ${NVM_DIR}/nvm.sh
.PHONY: node
node: .nvmrc
. $(HOME)/.nvm/nvm.sh && nvm install
node_modules: package.json src/headless/package.json
npm install
.PHONY: clean
clean:
npm run clean
rm -rf lib bin include parts
.PHONY: dev
dev: node_modules
npm run dev
.PHONY: devserver
devserver: node_modules
npm run serve
########################################################################
## Builds
dist/converse-no-dependencies.js: src webpack/webpack.common.js webpack/webpack.nodeps.js @converse/headless node_modules
npm run nodeps
dist/converse.js:: node_modules
npm run build
dist/converse.css:: node_modules
npm run build
dist/website.css:: node_modules src/shared/styles/website.scss
$(SASS) --load-path=$(BOOTSTRAP) src/shared/styles/website.scss $@
dist/website.min.css:: node_modules dist/website.css
$(CLEANCSS) dist/website.css > $@
.PHONY: watch
watch: node_modules
npm run watch
.PHONY: logo
logo: logo/conversejs-transparent16.png \
logo/conversejs-transparent19.png \
logo/conversejs-transparent48.png \
logo/conversejs-transparent128.png \
logo/conversejs-transparent512.png \
logo/conversejs-filled16.png \
logo/conversejs-filled19.png \
logo/conversejs-filled48.png \
logo/conversejs-filled128.png \
logo/conversejs-filled512.png \
logo/conversejs-transparent%.png:: logo/conversejs-transparent.svg
$(INKSCAPE) -e $@ -w $* $<
$(OXIPNG) $@
logo/conversejs-filled%.png:: logo/conversejs-filled.svg
$(INKSCAPE) -e $@ -w $* $<
$(OXIPNG) $@
@converse/headless: src/headless
src/headless/dist/converse-headless.js: src webpack/webpack.common.js node_modules @converse/headless
npm run headless-dev
src/headless/dist/converse-headless.min.js: src webpack/webpack.common.js node_modules @converse/headless
npm run headless
dist:: node_modules src/* | dist/website.css dist/website.min.css
npm run headless
# Ideally this should just be `npm run build`.
# The additional steps are necessary to properly generate JSON chunk files
# from the .po files. The nodeps config uses preset-env with IE11.
# Somehow this is necessary.
npm run nodeps
$(eval TMPD := $(shell mktemp -d))
mv dist/locales $(TMPD) && \
npm run build && \
mv $(TMPD)/locales/*-po.js dist/locales/ && \
rm -rf $(TMPD)
.PHONY: install
install:: dist
.PHONY: cdn
cdn:: node_modules
npm run cdn
.PHONY: types
types:: node_modules
npm run types
########################################################################
## Tests
.PHONY: eslint
eslint: node_modules
npm run lint
.PHONY: check
check: eslint | dist/converse.js dist/converse.css
npm run test -- $(ARGS)
.PHONY: test
test:
npm run test -- $(ARGS)
########################################################################
## Documentation
./bin/activate:
python3 -m venv .
.PHONY: docsdev
docsdev: ./bin/activate requirements.txt
./bin/pip install --upgrade pip==21.3.1
./bin/pip install -r requirements.txt
.PHONY: html
html: doc
.PHONY: doc
doc: node_modules docsdev apidoc
rm -rf $(BUILDDIR)/html
$(SPHINXBUILD) -b html $(ALLSPHINXOPTS) $(BUILDDIR)/html
make apidoc
@echo
@echo "Build finished. The HTML pages are in $(BUILDDIR)/html."
PHONY: apidoc
apidoc:
find ./src -type d -name node_modules -prune -false -o -name "*.js" | xargs $(JSDOC) --private --readme docs/source/jsdoc_intro.md -c docs/source/conf.json -d docs/html/api

17
README.chapril.md Normal file
View File

@ -0,0 +1,17 @@
# Construire une version Chapril de ConverseJS
```
cd .../conversejs
# La première fois, installer nvm (attention, ça va modifier le .bashrc, entre autres choses)
make nvm
export V=7.0.4
git rebase v${V?}
# [... Résoudre les conflits]
git checkout -b v${V?}-chapril
nvm install
make dist
# [... Tester les livrables présents dans dist/, et si tout est ok :]
make version VERSION=${V?}-chapril
rsync -av dist/ chapril-xmpp:/var/www/xmpp.chapril.org/public_html/dist-custom-chapril-${V?}/
```

188
README.md Normal file
View File

@ -0,0 +1,188 @@
<h2 align="center">
<a href="https://conversejs.org" target="_blank" rel="noopener">
<img alt="Converse.js" src="https://github.com/conversejs/converse.js/blob/master/logo/readme.png" width="480">
</a>
</h2>
[![XMPP Chat](https://conference.conversejs.org/muc_badge/discuss@conference.conversejs.org)](https://inverse.chat/#converse/room?jid=discuss@conference.conversejs.org)
[![CI Tests](https://github.com/conversejs/converse.js/actions/workflows/karma-tests.yml/badge.svg)](https://github.com/conversejs/converse.js/actions/workflows/karma-tests.yml)
[![Bountysource bounties](https://img.shields.io/bountysource/team/converse.js/activity.svg?maxAge=2592000)](https://www.bountysource.com/teams/converse.js/issues?tracker_ids=194169)
[![Translation status](https://hosted.weblate.org/widgets/conversejs/-/svg-badge.svg)](https://hosted.weblate.org/engage/conversejs/?utm_source=widget)
[Converse](https://conversejs.org) is a web based [XMPP/Jabber](https://xmpp.org) chat client.
You can either use it as a webchat app, or you can integrate it into your own website.
It's 100% client-side JavaScript, HTML and CSS and the only backend required
is a modern XMPP server.
Please support this project via [Patreon](https://www.patreon.com/jcbrand) or [Liberapay](https://liberapay.com/jcbrand)
## Demo
Converse is hosted and can be used at [https://conversejs.org](https://conversejs.org).
A demo showing anonymous login is available at [https://conversejs.org/demo/anonymous.html](https://conversejs.org/demo/anonymous.html)
and a demo which shows how you can embed a single chat room into a page is
avialable at [https://conversejs.org/demo/embedded.html](https://conversejs.org/demo/embedded.html).
## Documentation
The developer/integrator documentation can be found at [https://conversejs.org/docs/html](https://conversejs.org/docs/html).
You'll probably want to begin with the [quickstart guide](https://conversejs.org/docs/html/quickstart.html),
which shows you how to use the CDN (content delivery network) to quickly get a demo up and running.
## Converse modes
### Overlay
In overlay mode, Converse appears overlayed chats on top of the website.
![Screenshot of Converse in overlay mode](https://conversejs.org/screenshots/Converse-overlayed.png)
### Fullpage
In fullpage mode, Converse behaves like a single-page app that covers the whole browser viewport.
![Screenshot of Converse 9.0.0 in fullpage mode](https://conversejs.org/screenshots/Converse-fullscreen.png)
### Dark mode
![Screenshot of Converse 9.1.0 with a dark theme](https://conversejs.org/screenshots/Converse-Dracula-Theme.png)
### Embedded
In embedded mode, Converse can be embedded into an element in the DOM.
![Screenshot of Converse in embedded mode](https://conversejs.org/screenshots/Converse-embedded.png)
## Features
- Available as overlayed chat boxes or as a fullscreen application. See [inverse.chat](https://inverse.chat) for the fullscreen version.
- Custom status messages
- Desktop notifications
- A [plugin architecture](https://conversejs.org/docs/html/plugin_development.html) based on [pluggable.js](https://conversejs.github.io/pluggable.js/)
- Chat statuses (online, busy, away, offline)
- Anonymous logins, see the [anonymous login demo](https://conversejs.org/demo/anonymous.html)
- URL Previews (requires server support, for example [mod_ogp](https://modules.prosody.im/mod_ogp.html)
- Translated into over 30 languages
### Supported XMPP Extensions
- [RFC-7395](https://tools.ietf.org/html/rfc7395) XMPP Subprotocol support for WebSocket
- [XEP-0004](https://xmpp.org/extensions/xep-0004.html) Data Forms
- [XEP-0030](https://xmpp.org/extensions/xep-0030.html) Service discovery
- [XEP-0045](https://xmpp.org/extensions/xep-0045.html) Multi-user chat rooms
- [XEP-0048](https://xmpp.org/extensions/xep-0048.html) Bookmarks
- [XEP-0050](https://xmpp.org/extensions/xep-0050.html) Ad-Hoc Commands
- [XEP-0054](https://xmpp.org/extensions/xep-0054.html) VCard-temp
- [XEP-0059](https://xmpp.org/extensions/xep-0059.html) Result Set Management
- [XEP-0060](https://xmpp.org/extensions/xep-0060.html) Publish-Subscribe (limited support)
- [XEP-0066](https://xmpp.org/extensions/xep-0066.html) Out of Band Data
- [XEP-0077](https://xmpp.org/extensions/xep-0077.html) In-band registration
- [XEP-0085](https://xmpp.org/extensions/xep-0085.html) Chat State Notifications
- [XEP-0115](https://xmpp.org/extensions/xep-0115.html) Entity Capabilities
- [XEP-0124](https://xmpp.org/extensions/xep-0124.html) Bidirectional-streams Over Synchronous HTTP (BOSH)
- [XEP-0144](https://xmpp.org/extensions/xep-0144.html) Roster item exchange
- [XEP-0156](https://xmpp.org/extensions/xep-0156.html) Discovering Alternative XMPP Connection Methods
- [XEP-0163](https://xmpp.org/extensions/xep-0163.html) Personal Eventing Protocol (limited support)
- [XEP-0184](https://xmpp.org/extensions/xep-0184.html) Message Receipt
- [XEP-0198](https://xmpp.org/extensions/xep-0198.html) Stream Management
- [XEP-0199](https://xmpp.org/extensions/xep-0199.html) XMPP Ping
- [XEP-0203](https://xmpp.org/extensions/xep-0203.html) Delayed Delivery
- [XEP-0206](https://xmpp.org/extensions/xep-0206.html) XMPP Over BOSH
- [XEP-0245](https://xmpp.org/extensions/xep-0245.html) The /me Command
- [XEP-0249](https://xmpp.org/extensions/xep-0249.html) Direct MUC Invitations
- [XEP-0280](https://xmpp.org/extensions/xep-0280.html) Message Carbons
- [XEP-0297](https://xmpp.org/extensions/xep-0297.html) Stanza Forwarding (limited support)
- [XEP-0308](https://xmpp.org/extensions/xep-0308.html) Last Message Correction
- [XEP-0313](https://xmpp.org/extensions/xep-0313.html) Message Archive Management
- [XEP-0316](https://xmpp.org/extensions/xep-0316.html) MUC Eventing protocol (limited support)
- [XEP-0317](https://xmpp.org/extensions/xep-0317.html) Hats (limited support)
- [XEP-0333](https://xmpp.org/extensions/xep-0333.html) Chat Markers (limited support)
- [XEP-0352](https://xmpp.org/extensions/xep-0352.html) Client State Indication
- [XEP-0357](https://xmpp.org/extensions/xep-0357.html) Push Notifications
- [XEP-0359](https://xmpp.org/extensions/xep-0359.html) Unique and Stable Stanza IDs
- [XEP-0363](https://xmpp.org/extensions/xep-0363.html) HTTP File Upload
- [XEP-0372](https://xmpp.org/extensions/xep-0372.html) References
- [XEP-0382](https://xmpp.org/extensions/xep-0382.html) Spoiler messages
- [XEP-0384](https://xmpp.org/extensions/xep-0384.html) OMEMO Encryption
- [XEP-0393](https://xmpp.org/extensions/xep-0393.html) Message styling
- [XEP-0422](https://xmpp.org/extensions/xep-0422.html) Message Fastening (limited support)
- [XEP-0424](https://xmpp.org/extensions/xep-0424.html) Message Retractions
- [XEP-0425](https://xmpp.org/extensions/xep-0425.html) Message Moderation
- [XEP-0437](https://xmpp.org/extensions/xep-0437.html) Room Activity Indicators
- [XEP-0453](https://xmpp.org/extensions/xep-0453.html) DOAP Usage in XMPP
- [XEP-0454](https://xmpp.org/extensions/xep-0454.html) OMEMO Media sharing
## Integration into other servers and frameworks
### XMPP servers
- **[Openfire](https://www.igniterealtime.org/projects/openfire/index.jsp)**: [inverse.jar](https://www.igniterealtime.org/projects/openfire/plugins.jsp)
- **[Prosody](https://prosody.im/)**: [mod_conversejs](https://modules.prosody.im/mod_conversejs.html)
- **[Ejabberd](https://ejabberd.im/)**: [mod-conversejs](https://docs.ejabberd.im/admin/configuration/modules/#mod-conversejs)
### Other
- **[Alfresco](https://www.alfresco.com)**: [alfresco-js-chat-share](https://github.com/keensoft/alfresco-js-chat-share)
- **[Django](https://www.djangoproject.com)**: [django-conversejs](https://pypi.python.org/pypi/django-conversejs) or [django-xmpp](https://github.com/fpytloun/django-xmpp)
- **[Elgg](https://elgg.org)**: [plugin](https://elgg.org/plugins/2997196)
- **[Friendica](https://friendi.ca)**: [converse](https://github.com/friendica/friendica-addons/tree/master/xmpp/converse)
- **[Patternslib](http://patternslib.com)**: [patterns.converse](https://github.com/jcbrand/patterns.converse)
- **[Plone](https://plone.com)**: [collective.converse](https://github.com/collective/collective.converse)
- **[Pàdé](https://www.igniterealtime.org/projects/pade/index.jsp)**: [Pàdé](https://www.igniterealtime.org/projects/pade/index.jsp)
- **[Roundcube](https://roundcube.net)**: [roundcube-converse.js-xmpp-plugin](https://github.com/devurandom/roundcube-converse.js-xmpp-plugin)
- **[Ruby on Rails](https://rubyonrails.org)**: [conversejs-rails](https://github.com/mikemarsian/conversejs-rails)
- **[Tiki Wiki CMS Groupware](https://tiki.org)**: [built-in optional feature](https://doc.tiki.org/XMPP)
- **[Wordpress](https://wordpress.org)**: [ConverseJS](https://wordpress.org/plugins/conversejs/)
## Tests
We use behavior-driven tests written with [jasmine.js](https://jasmine.github.io/).
Run `make check` to execute all the tests.
## Licence
`Converse.js` is released under the [Mozilla Public License (MPL)](https://www.mozilla.org/MPL/2.0/index.txt).
## Attribution
Emoji images are courtesy of [Twemoji](https://emojitwo.github.io/).
## Support
Issues can be logged on the [Github issue tracker](https://github.com/conversejs/converse.js/issues).
## Donations
A heartfelt thanks for everyone who has supported this project over the years.
Many people have contributed testing, bugfixes, features and corrections.
We accept donations via [Patreon](https://www.patreon.com/jcbrand) and [Liberapay](https://liberapay.com/jcbrand).
## Sponsors
<p>
<a href="https://bairesdev.com/sponsoring-open-source-projects/?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="BairesDev" src="https://raw.githubusercontent.com/conversejs/media/main/logos/bairesdev-primary.png" width="200">
</a>
</p>
<p>
<a href="https://blokt.com?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Blokt Crypto & Privacy" src="https://raw.githubusercontent.com/conversejs/converse.js/541613d1fea8aef364af00180f60e959162e5e4b/logo/blokt.png" width="200">
</a>
</p>
<p>
<a href="https://primesound.org/?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="Prime Sound" src="https://raw.githubusercontent.com/conversejs/media/main/logos/primesound.png" width="200">
</a>
</p>
<p>
<a href="https://www.keycdn.com?utm_source=conversejs" target="_blank" rel="noopener">
<img alt="KeyCDN" src="https://raw.githubusercontent.com/conversejs/converse.js/541613d1fea8aef364af00180f60e959162e5e4b/logo/keycdn.png" width="200">
</a>
</p>

View File

@ -1,87 +0,0 @@
Weblate
=======
Weblate is web based translation tool. It is based on translate-toolkit and
heavily uses git backed to store project.
Project goals
-------------
Minimalistic web based translation with direct commit to git on each
translation made. There is no plan in heavy conflict resolution as these
should be primarily handled on git side.
Planned features
----------------
* Easy web based translation
* Propagation of translations accross sub-projects (for different branches)
* Tight git integration
* Usage of Django's admin interface
* Upload and automatic merging of po files
* Links to source files for context
Requirements
------------
Django
https://www.djangoproject.com/
Translate-toolkit
http://translate.sourceforge.net/wiki/toolkit/index
GitPython (>= 0.3)
http://gitorious.org/projects/git-python/
Django-registration
https://bitbucket.org/ubernostrum/django-registration/
Installation
------------
Install all required components (see above), adjust settings.py and then run
./manage.py syncdb to create database structure. Now you should be able to
create translation projects using admin interface. You probably also want to
run ./manage.py setuplang to get default list of languages.
As setup of translation project includes fetching Git repositories, you might
want to preseed these, repos are stored in path defined by GIT_ROOT in
settings.py in <project>/<subproject> directories.
Management commands
-------------------
The ./manage.py is extended with following commands:
loadpo
Reloads translations from disk (eg. in case you did some updates in Git
repository).
setuplang
Setups list of languages (it has own list and all defined in
translate-toolkit).
updategit
Fetches remote Git repositories and updates internal cache.
Project name
------------
The project is named as mixture of words web and translate.
Authors
-------
This tool was written by Michal Čihař <michal@cihar.com>.
License
-------
Copyright (C) 2012 Michal Čihař <michal@cihar.com>
This program is free software: you can redistribute it and/or modify it under
the terms of the GNU General Public License as published by the Free Software
Foundation, either version 3 of the License, or (at your option) any later
version.
This program is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
PARTICULAR PURPOSE. See the GNU General Public License for more details.
You should have received a copy of the GNU General Public License along with
this program. If not, see <http://www.gnu.org/licenses/>.

18
RELEASE.md Normal file
View File

@ -0,0 +1,18 @@
# Release checklist
1. Merge weblate translations: https://hosted.weblate.org/projects/conversejs/translations/#repository
2. Run `make check` to check that all tests pass.
3. Run `make version VERSION=10.1.6`
4. Do a `git diff` to check if things look sane.
5. Do a quick manual test with the `dist` files (via `index.html`)
6. `git commit -am "Release 10.1.6"`
7. `git tag -s v10.1.6 -m "Release 10.1.6"`
8. `git push && git push origin v10.1.6`
9. `make publish BRANCH=v10.1.6`
10. Update release page on Github
* Upload tar files
11. Update https://conversejs.org
* `cd /home/conversejs/converse.js`
* `make deploy VERSION=10.1.6`
12. Update the repository on weblate
13. Decide on next release number and run `make postrelease VERSION=10.1.7`

8
TODO
View File

@ -1,8 +0,0 @@
Possible features for future releases
* Auto translate using some online service
* Checking of messages
* \n at beginning/end
* php-format
* python-format
* Glossary of frequently used term (per project)

View File

View File

View File

@ -1,8 +0,0 @@
from django.contrib import admin
from accounts.models import Profile
class ProfileAdmin(admin.ModelAdmin):
search_fields = ['user__username']
admin.site.register(Profile, ProfileAdmin)

View File

@ -1,53 +0,0 @@
from django import forms
from django.utils.translation import ugettext_lazy as _
from accounts.models import Profile
from django.contrib.auth.models import User
from registration.forms import RegistrationFormUniqueEmail
class ProfileForm(forms.ModelForm):
class Meta:
model = Profile
exclude = [
'suggested',
'translated',
]
class UserForm(forms.ModelForm):
class Meta:
model = User
fields = [
'first_name',
'last_name',
'email',
]
class ContactForm(forms.Form):
subject = forms.CharField(label = _('Subject'), required = True)
name = forms.CharField(label = _('Your name'), required = True)
email = forms.EmailField(label = _('Your email'), required = True)
message = forms.CharField(
label = _('Message'),
required = True,
widget = forms.Textarea
)
class RegistrationForm(RegistrationFormUniqueEmail):
first_name = forms.CharField(label = _('First name'))
last_name = forms.CharField(label = _('Last name'))
def __init__(self, *args, **kwargs):
super(RegistrationForm, self).__init__(*args, **kwargs)
self.fields['username'].label = _('Username')
self.fields['email'].label = _('Email address')
self.fields['password1'].label = _('Password')
self.fields['password2'].label = _('Password (again)')
def save(self, *args, **kwargs):
new_user = super(RegistrationForm, self).save(*args, **kwargs)
new_user.first_name = self.cleaned_data['first_name']
new_user.last_name = self.cleaned_data['last_name']
new_user.save()
return new_user

View File

@ -1,8 +0,0 @@
'''
Fake file to translate messages from django-registration.
'''
def fake():
_(u'This username is already taken. Please choose another.')
_(u'You must type the same password each time')
_(u'This email address is already in use. Please supply a different email address.')

View File

@ -1,47 +0,0 @@
from django.db import models
from django.dispatch import receiver
from django.contrib.auth.models import User
from django.conf import settings
from django.contrib.auth.signals import user_logged_in
from django.db.models.signals import post_save
from django.utils.translation import ugettext_lazy as _
from lang.models import Language
class Profile(models.Model):
user = models.ForeignKey(User, unique = True, editable = False)
language = models.CharField(
verbose_name = _(u"Interface Language"),
max_length = 10,
choices = settings.LANGUAGES
)
languages = models.ManyToManyField(
Language,
verbose_name = _('Languages'),
blank = True,
)
secondary_languages = models.ManyToManyField(
Language,
verbose_name = _('Secondary languages'),
related_name = 'secondary_profile_set',
blank = True,
)
suggested = models.IntegerField(default = 0, db_index = True)
translated = models.IntegerField(default = 0, db_index = True)
@receiver(user_logged_in)
def set_lang(sender, **kwargs):
lang_code = kwargs['user'].get_profile().language
kwargs['request'].session['django_language'] = lang_code
def create_profile_callback(sender, **kwargs):
'''
Automatically create profile when creating new user.
'''
if kwargs['created']:
profile, newprofile = Profile.objects.get_or_create(user = kwargs['instance'])
if newprofile:
profile.save
post_save.connect(create_profile_callback, sender = User)

View File

@ -1,16 +0,0 @@
"""
This file demonstrates writing tests using the unittest module. These will pass
when you run "manage.py test".
Replace this with more appropriate tests for your application.
"""
from django.test import TestCase
class SimpleTest(TestCase):
def test_basic_addition(self):
"""
Tests that 1 + 1 always equals 2.
"""
self.assertEqual(1 + 1, 2)

View File

@ -1,62 +0,0 @@
from django.shortcuts import render_to_response
from django.template import RequestContext
from django.conf import settings
from django.contrib import messages
from django.utils.translation import ugettext as _
from django.http import HttpResponseRedirect
from django.core.mail import mail_admins
from django.contrib.auth.decorators import login_required
from accounts.models import set_lang
from accounts.forms import ProfileForm, UserForm, ContactForm
@login_required
def profile(request):
if request.method == 'POST':
form = ProfileForm(request.POST, instance = request.user.get_profile())
userform = UserForm(request.POST, instance = request.user)
if form.is_valid() and userform.is_valid():
form.save()
userform.save()
set_lang(request.user, request = request, user = request.user)
# Need to redirect to allow language change
return HttpResponseRedirect('/accounts/profile/')
else:
form = ProfileForm(instance = request.user.get_profile())
userform = UserForm(instance = request.user)
response = render_to_response('profile.html', RequestContext(request, {
'form': form,
'userform': userform,
'title': _('User profile'),
}))
response.set_cookie(settings.LANGUAGE_COOKIE_NAME, request.user.get_profile().language)
return response
def contact(request):
if request.method == 'POST':
form = ContactForm(request.POST)
if form.is_valid():
mail_admins(
form.cleaned_data['subject'],
'Message from %s <%s>:\n\n%s' % (
form.cleaned_data['name'],
form.cleaned_data['email'],
form.cleaned_data['message']
))
messages.add_message(request, messages.INFO, _('Message has been sent to administrator.'))
return HttpResponseRedirect('/')
else:
initial = {}
if request.user.is_authenticated():
initial['name'] = request.user.get_full_name()
initial['email'] = request.user.email
if 'subject' in request.GET:
initial['subject'] = request.GET['subject']
form = ContactForm(initial = initial)
return render_to_response('contact.html', RequestContext(request, {
'form': form,
'title': _('Contact'),
}))

10
babel.config.json Normal file
View File

@ -0,0 +1,10 @@
{
"presets": [
["@babel/preset-env", {
"targets": {
"browsers": [">1%", "not ie 11", "not op_mini all", "not dead"]
}
}]
],
"plugins": []
}

10
composer.json Normal file
View File

@ -0,0 +1,10 @@
{
"name": "jcbrand/converse.js",
"description": "Browser based XMPP instant messaging client",
"type": "library",
"license": "MPL-2.0",
"minimum-stability": "stable",
"homepage": "https://conversejs.org/",
"keywords": ["xmpp", "messaging", "chat", "presence"],
"require": {}
}

293
conversejs.doap Normal file
View File

@ -0,0 +1,293 @@
<?xml version="1.0" encoding="UTF-8"?>
<rdf:RDF xmlns:doap="http://usefulinc.com/ns/doap#" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xmpp="https://linkmauve.fr/ns/xmpp-doap#" xmlns:schema="https://schema.org/" xml:lang="en">
<Project xmlns="http://usefulinc.com/ns/doap#">
<name>Converse.js</name>
<shortdesc>Browser based XMPP chat client</shortdesc>
<homepage rdf:resource="https://conversejs.org/"/>
<bug-database rdf:resource="https://github.com/conversejs/converse.js/issues"/>
<developer-forum rdf:resource="xmpp:discuss@conference.conversejs.org?join"/>
<support-forum rdf:resource="xmpp:discuss@conference.conversejs.org?join"/>
<category rdf:resource="https://linkmauve.fr/ns/xmpp-doap#category-client"/>
<programming-language>JavaScript</programming-language>
<os>Browser</os>
<os>Linux</os>
<os>macOS</os>
<os>Windows</os>
<schema:logo rdf:resource="https://raw.githubusercontent.com/conversejs/converse.js/master/logo/conversejs-filled.svg"/>
<repository>
<GitRepository>
<browse rdf:resource="https://github.com/conversejs/converse.js"/>
<location rdf:resource="https://github.com/conversejs/converse.js.git"/>
</GitRepository>
</repository>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6120"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6121"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc6122"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7395"/>
<implements rdf:resource="https://www.rfc-editor.org/info/rfc7590"/>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0004.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0030.html"/>
<xmpp:since>0.8.2</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0045.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0048.html"/>
<xmpp:since>2.0.1</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0050.html"/>
<xmpp:since>7.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0054.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0059.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0060.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0066.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0077.html"/>
<xmpp:since>0.8.5</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0085.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0115.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>advertises caps but no caching</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0122.html"/>
<xmpp:status>partial</xmpp:status>
<xmpp:note>basic string field sub-type usage</xmpp:note>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0124.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0144.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0156.html"/>
<xmpp:since>6.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0163.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0184.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0198.html"/>
<xmpp:since>5.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0199.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0203.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0206.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0245.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0249.html"/>
<xmpp:since>0.8.2</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0280.html"/>
<xmpp:since>0.8.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0297.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0308.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0313.html"/>
<xmpp:since>0.9.5</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0317.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0319.html"/>
<xmpp:since>4.0.5</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0333.html"/>
<xmpp:since>4.1.1</xmpp:since>
<xmpp:status>partial</xmpp:status>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0352.html"/>
<xmpp:since>0.9.4</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0357.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0359.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0363.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0371.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0372.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0382.html"/>
<xmpp:since>3.3.3</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0384.html"/>
<xmpp:since>4.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0393.html"/>
<xmpp:since>8.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0410.html"/>
<xmpp:since>5.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0421.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0422.html"/>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0424.html"/>
<xmpp:since>6.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0425.html"/>
<xmpp:since>6.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0437.html"/>
<xmpp:since>8.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
<implements>
<xmpp:SupportedXep>
<xmpp:xep rdf:resource="https://xmpp.org/extensions/xep-0454.html"/>
<xmpp:since>8.0.0</xmpp:since>
</xmpp:SupportedXep>
</implements>
</Project>
</rdf:RDF>

127
demo/anonymous.html Normal file
View File

@ -0,0 +1,127 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Converse - Anonymous login demo</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Converse XMPP/Jabber Chat"/>
<meta name="author" content="JC Brand" />
<meta name="keywords" content="xmpp chat webchat converse.js Converse" />
<!-- These files are NOT needed when using converse.js in your own project. -->
<link rel="shortcut icon" type="image/ico" href="/dist/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="/dist/website.min.css" />
<noscript><p><img src="//stats.opkode.com/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript>
<script type="text/javascript" src="analytics.js"></script>
<!-- *********************************************************************** -->
<link rel="manifest" href="/manifest.json">
<link type="text/css" rel="stylesheet" media="screen" href="/dist/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="/dist/converse.min.js"></script>
</head>
<body id="page-top" data-spy="scroll" class="converse-website">
<section class="section-wrapper">
<nav class="navbar sticky-top navbar-expand-lg" role="navigation">
<div class="collapse navbar-collapse" id="navbarTogglerDemo01">
<span class="page-scroll">
<a class="navbar-brand" href="/"><span class="converse-brand-heading">Home</span></a>
<a class="navbar-brand" href="/demo"><span class="converse-brand-heading">Demos</span></a>
</span>
</div>
</nav>
<section id="intro" class="intro" class="container">
<div class="row">
<div class="col-md-12 col-md-offset-2">
<h1 class="brand-heading fade-in">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-heading__text">
<span>converse<span class="subdued">.js</span></span>
<p class="byline">messaging freedom</p>
</span>
</h1>
<p class="intro-text">Anonymous login demo</p>
</div>
</div>
</section>
</section>
</body>
<script>
/*
@licstart
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
@licend
*/
converse.initialize({
allow_logout: false, // No point in logging out when we have auto_login as true.
allow_muc_invitations: false, // Doesn't make sense to allow because only
// roster contacts can be invited
allow_contact_requests: false, // Contacts from other servers cannot,
// be added and anonymous users don't
// know one another's JIDs, so disabling.
authentication: 'anonymous',
auto_login: true,
auto_join_rooms: [
'anonymous@conference.nomnom.im',
],
notify_all_room_messages: [
'anonymous@conference.nomnom.im',
],
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
jid: 'nomnom.im', // XMPP server which allows anonymous login (doesn't
// allow chatting with other XMPP servers).
keepalive: true,
hide_muc_server: true, // Federation is disabled, so no use in
// showing the MUC server.
play_sounds: true,
show_controlbox_by_default: true,
strict_plugin_dependencies: false,
});
</script>
</html>

103
demo/embedded.html Normal file
View File

@ -0,0 +1,103 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Converse - Anonymous login demo</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Converse XMPP/Jabber Chat"/>
<meta name="author" content="JC Brand" />
<meta name="keywords" content="xmpp chat webchat converse.js Converse" />
<!-- These files are NOT needed when using converse.js in your own project. -->
<link rel="shortcut icon" type="image/ico" href="../dist/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="../dist/website.min.css" />
<noscript><p><img src="https://stats.opkode.com/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript>
<script type="text/javascript" src="/analytics.js"></script>
<!-- *********************************************************************** -->
<link rel="manifest" href="../manifest.json">
<link type="text/css" rel="stylesheet" media="screen" href="../dist/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="../dist/converse.min.js"></script>
<style>
.converse-container {
height: 50vh;
}
</style>
</head>
<body id="page-top" data-spy="scroll" class="converse-website">
<section class="section-wrapper">
<nav class="navbar sticky-top navbar-expand-lg" role="navigation">
<div class="collapse navbar-collapse" id="navbarTogglerDemo01">
<span class="page-scroll">
<a class="navbar-brand" href="/"><span class="converse-brand-heading">Home</span></a>
<a class="navbar-brand" href="/demo"><span class="converse-brand-heading">Demos</span></a>
</span>
</div>
</nav>
<section class="intro">
<div class="intro-body">
<div class="container">
<div class="row">
<div class="col-md-12">
<h1 class="brand-heading fade-in" style="margin: 1.5em 0 0 0">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Home</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-heading__text">
<span>converse<span class="subdued">.js</span></span>
<p class="byline">messaging freedom</p>
</span>
</h1>
<p class="intro-text">Embedded MUC chat demo</p>
<div class="converse-container">
<converse-root></converse-root>
</div>
</div>
</div>
</div>
</div>
</section>
</section>
</body>
<script>
converse.initialize({
authentication: 'anonymous',
auto_login: true,
auto_join_rooms: [
'anonymous@conference.nomnom.im',
],
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
jid: 'nomnom.im', // XMPP server which allows anonymous login (doesn't
// allow chatting with other XMPP servers).
notify_all_room_messages: [
'anonymous@conference.nomnom.im',
],
singleton: true,
locales_url: "../locale/{{{locale}}}/LC_MESSAGES/converse.json",
view_mode: 'embedded',
});
</script>
</html>

113
demo/index.html Normal file
View File

@ -0,0 +1,113 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Converse Demos</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Converse XMPP/Jabber Chat"/>
<meta name="author" content="JC Brand" />
<meta name="keywords" content="xmpp chat webchat converse.js Converse" />
<!-- These files are NOT needed when using converse.js in your own project. -->
<link rel="shortcut icon" type="image/ico" href="/dist/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="/dist/website.min.css" />
<noscript><p><img src="//stats.opkode.com/piwik.php?idsite=1" style="border:0;" alt="" /></p></noscript>
<script type="text/javascript" src="analytics.js"></script>
<!-- *********************************************************************** -->
<link rel="manifest" href="/manifest.json">
<link type="text/css" rel="stylesheet" media="screen" href="/dist/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="/dist/converse.min.js"></script>
</head>
<body id="page-top" data-spy="scroll" class="converse-website">
<section class="section-wrapper">
<nav class="navbar sticky-top navbar-expand-lg" role="navigation">
<div class="collapse navbar-collapse" id="navbarTogglerDemo01">
<span class="page-scroll">
<a class="navbar-brand" href="/"><span class="converse-brand-heading">Home</span></a>
</span>
</div>
</nav>
<section id="intro" class="intro" class="container">
<div class="row">
<div class="col-md-12 col-md-offset-2">
<h1 class="brand-heading fade-in">
<svg class="converse-svg-logo"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Home</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-heading__text">
<span>converse<span class="subdued">.js</span></span>
<p class="byline">messaging freedom</p>
</span>
</h1>
<p class="intro-text">Demos:</p>
<p class="intro-text">
<ul style="list-style: none; font-size: 22px;">
<li><a href="/fullscreen.html">As a fullscreen application</a></li>
<li><a href="/demo/anonymous.html">Anonymous login</a></li>
<li><a href="/demo/embedded.html">Single MUC chatroom embedded into the page</a></li>
</ul>
</p>
</div>
</div>
</section>
</section>
</section>
</body>
<script>
/*
@licstart
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <https://unlicense.org/>
@licend
*/
converse.initialize({
// Please use this connection manager only for testing purposes
bosh_service_url: 'https://conversejs.org/http-bind/'
});
</script>
</html>

50
dev.html Normal file
View File

@ -0,0 +1,50 @@
<!DOCTYPE html>
<html lang="en">
<head>
<title>Converse</title>
<meta charset="utf-8">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta name="description" content="Converse XMPP/Jabber Chat" />
<meta name="author" content="JC Brand" />
<meta name="keywords" content="xmpp chat webchat converse.js" />
<link rel="manifest" href="./manifest.json">
<link rel="shortcut icon" type="image/ico" href="images/favicon.ico"/>
<link type="text/css" rel="stylesheet" media="screen" href="dist/website.css" />
<link type="text/css" rel="stylesheet" media="screen" href="dist/converse.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="dist/converse.js"></script>
</head>
<body class="reset" style="background-color: var(--global-background-color)">
<div id="conversejs-bg"></div>
<script>
converse.plugins.add('converse-debug', {
initialize () {
const { _converse } = this;
window._converse = _converse;
}
});
converse.initialize({
i18n: 'af',
theme: 'dracula',
auto_away: 300,
enable_smacks: true,
loglevel: 'debug',
reuse_scram_keys: true,
prune_messages_above: 100,
message_archiving: 'always',
muc_respect_autojoin: true,
muc_show_logs_before_join: true,
notify_all_room_messages: ['discuss@conference.conversejs.org'],
view_mode: 'fullscreen',
// websocket_url: 'wss://conversejs.org/xmpp-websocket',
websocket_url: 'ws://chat.example.org:5380/xmpp-websocket',
whitelisted_plugins: ['converse-debug'],
// connection_options: { worker: '/dist/shared-connection-worker.js' }
});
</script>
</body>
</html>

View File

@ -0,0 +1,48 @@
.brand-heading {
display: flex;
}
.brand-heading__text {
font-size: 6rem;
margin-left: 1rem;
margin-top: -1rem;
}
.subdued {
color: darkgray;
}
.byline {
font-size: 30%;
margin-top: 0;
}
section h1 {
margin-left: 0;
}
h2 {
font-size: 40px;
}
h3 {
font-size: 30px;
}
h4 {
font-size: 25px;
margin-top: 40px;
}
p {
font-size: 1.2rem;
}
.details {
margin-bottom: 20px;
}
.prettyprint code {
padding: 8px 12px;
font-family: courier;
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.1 KiB

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 64 KiB

View File

@ -0,0 +1,169 @@
body {
font-family: "Lora", "Helvetica Neue", Helvetica, Arial, sans-serif;
}
h1 {
font-size: 50px;
}
h4 {
font-weight: bold;
}
h5 {
font-size: 16px;
font-weight: bold;
}
.toctree-l1 > a {
font-size: 110%;
font-weight: bold;
}
.navbar-brand {
padding-top: 7px;
}
.navbar-brand img {
float: left;
margin-right: 0.5em;
}
.nav-header {
font-weight: bold;
font-size: 110%;
}
.sidebar-title {
padding-left: 15px;
color: #716b7a;
}
.sponsors-list {
overflow-y: auto !important;
overflow-x: hidden;
}
.bs-sidenav .sponsors-list li a:hover {
background-color: transparent;
border: none;
}
.sponsors-list li {
padding: 0.5em 0;
}
.sponsors-list li a {
background-color: transparent;
text-align: center;
}
.centered-text-container {
display: block;
width: 100%;
text-align: center;
}
.patreon-link-container {
margin: 0.5em 0 1em 0;
padding: 0;
}
.patreon-link-container a {
font-size: 85%;
}
#sidebar > .nav-list {
max-height: 35vh;
overflow-y: auto;
}
.bs-sidenav .nav .nav > li > a {
font-size: 100%;
}
.bs-sidenav .nav .nav .nav > li > a {
font-size: 90%;
color: gray;
}
/*
Copyright (c) 2012 Terrence Ryan
Permission is hereby granted, free of charge, to any person obtaining a copy of this
software and associated documentation files (the "Software"), to deal in the Software
without restriction, including without limitation the rights to use, copy, modify,
merge, publish, distribute, sublicense, and/or sell copies of the Software, and to
permit persons to whom the Software is furnished to do so, subject to the following
conditions:
The above copyright notice and this permission notice shall be included in all copies
or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE
OR OTHER DEALINGS IN THE SOFTWARE.
*/
#banner {
height: 149px;
width: 149px;
overflow:hidden;
padding: 0;
margin: 0;
float: right;
}
#banner a {
display: block;
width: 235px;
font-size: 14px;
font-family: Frutiger, "Frutiger Linotype", Univers, Calibri, "Gill Sans", "Gill Sans MT",
"Myriad Pro", Myriad, "DejaVu Sans Condensed", "Liberation Sans", "Nimbus Sans L", Tahoma,
Geneva, "Helvetica Neue", Helvetica, Arial, sans serif;
background-color: #333;
color: #FFF;
word-spacing: 2px;
text-decoration: none;
padding: 5px 15px 5px 25px;
position:relative;
left: 20px;
top: -33px;
text-align: center;
-moz-transform-origin: 0 0 ;
-moz-transform:rotate(45deg);
-moz-box-shadow: 1px 1px 5px 1px #666;
-webkit-transform-origin: 0 0 ;
-webkit-transform:rotate(45deg);
-webkit-box-shadow: 1px 1px 5px 1px #666;
-ms-transform-origin: 0 0 ;
-ms-transform:rotate(45deg);
-ms-box-shadow: 1px 1px 5px 1px #666;
transform-origin: 0 0 ;
transform:rotate(45deg);
box-shadow: 1px 1px 5px 1px #666;
background-image: linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -o-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -moz-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -webkit-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -ms-linear-gradient(bottom, #000000 3%, #666666 5%, #000000 7%, #000000 93%, #666666 95%, #000000 97%);
background-image: -webkit-gradient(
linear,
left bottom,
left top,
color-stop(0.03, #000000),
color-stop(0.05, #666666),
color-stop(0.07, #000000),
color-stop(0.93, #000000),
color-stop(0.95, #666666),
color-stop(0.97, #000000)
);
}

View File

@ -0,0 +1,63 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Converse.js API Documentation <?js= title ?></title>
<script src="scripts/prettify/prettify.js"></script>
<script src="scripts/prettify/lang-css.js"></script>
<script src="./analytics.js"></script>
<link type="text/css" rel="stylesheet" href="styles/prettify-tomorrow.css">
<link type="text/css" rel="stylesheet" href="styles/jsdoc-default.css">
<link type="text/css" rel="stylesheet" href="/docs/source/_static/api.css">
<link rel="shortcut icon" href="/images/favicon.ico"/>
</head>
<body>
<div id="main">
<h1 class="brand-heading fade-in">
<svg
style="height: 8rem"
xmlns:svg="http://www.w3.org/2000/svg"
xmlns="http://www.w3.org/2000/svg"
xmlns:xlink="http://www.w3.org/1999/xlink"
viewBox="0 0 364 364">
<title>Converse</title>
<g class="cls-1" id="g904">
<g data-name="Layer 2">
<g data-name="Layer 7">
<path
class="cls-3"
d="M221.46,103.71c0,18.83-29.36,18.83-29.12,0C192.1,84.88,221.46,84.88,221.46,103.71Z" />
<path
class="cls-4"
d="M179.9,4.15A175.48,175.48,0,1,0,355.38,179.63,175.48,175.48,0,0,0,179.9,4.15Zm-40.79,264.5c-.23-17.82,27.58-17.82,27.58,0S138.88,286.48,139.11,268.65ZM218.6,168.24A79.65,79.65,0,0,1,205.15,174a12.76,12.76,0,0,0-6.29,4.65L167.54,222a1.36,1.36,0,0,1-2.46-.8v-35.8a2.58,2.58,0,0,0-3.06-2.53c-15.43,3-30.23,7.7-42.73,19.94-38.8,38-29.42,105.69,16.09,133.16a162.25,162.25,0,0,1-91.47-67.27C-3.86,182.26,34.5,47.25,138.37,25.66c46.89-9.75,118.25,5.16,123.73,62.83C265.15,120.64,246.56,152.89,218.6,168.24Z" />
</g>
</g>
</g>
</svg>
<span class="brand-heading__text">
<span>converse<span class="subdued">.js</span></span>
<p class="byline">API Documentation</p>
</span>
</h1>
<h1 class="page-title"><?js= title ?></h1>
<?js= content ?>
</div>
<nav>
<h2><a href="/docs/html/index.html">Docs Entrypoint</a></h2>
<?js= this.nav ?>
</nav>
<br class="clear">
<footer>
Documentation generated by <a href="https://github.com/jsdoc3/jsdoc">JSDoc <?js= env.version.number ?></a><?js if(env.conf.templates && env.conf.templates.default && env.conf.templates.default.includeDate !== false) { ?> on <?js= (new Date()) ?><?js } ?>
</footer>
<script> prettyPrint(); </script>
<script src="scripts/linenumber.js"> </script>
</body>
</html>

View File

@ -0,0 +1,13 @@
{# Import the theme's layout. #}
{% extends "!layout.html" %}
{# Custom CSS overrides #}
{% set css_files = css_files + ['_static/style.css'] %}
{% set script_files = script_files + ["../../analytics.js"] %}
{# Add some extra stuff before and use existing with 'super()' call. #}
{% block footer %}
{{ super() }}
{% endblock %}

View File

@ -0,0 +1,13 @@
{#
basic/localtoc.html
~~~~~~~~~~~~~~~~~~~
Sphinx sidebar template: local table of contents.
:copyright: Copyright 2007-2016 by the Sphinx team, see AUTHORS.
:license: BSD, see LICENSE for details.
#}
{%- if display_toc %}
<h3 class="sidebar-title"><a href="{{ pathto(master_doc) }}">{{ _('Table Of Contents') }}</a></h3>
{{ toc }}
{%- endif %}

View File

@ -0,0 +1,22 @@
<span class="centered-text-container">
<h4 class="sidebar-title">Sponsored by</h4>
</span>
<ul class="sponsors-list">
<li><a href="https://bairesdev.com/sponsoring-open-source-projects/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 10em" src="/media/logos/bairesdev-primary.png" alt="BairesDev">
</a>
</li>
<li><a href="https://blokt.com/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 9em" src="/logo/blokt.png" alt="Blokt Crypto & Privacy">
</a>
</li>
<li><a href="https://primesound.org/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="width: 9em" src="/media/logos/primesound.png" alt="Prime Sound">
</a>
</li>
<li><a href="https://www.keycdn.com/?utm_source=conversejs" target="_blank" rel="noopener">
<img style="height: 2.5em" src="/logo/keycdn.png" alt="KeyCDN">
</a>
</li>
</ul>
<span class="centered-text-container patreon-link-container"><a href="https://conversejs.org#sponsors">Become a sponsor</a></span>

12
docs/source/api/index.rst Normal file
View File

@ -0,0 +1,12 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/api/index.rst">Edit me on GitHub</a></div>
============================================
The API documentation (generated with JSDoc)
============================================
This document is a stub. It shouldn't show at all, instead it's a hack in order
to link to the JSDoc output.
See https://stackoverflow.com/questions/27979803/external-relative-link-in-sphinx-toctree-directive

107
docs/source/builds.rst Normal file
View File

@ -0,0 +1,107 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/builds.rst">Edit me on GitHub</a></div>
.. _builds:
=================
Generating builds
=================
.. contents:: Table of Contents
:depth: 3
:local:
.. warning:: There current documentation in this section does not adequately
explain how to create custom bundles.
.. Note:: Please make sure to read the section :doc:`development` and that you have installed
all development dependencies (long story short, you should be able to just run ``make dev``)
.. _creating_builds:
Creating JavaScript and CSS bundles and distribution files
==========================================================
Converse uses `webpack <https://webpack.js.org/>`_ to create the final JavaScript and CSS distribution files.
The generated distribution files are all placed in the ``./dist`` directory.
The Converse repository does not include ``dist`` directory by default.
To generate the ``./dist`` directory and all CSS and JavaScript bundles, simply run ``make dist``.
When you're developing, and constantly changing code, you can run ``make watch``
to let the bundles be automatically generated as soon as you edit a file.
.. note::
If you're on Windows or don't have GNU Make installed, you can run ``npm build``
to build all the distribution files.
Creating custom bundles
=======================
One reason you might want to create your own bundles, is because you want to
remove some of the core plugins of Converse, or perhaps you want to include
your own.
To add or remove plugins from the build, you need to modify the
`src/converse.js <https://github.com/conversejs/converse.js/blob/master/src/converse.js>`_ file.
You'll find a section marked ``/* START: Removable components`` and
``/* END: Removable components */``.
In this section is listed the Converse plugins that will make up a bundle.
You could for example decide to disable the ControlBox altogether by removing
the ``converse-controlbox`` plugin.
After doing so, you need to run ``make dist`` again in the root or your
Converse repository, in order to generate the new build.
Be aware that some plugins might have dependencies on other plugins, so if you
remove a certain plugin but other included plugins still depend on it, then it
will still be included in your build.
To see which other plugins a particular plugin depends on, open it up in your
text editor and look at the list specified as the second parameter to the
``define`` call, near the top of the file. This list specifies the dependencies
of that plugin.
Besides the standard build, the Converse repository includes configuration
for certain other non-standard builds, which we'll now mention below.
Excluding all 3rd party dependencies
------------------------------------
The ``dist/converse-no-dependencies.js`` bundle contains only the core Converse
code and none of the 3rd party dependencies. This might be useful if you need
to load the dependencies separately.
To generate this bundle, you can run:
::
make dist/converse-no-dependencies.js
make dist/converse-no-dependencies.min.js
Headless build
--------------
Converse also has a special build called the `headless build`.
You can generate it by running ``make dist/converse-headless.js``
The headless build is a bundle of all the non-UI parts of Converse, and its aim
is to provide you with an XMPP library (and application) on which you can build
your own UI.
It's also installable as `@converse/headless <https://www.npmjs.com/package/@converse/headless>`_.
The main distribution of Converse relies on the headless build.
The file `src/headless/headless.js <https://github.com/jcbrand/converse.js/blob/master/src/headless/headless.js>`_
is used to determine which plugins are included in the build.

8
docs/source/conf.json Normal file
View File

@ -0,0 +1,8 @@
{
"plugins": ["plugins/markdown"],
"templates": {
"default": {
"layoutFile": "_templates/jsdoc_layout.tmpl"
}
}
}

288
docs/source/conf.py Normal file
View File

@ -0,0 +1,288 @@
# -*- coding: utf-8 -*-
#
# Converse documentation build configuration file, created by
# sphinx-quickstart on Fri Apr 26 20:48:03 2013.
#
# This file is execfile()d with the current directory set to its containing dir.
#
# Note that not all possible configuration values are present in this
# autogenerated file.
#
# All configuration values have a default; values that are commented out
# serve to show the default.
import sys, os
# If extensions (or modules to document with autodoc) are in another directory,
# add these directories to sys.path here. If the directory is relative to the
# documentation root, use os.path.abspath to make it absolute, like shown here.
#sys.path.insert(0, os.path.abspath('.'))
# -- General configuration -----------------------------------------------------
# If your documentation needs a minimal Sphinx version, state it here.
#needs_sphinx = '1.0'
# Add any Sphinx extension module names here, as strings. They can be extensions
# coming with Sphinx (named 'sphinx.ext.*') or your custom ones.
extensions = ['sphinx.ext.todo']
# Add any paths that contain templates here, relative to this directory.
templates_path = ['_templates']
# The suffix of source filenames.
source_suffix = '.rst'
# The encoding of source files.
#source_encoding = 'utf-8-sig'
# The master toctree document.
master_doc = 'index'
# General information about the project.
project = u'Converse'
copyright = u'2018, JC Brand'
# The version info for the project you're documenting, acts as replacement for
# |version| and |release|, also used in various other places throughout the
# built documents.
#
# The short X.Y version.
version = '10.1.6'
# The full version, including alpha/beta/rc tags.
release = '10.1.6'
# The language for content autogenerated by Sphinx. Refer to documentation
# for a list of supported languages.
#language = None
# There are two options for replacing |today|: either, you set today to some
# non-false value, then it is used:
#today = ''
# Else, today_fmt is used as the format for a strftime call.
#today_fmt = '%B %d, %Y'
# List of patterns, relative to source directory, that match files and
# directories to ignore when looking for source files.
exclude_patterns = []
# The reST default role (used for this markup: `text`) to use for all documents.
#default_role = None
# If true, '()' will be appended to :func: etc. cross-reference text.
#add_function_parentheses = True
# If true, the current module name will be prepended to all description
# unit titles (such as .. function::).
#add_module_names = True
# If true, sectionauthor and moduleauthor directives will be shown in the
# output. They are ignored by default.
#show_authors = False
# The name of the Pygments (syntax highlighting) style to use.
pygments_style = 'sphinx'
# A list of ignored prefixes for module index sorting.
#modindex_common_prefix = []
# -- Options for HTML output ---------------------------------------------------
# The theme to use for HTML and HTML Help pages. See the documentation for
# a list of builtin themes.
import sphinx_bootstrap_theme
html_theme = 'bootstrap'
html_theme_path = sphinx_bootstrap_theme.get_html_theme_path()
# Add any paths that contain custom static files (such as style sheets) here,
# relative to this directory. They are copied after the builtin static files,
# so a file named "default.css" will overwrite the builtin "default.css".
html_static_path = ['_static']
# (Optional) Logo. Should be small enough to fit the navbar (ideally 24x24).
# Path should be relative to the ``_static`` files directory.
html_logo = "_static/logo.svg"
# Theme options are theme-specific and customize the look and feel of a
# theme further.
html_theme_options = {
# Navigation bar title. (Default: ``project`` value)
'navbar_title': "Converse",
# Tab name for entire site. (Default: "Site")
'navbar_site_name': "Table of Contents",
# A list of tuples containing pages or urls to link to.
# Valid tuples should be in the following forms:
# (name, page) # a link to a page
# (name, "/aa/bb", 1) # a link to an arbitrary relative url
# (name, "http://example.com", True) # arbitrary absolute url
# Note the "1" or "True" value above as the third argument to indicate
# an arbitrary url.
'navbar_links': [
("Homepage", "https://conversejs.org", True)
],
# Render the next and previous page links in navbar. (Default: true)
'navbar_sidebarrel': True,
# Render the current pages TOC in the navbar. (Default: true)
'navbar_pagenav': True,
# Tab name for the current pages TOC. (Default: "Page")
'navbar_pagenav_name': "Current Page",
# Global TOC depth for "site" navbar tab. (Default: 1)
# Switching to -1 shows all levels.
'globaltoc_depth': 2,
# Include hidden TOCs in Site navbar?
#
# Note: If this is "false", you cannot have mixed ``:hidden:`` and
# non-hidden ``toctree`` directives in the same page, or else the build
# will break.
#
# Values: "true" (default) or "false"
'globaltoc_includehidden': "true",
# HTML navbar class (Default: "navbar") to attach to <div> element.
# For black navbar, do "navbar navbar-inverse"
'navbar_class': "navbar",
# Fix navigation bar to top of page?
# Values: "true" (default) or "false"
'navbar_fixed_top': "true",
# Location of link to source.
# Options are "nav" (default), "footer" or anything else to exclude.
'source_link_position': "footer",
# Bootswatch (http://bootswatch.com/) theme.
# Options are nothing (default) or the name of a valid theme
# such as "amelia" or "cosmo".
# 'bootswatch_theme': "yeti",
# Choose Bootstrap version.
# Values: "3" (default) or "2" (in quotes)
'bootstrap_version': "3",
}
# The name for this set of Sphinx documents. If None, it defaults to
# "<project> v<release> documentation".
#html_title = None
# A shorter title for the navigation bar. Default is the same as html_title.
#html_short_title = None
# The name of an image file (within the static path) to use as favicon of the
# docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32
# pixels large.
html_favicon = "_static/favicon.ico"
# If not '', a 'Last updated on:' timestamp is inserted at every page bottom,
# using the given strftime format.
#html_last_updated_fmt = '%b %d, %Y'
# If true, SmartyPants will be used to convert quotes and dashes to
# typographically correct entities.
#html_use_smartypants = True
# Custom sidebar templates, maps document names to template names.
html_sidebars = {'**': ['sponsors.html', 'localtoc.html', 'sourcelink.html', 'searchbox.html']}
# Additional templates that should be rendered to pages, maps page names to
# template names.
#html_additional_pages = {}
# If false, no module index is generated.
#html_domain_indices = True
# If false, no index is generated.
#html_use_index = True
# If true, the index is split into individual pages for each letter.
#html_split_index = False
# If true, links to the reST sources are added to the pages.
#html_show_sourcelink = True
# If true, "Created using Sphinx" is shown in the HTML footer. Default is True.
#html_show_sphinx = True
# If true, "(C) Copyright ..." is shown in the HTML footer. Default is True.
#html_show_copyright = True
# If true, an OpenSearch description file will be output, and all pages will
# contain a <link> tag referring to it. The value of this option must be the
# base URL from which the finished HTML is served.
#html_use_opensearch = ''
# This is the file name suffix for HTML files (e.g. ".xhtml").
#html_file_suffix = None
# Output file base name for HTML help builder.
htmlhelp_basename = 'Conversejsdoc'
# -- Options for LaTeX output --------------------------------------------------
latex_elements = {
# The paper size ('letterpaper' or 'a4paper').
#'papersize': 'letterpaper',
# The font size ('10pt', '11pt' or '12pt').
#'pointsize': '10pt',
# Additional stuff for the LaTeX preamble.
#'preamble': '',
}
# Grouping the document tree into LaTeX files. List of tuples
# (source start file, target name, title, author, documentclass [howto/manual]).
latex_documents = [
('index', 'Conversejs.tex', u'Converse Documentation',
u'JC Brand', 'manual'),
]
# The name of an image file (relative to this directory) to place at the top of
# the title page.
#latex_logo = None
# For "manual" documents, if this is true, then toplevel headings are parts,
# not chapters.
#latex_use_parts = False
# If true, show page references after internal links.
#latex_show_pagerefs = False
# If true, show URL addresses after external links.
#latex_show_urls = False
# Documents to append as an appendix to all manuals.
#latex_appendices = []
# If false, no module index is generated.
#latex_domain_indices = True
# -- Options for manual page output --------------------------------------------
# One entry per manual page. List of tuples
# (source start file, name, description, authors, manual section).
man_pages = [
('index', 'conversejs', u'Converse Documentation',
[u'JC Brand'], 1)
]
# If true, show URL addresses after external links.
#man_show_urls = False
# -- Options for Texinfo output ------------------------------------------------
# Grouping the document tree into Texinfo files. List of tuples
# (source start file, target name, title, author,
# dir menu entry, description, category)
texinfo_documents = [
('index', 'Conversejs', u'Converse Documentation',
u'JC Brand', 'Converse', 'Open Source XMPP webchat',
'Miscellaneous'),
]
# Documents to append as an appendix to all manuals.
#texinfo_appendices = []
# If false, no module index is generated.
#texinfo_domain_indices = True
# How to display URL addresses: 'footnote', 'no', or 'inline'.
#texinfo_show_urls = 'footnote'

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,139 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/dependencies.rst">Edit me on GitHub</a></div>
.. _`development`:
============================
Setting up a dev environment
============================
Installing the 3rd party dependencies
=====================================
To develop and customize Converse, you'll first need to check out Converse's Git
repository:
::
git clone https://github.com/conversejs/converse.js.git
cd converse.js
We use development tools which depend on Node.js and NPM (the Node package manager).
It's recommended that you use `NVM <https://github.com/nvm-sh/nvm>`_ (the Node version manager)
to make sure you have the right version of Node.
Refer to the `NVM Github page <https://github.com/nvm-sh/nvm#install--update-script>`_ for instructions on how to install it.
Once NVM is installed, you can run the following inside your checkout of the Converse Git repository:
::
nvm install
.. note::
You will always have to first run ``nvm install`` in a new terminal session before working on Converse.
To set up the Converse development environment, you now run ``make dev``.
::
make dev
Alternatively, if you're using Windows, or don't have GNU Make installed, you can run the
following:
::
npm install
npm run lerna
This will install the Node development tools and Converse's dependencies.
The front-end dependencies are those JavaScript files on which
Converse directly depends and which will be loaded in the browser as part of
the bundle in ``dist/converse.js`` (or ``dist/converse.min.js``).
To see the 3rd party dependencies (not just the front-end dependencies, but
also ones necessary for development tasks like making builds), take a look at
the list under the ``devDependencies`` in `package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
.. note::
After running ```make dev```, you should now have a new *node_modules* directory
which contains all the external dependencies of Converse.
If this directory does NOT exist, something must have gone wrong.
Double-check the output of ```make dev``` to see if there are any errors
listed. For support, you can ask in our chatroom: `dicuss@conference.conversejs.org <xmpp:discuss@conference.conversejs.org>`_.
If you don't have an XMPP client installed, follow this link to
`conversejs.org <https://conversejs.org/fullscreen#converse/room?jid=discuss@conference.conversejs.org>`_
where you can log in and be taken directly to the chatroom.
.. _`dependency-libsignal`:
Libsignal
---------
If you want OMEMO encryption, you need to load `libsignal <https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in your page.
For example::
<script src="3rdparty/libsignal-protocol-javascript/dist/libsignal-protocol.js"></script>
The reason libsignal needs to be loaded separately is because it's released
under the `GPLv3 <https://github.com/signalapp/libsignal-protocol-javascript/blob/master/LICENSE>`_
which requires all other dependent JavaScript code to also be open sourced under the same
license. You might not be willing to adhere to those terms, which is why you
need to decide for yourself whether you're going to load libsignal or not.
.. _`webserver`:
Setting up a webserver
======================
When making changes to Converse, either development or theming changes,
you'll want to preview them in your browser.
For this, you'll need to serve the development files via a web server,
so that you can see your local changes in the browser.
Manually starting a web server
------------------------------
To both set up the development environment and also start up a web browser to
serve the files for you, you can run::
make serve
.. note::
To run the "make" commands, you'll need `GNUMake <https://www.gnu.org/software/make>`_
installed on your computer. If you use GNU/Linux or \*BSD, it should be installed or
available via your package manager. For Mac, you'll need to install XCode and in
Windows you can use `Chocolatey <https://chocolatey.org/>`_.
After running ``make serve`` you can open http://localhost:8000 in your webbrowser to see the Converse website.
When developing or changing the theme, you'll want to load all the
unminified JS and CSS resources as separate files. To do this, open http://localhost:8000/dev.html instead.
You might want to open `dev.html <https://github.com/conversejs/converse.js/blob/master/dev.html>`_ in your text editor or IDE as well, to see
how ``converse.initialize`` is called and to potentially change any of the
settings.
Starting a web server with live reloading
-----------------------------------------
Alternatively, if you want to have live reloading whenever any of the source files change, you
can run ``make devserver`` (which will use `webpack-dev-server <https://github.com/webpack/webpack-dev-server>`_).
Instead of ``dev.html`` being used, `webpack.html <https://github.com/conversejs/converse.js/blob/master/webpack.html>`_
is now being used as the HTML template, and you'll need to modify that file if
you want to change the settings passed to ``converse.initialize``.
If you're running ``make devserver``, you need to open http://localhost:8080.

View File

@ -0,0 +1,32 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/development.rst">Edit me on GitHub</a></div>
.. _`development`:
===========
Development
===========
Welcome to the developer documentation of Converse.js.
Here you will learn how to add new features and how you can create your own
customized version of Converse.
Converse is a community project and largely volunteer driven.
We're grateful for your contributions, so please don't hesitate to
make a `Github pull request <https://help.github.com/categories/collaborating-with-issues-and-pull-requests/>`_
to fix a bug or to add new functionality.
.. toctree::
:maxdepth: 2
setup_dev_environment
plugin_development
api/index
testing
other_frameworks
builds
style_guide

View File

@ -0,0 +1,55 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/documentation.rst">Edit me on GitHub</a></div>
=====================
Writing Documentation
=====================
.. note:: Contributions to the documentation are much appreciated.
What is used to write the documentation?
========================================
This documentation is written in `Sphinx <http://sphinx-doc.org/>`_, a
documentation generator written in `Python <http://python.org>`_.
The documentation is written in `reStructuredText (reST) <http://sphinx-doc.org/rest.html>`_,
a very easy to write plain text format, relatively similar to Markdown.
So see what the source looks like, click the **Source** link in the footer of
this page.
Where is the documentation?
===========================
The reST documentation files are located in the
`converse.js code repository <https://github.com/jcbrand/converse.js/tree/master/docs/source>`_
under ``docs/source``.
How to generate HTML from the source files?
===========================================
Generate the HTML
-----------------
After installing the dependencies, you can generate the HTML by running::
make html
The HTMl files will be located in ``./docs/html``
What ``make html`` does for you is it installs `zc.buildout <http://www.buildout.org/en/latest/>`_
which is used to install Sphinx and all its dependencies.
You'll need to have Python and `Virtualenv <https://virtualenv.pypa.io/en/latest/>`_ available on your computer.
.. warning:: When contributing, please don't commit any generated html files.
Serving the documentation
-------------------------
To view the generated docs, you can run ``make serve`` and then open
http://localhost:8000/docs/html/index.html in your browser.

191
docs/source/features.rst Normal file
View File

@ -0,0 +1,191 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/features.rst">Edit me on GitHub</a></div>
.. _`features`:
========
Features
========
File sharing (`XEP-0363 HTTP File Upload <https://xmpp.org/extensions/xep-0363.html>`_)
=======================================================================================
Converse supports file sharing by first uploading the file to a file server and
then sending the file's URL to the recipient.
The file server that is used is configured by the XMPP server admin, and is not
something that Converse has any control over.
Often when people report file sharing not working, it's because the file server
is not configured to allow file uploads from other domains.
The file server needs to be configured for `Cross-Origin resource sharing <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`_
(known by the acronym CORS). Specifically, it needs to add a
``Access-Control-Allow-Origin`` header which includes the domain hosting
Converse.
.. _`feature-omemo`:
End to end message encryption (`XEP-0384 OMEMO <https://xmpp.org/extensions/xep-0384.html>`_)
=============================================================================================
.. note::
Converse versions older than 8.0.0 do NOT support encryption or decryption
of uploaded files. Files will be uploaded WITHOUT ENCRYPTION, even when
OMEMO is enabled.
.. note::
For end-to-end encryption via OMEMO, you'll need to load `libsignal-protocol.js
<https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in
your page. Take a look at the section on :ref:`libsignal <dependency-libsignal>` and the
:ref:`security considerations around OMEMO <feature-omemo>`.
Converse supports OMEMO encryption based on the
`Signal Protocol <https://github.com/signalapp/libsignal-protocol-javascript>`_.
The Signal Protocol is session-oriented. Clients establish a session, which is
then used for all subsequent encrypt/decrypt operations. There is no need to
ever tear down a session once one has been established.
This means that a session needs to be stored permanently after logging out.
Converse stores this session information in the browser's `IndexedDB <https://developer.mozilla.org/en-US/docs/Web/API/IndexedDB_API>`_
or `localStorage <https://developer.mozilla.org/en-US/docs/Web/API/Storage/LocalStorage>`_
database, depending on the value provided to :ref:`persistent-store`.
If you've checked the "This is not a trusted device" checkbox when logging in,
then `sessionStorage <https://developer.mozilla.org/en-US/docs/Web/API/Window/sessionStorage>`_
is used instead of localStorage and all data is cleared when you log out.
For this reason, OMEMO is disabled when you've indicated that you're using
an untrusted device. You would in any case not be able to decrypt previously
received OMEMO messages, due to the Signal Protocol's forward secrecy and the
fact that you don't have a pre-existing session.
Security considerations for browser-based crypto
------------------------------------------------
Crypto apps deployed via regular web hosting can be described as relying on
"host-based" security.
Host-based security services require you to trust the host every time you access
it, whereas with installable desktop software you trust the host when you
download/install the software (and whenever it gets updated).
The dynamic nature of "host-based" systems makes it impractical for security
researchers to do security audits because the hosted code can change at any
time.
In such a setup you need to fully trust the host that serves you the JavaScript code.
The host that serves the JavaScript code is not necessarily the same host that
stores and procesess your chat messages. So using OMEMO can still protect your
messages from snooping on the XMPP server where they're stored encrypted.
In other words, you do have to trust the webserver that hosts Converse for you,
but you don't necessarily have to trust the XMPP server (if it's on a different host),
because it never gets hold of your private key.
One way to improve this situation is to host Converse yourself, especially if
you host it locally on your own machine. If you're not able to do that, then
at least make sure you use a reputable host that serves files over HTTPS and
that set `CSP <https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/Content-Security-Policy>`_
headers.
Due to these reasons, it's NOT a good idea to use encrypted messaging with a
browser-based solution in life-threatening situations.
Security can be increased by using an installable app (like `Converse Desktop <https://github.com/conversejs/converse-desktop>`_).
For further reading on the challenges of web-based crypto, take a look at these
articles:
* `What's wrong with webcrypto? <https://tonyarcieri.com/whats-wrong-with-webcrypto>`_
* `Heartbleed and JavaScript crypto <https://tankredhase.com/2014/04/13/heartbleed-and-javascript-crypto/>`_
OMEMO in Multi-user chats (MUC)
-------------------------------
Converse supports OMEMO encryption in groupchats, but only if the groupchat is
set to `members only` and `non-anonymous`. This is the same criteria used by
the popular Android XMPP client `Conversations <https://conversations.im/>`_.
If the groupchat is configured properly, you'll see the lock icon in the
toolbar.
Open chats via URL
==================
From version 3.3.0, converse.js now has the ability to open chats (private or
groupchat) based on the URL fragment.
A room (aka groupchat) can be opened with a URL fragment such as `#converse/room?jid=room@domain`
and a private chat with a URL fragment such as
`#converse/chat?jid=user@domain`.
Notifications
=============
From version 0.8.1 Converse can play a sound notification when you receive a
message.
For more info, refer to the :ref:`play-sounds` configuration setting.
It can also show `desktop notification messages <https://developer.mozilla.org/en-US/docs/Web/API/notification>`_
when the browser is not currently visible.
For more info, refer to the :ref:`show-desktop-notifications` configuration setting.
Multilingual Support
====================
Converse is translated into over 30 languages. Translations can be added or
updated on `Weblate <https://hosted.weblate.org/projects/conversejs/>`_.
Translations are supplied in JSON format and are loaded on demand. Converse will expect to find the
translations in the ``/dist/locales`` path of your site. This path can be
changed via the :ref:`assets_path` configuration setting.
Moderating chatrooms
====================
Here are the different commands that may be used to moderate a chatroom:
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| Event Type | When is it triggered? | Example (substitue $nickname with an actual user's nickname) |
+============+==============================================================================================+===============================================================+
| **ban** | Ban a user from the chatroom. They will not be able to join again. | /ban $nickname |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **clear** | Clear the messages shown in the chatroom. | /clear |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **deop** | Make a moderator a normal occupant. | /deop $nickname [$reason] |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **help** | Show the list of available commands. | /help |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **kick** | Kick a user out of a room. They will be able to join again. | /kick $nickname [$reason] |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **me** | Speak in the 3rd person. | /me $message |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **mute** | Remove a user's ability to post messages to the room. They will still be able to observe. | /mute $nickname [$reason] |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **nick** | Change your nickname. | /nick $nickname |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **op** | Make a normal occupant a moderator. | /op $nickname [$reason] |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **topic** | Set the topic of the chatroom. | /topic ${topic text} |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
| **voice** | Allow a muted user to post messages to the room. | /voice $nickname [$reason] |
+------------+----------------------------------------------------------------------------------------------+---------------------------------------------------------------+
Passwordless login with client certificates
===========================================
Converse supports the SASL-EXTERNAL authentication mechanism, which can be
used together with x509 client certificates to enable passwordless login or
even 2-factor authentication.
For more info, `read this blog post <https://opkode.com/blog/strophe_converse_sasl_external/>`_.

Binary file not shown.

After

Width:  |  Height:  |  Size: 81 KiB

View File

@ -0,0 +1 @@
<mxfile userAgent="Mozilla/5.0 (Macintosh; Intel Mac OS X 10.12; rv:55.0) Gecko/20100101 Firefox/55.0" version="7.3.5" editor="www.draw.io" type="device"><diagram name="Page-1" id="e3a06f82-3646-2815-327d-82caf3d4e204">7Vtbc5s4FP41ntl9KKMLuj3GTi8P6Wx28tDuU0cG2abFyAMkcfrrVwJhA8Kxk+Jsmll3xrWOhCS+8+k7R4JM8Gy9/ZjLzeqzjlU6QSDeTvDlBCEREvNtDQ+1gQhQG5Z5EtcmuDfcJD+VMzbNbpNYFZ2GpdZpmWy6xkhnmYrKjk3mub7vNlvotDvqRi6VZ7iJZNpYA7K3f0nicuXskIp9xSeVLFducI5YXTGX0Y9lrm8zN2KmM1XXrGXTjbvLYiVjfd8y4fcTPMu1Lutf6+1MpRbXBrPmuvKhmegET1flOjUFaH5W1R8OXAxPudjcV66ysj3cof6oZDFfYKQAjgVm4B1x0NzJ9LYZoT/k/Sop1c1GRrZ8b7jTncMiSdOZTnVetcbvL+0/a9dZ6VgCQ1Muylz/UE3LCmI8vVN5mRgfXqTJMjPmUm8Gb8sBYZurbcvkbvOj0mtV5g+miaslDS0dm6lw7LjfMwNh12bVIoW51HHS8XG563sPrPnhsD3gNzY2rIvFAkXRUVhNy5jOKaFHsPWAHID7ILYo7GIbNkrRwpaSAWwhx7+O7Y4Lo2EbE8Xj8BRsOZpjelZsGe3zlvq8ZefC1tcH7oE905m5w0IF34sJoqkZfjrPza9lWSFA5dpCkc0L+19+m2VJtrRDZHZu9kbU3EquFXyV/6rnpOKL46viUbGpLnUTACMoD6Ss40FGoedBDAc8iCE/gwcx9TBWsQmcruigqYKfiisIOoAXpcx3yNo6lcXt4ndVlg/OIG9LbUw6L1d6qTOZXmmLcO24noNMNxc26O+nYCwfEntf1RRqBzZhHFX1Boqvrroq/GMLQWiI7wzXKk8MYip3rQ56s9C3eaQOINYkLzJfqsY1tckC9ygFcpXKMrnr5ilD7nSXXuvEzGxHHYp61OEwYEBAgNxXt8N6hq6PHkV2k3oea3yNnaWJcuO0udSsqSs5V+m1LpIy0XZtzXVZ6rXxgSw2dba3SLaWYG1yDS/IwbVr8q6NHXK9XdrsNYiSMk+2QSo35qJvyJcGSqfog0FkatrHduqtOgAonc0GWDnC8kfAUFK0Ph2PcuSnISZB9cWA02CEPMRXA/ZG1OCkpU38lcz+o5UscBBCRriov15uJdPfZCVvYvmKFnGIAwJaH9rxpqDYD+kDEZ0+wpvnL2H+RpbwPqAHzHWxC+pmt3YgpqttUtYXEcBcub4GYOjKz8oDmC8W4oXEgpKuWIS9LuppevLgddTfPDBGA0AoRYLjEJEQnUt1sCcyX7pZvr9PeF3q00x0lD0c7rmBY+HJRcia+N4WDIbGiPrkf2884g0Rhi/qDf8oqPbGjcrvBjbAh6CvUXwK7jtnPQX6SEYr9a2o5zZOPE57d5LXCE+lm2eqFuU4riZ9IWX+1rsxtR0t2BiO9o9Sp3/dfDIWg5DpOTXxKKvCRGqnbEhQ6OiHCTVHD1H+UEm5slQxPJFZLNPqeHq267moQbKBQC9sCFuZavD18/W1vaRy5Z+vjWf3al6xLLHhd7rSefLT0EY2Y/Q5ExkGVIRsSLMzjKEQpEsbwgbOM/FAegd+nTTQF2vnuNepD43fKuxP91JbE8hIi713Cr0rtxc7HdJ1MYbf3syx2i6fFoB08mncFIfT6V5WfDS/dvLYzq9r8o+eT2OBAoEYEUiQUAgAcZcoorf7PjW9Nv12O0I9Io2XUEM/mFxdXlw3kn8RVfAgcJnkZr1rx90X1Ykq5NvPYbGIm9m1EoqeELxccsB4b3M0cC5PB9SC8zGSg4HnwL+7XhDMW3rxzmzA4aENeGurL0LY2+rjI+f3TxUa+HJKw/vPenCPKqdKC4Xdjuj5pGVgs+5R84nPpnmkTns2PeckJODgHnGMrAB2czkxkBXsFuP4z6ZDD9upNEl+Fk+aB59ys0nNnVdy98q23Z3c7hwZG4dd3wzk2efL2JpjkTekwLijwCDgHB0XYIJwV4ABQuMK8MBJar0wRtffsPeWD+c9opysvwgPU/MM+uu/UnHz95UxfFZFYd9xM+ldHq2q/O517f1iWcq5LNQJadxZ9+uM9HZ+1NeREA3pCBlBR7D/Ut5vqiN7TeCkKwkHn76cLggvkH2xsJs0Ef7c7AscINQZnpS8tSgEA0BwJwqZGH48CoH+Ez9MxLhRCPs8ZOcJQgAEvaQTsABCATiBZkcAmrOip9KSsO7LI4zZlQpESDGzpxH8bCR9e4dbIes+LBYncJTTXqYEx2Xo0Eb1TIkS6b+H1GxcnyyVuJco9TOuEVn4tt5VOs6O0b2OGO4rk4ABwYTBEPHq+3kswESciQWmuP9jirr5/q9V8Pt/AQ==</diagram></mxfile>

54
docs/source/index.rst Normal file
View File

@ -0,0 +1,54 @@
.. Converse documentation master file, created by
sphinx-quickstart on Fri Apr 26 20:48:03 2013.
You can adapt this file completely to your liking, but it should at least
contain the root `toctree` directive.
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/index.rst">Edit me on GitHub</a></div>
======================
Converse Documentation
======================
Preface
=======
This is the official documentation for Converse. If you'd like to
contribute, please read the :doc:`documentation` page.
Introduction
============
Converse is a free and open-source `XMPP <https://xmpp.org/about-xmpp/>`_
chat client written in JavaScript which can be tightly integrated into any website.
The benefit of using converse.js as opposed to relying on a SaaS
(software-as-a-service) solution, is that your users can have a much more
customized, streamlined and integrated webchat experience and that you have
control over the data. The latter being a requirement for many sites dealing
with sensitive information.
You'll likely want users who are authenticated on your website, to also
automatically be authenticated on the XMPP server. In order to do this, you'll
have to add some server-side code for your website.
The :ref:`what-you-will-need` and :ref:`session-support` sections provide more information on how to achieve this.
Table of Contents
=================
.. toctree::
:maxdepth: 2
quickstart
features
setup
session
configuration
development
theming
security
translations
troubleshooting
documentation

View File

@ -0,0 +1,59 @@
# The Converse API documentation
Welcome to the new Converse API documentation, generated with
[JSDoc](http://usejsdoc.org/).
## The public and private API
Converse has a public API and a private API only available to plugins.
The reason we make this distinction between public and private is so that API
methods which could be used to "impersonate" the user, for example by
sending messages on their behalf, are not available to random scripts running
in your website.
The public API is accessible via the [window.converse](/docs/html/api/converse.html)
global and is therefore available to any JavaScript running in the page.
The private API is only accessible to plugins, which have been whitelisted and
registered before [converse.initialize](/docs/html/api/converse.html#.initialize)
(which is a public API method) has been called.
See the [plugin development](/docs/html/plugin_development.html)
section for more info on writing plugins.
Inside a plugin, you can get access to the {@link _converse.api}
object. Note the underscore in front of {@link _converse},
which indicates that this is a private, closured object.
## API Namespaces
The Converse API (private and public) makes use of namespaces to logically
group relevant methods.
So, for example, all the XEP-0030 service discovery methods are under the
{@link \_converse.api.disco} namespace, in the [private API]{@link \_converse.api}.
Which means that you access it via {@link _converse.api.disco}.
### Nested Namespaces
Namespaces can be nested.
{@link _converse.api} is the top-level namespace, of which {@link \_converse.api.disco}
is a nested, child namespace and {@link \_converse.api.disco.own} is nested another
level deeper.
Not all methods are however within a namespace. For example {@link converse.initialize}.
## Stable API versus unstable API
Converse uses [semantic versioning](https://semver.org/) for releases, which means that
we try to maintain a stable API for minor and patch releases and when we do change the
stable API we will make a major release.
In the JSDoc API documentation, all API methods that are **not** marked as *Private*
are considered to be part of the stable API, and you can therefore expect them to
not change between minor and patch releases. If a method is marked as *Private*,
then you could still use it, but we don't provide any guarantee that it won't change
between minor and patch releases.

View File

@ -0,0 +1,140 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/other_frameworks.rst">Edit me on GitHub</a></div>
Integrating converse.js into other frameworks
=============================================
Angular.js
----------
Angular.js has the concept of a `service <https://docs.angularjs.org/guide/services#!>`_,
which is a special kind of `provider <https://docs.angularjs.org/guide/providers>`_.
An angular.js service is a constructor or object which provides an API defined by the
author of the service. The goal of a service is to organize and share code, so
that it can be used across an application.
So, if we wanted to properly integrate converse.js into an angular.js
application, then putting it into a service is a good approach.
This lets us avoid having a global ``converse`` API object (accessible via
``windows.converse``), and instead we can get hold of the converse API via
angular's dependency injection when we specify it as a dependency for our
angular components.
Below is an example code that wraps converse.js as an angular.js service.
.. code-block:: javascript
angular.module('converse', []).service('converse', function() {
// We create three promises, which will be resolved at various times
var loaded_deferred = new $.Deferred(),
connected_deferred = new $.Deferred();
var service = {
'waitUntilLoaded': _.constant(loaded_deferred.promise()),
'initialize': function initConverse(options) {
this.waitUntilLoaded().done(_.partial(this.api.initialize, options));
},
'waitUntilConnected': _.constant(connected_deferred.promise())
};
// Here we define the core components of converse.js that will be
// loaded and used.
define([
"converse-core",
// START: Removable components
// --------------------
// Any of the following components may be removed if they're not needed.
"locales", // Translations for converse.js. This line can be removed
// to remove *all* translations, or you can modify the
// file src/locales.js to include only those
// translations that you care about.
"converse-chatview", // Renders standalone chatboxes for single user chat
"converse-controlbox", // The control box
"converse-bookmarks", // XEP-0048 Bookmarks
"converse-mam", // XEP-0313 Message Archive Management
"converse-muc", // XEP-0045 Multi-user chat
"converse-vcard", // XEP-0054 VCard-temp
"converse-register", // XEP-0077 In-band registration
"converse-ping", // XEP-0199 XMPP Ping
"converse-notification", // HTML5 Notifications
"converse-minimize", // Allows chatboxes to be minimized
"converse-dragresize", // Allows chatboxes to be resized by dragging them
"converse-headline", // Support for headline messages
// END: Removable components
], function(converse) {
service.api = converse;
// Register a plugin which resolves `waitUntilConnected` promise.
converse.plugins.add('conversejs-angular-service', {
initialize: function () {
this._converse.api.listen.on('connected', connected_deferred.resolve);
}
});
// Converse.js has been loaded, so we can resolve the `waitUntilLoaded` promise.
return loaded_deferred.resolve();
});
require(["converse"]);
return service;
});
The above code is a modified version of the file `src/converse.js <https://github.com/jcbrand/converse.js/blob/master/src/converse.js>`_
which defines the converse AMD module and specifies which plugins will go into
this build.
You should replace the contents of that file with the above, if you want such a
service registered. Then, you should run `make build`, to create new build
files in the `dist` directory, containing your new angular.js service.
The above code registers an angular.js module and service, both named ``converse``.
This module should then be added as a dependency for your own angular.js
modules, for example:
.. code-block:: javascript
angular.module('my-module', ['converse']);
Then you can have the converse service dependency injected into
your components, for example:
.. code-block:: javascript
angular.module('my-module').provider('my-provider', function(converse) {
// Your custom code can come here..
// Then when you're ready, you can initialize converse.js
converse.waitUntilLoaded().done(function () {
converse.initialize({
'allow_logout': false,
'auto_login': 'true',
'auto_reconnect': true,
'bosh_service_url': bosh_url,
'jid': bare_jid,
'credentials_url': credentials_url,
'whitelisted_plugins': ['conversejs-angular-service']
});
// More custom code could come here...
});
});
You might have noticed the ``waitUntilLoaded()`` method being called on the ``converse``
service. This is a special method added to the service (see the implementation
example above) that makes sure that converse.js is loaded and available. It
returns a promise which resolves once converse.js is available.
This is necessary because with otherwise you might run into race-conditions
when your angular application loads more quickly then converse.js.
Lastly, the API of converse is available via the ``.api`` attribute on the service.
So you can call it like this for example:
.. code-block:: javascript
converse.api.user.status.set('online');

View File

@ -0,0 +1,640 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/plugin_development.rst">Edit me on GitHub</a></div>
.. _`writing-a-plugin`:
Writing a plugin
================
Introduction
------------
Converse.js has a plugin architecture based on `pluggable.js <https://github.com/jcbrand/pluggable.js/>`_
and is itself composed out of plugins.
There are only a few files that are included in the default build of Converse
which aren't plugins.
An important one is `core.js <https://github.com/conversejs/.js/blob/master/src/headless/core.js>`_,
which is responsible for bootstrapping the plugin architecture,
setting up and maintaining the connection to the XMPP
server and declaring the public (`window.converse </docs/html/api/converse.html>`_) and protected (`_converse.api </docs/html/api/-_converse.api.html>`_) APIs.
The other non-plugin files all contain utility methods in
`src/utils <https://github.com/conversejs/converse.js/blob/master/src/utils>`_ and
`src/headless/utils <https://github.com/conversejs/converse.js/blob/master/src/headless/utils>`_.
As a general rule, any file in the ``./src`` directory that starts with
``converse-`` is a plugin (with the exception of ``converse-core.js``.
The plugin architecture lets you add new features or modify existing functionality in a
modular and self-contained way, without having to change other files.
This ensures that plugins are fully optional (one of the design goals of
Converse) and can be removed from the main build without breaking the app.
For example, the ``converse-omemo``,
``converse-rosterview``, ``converse-dragresize``, ``converse-minimize``,
``converse-muc`` and ``converse-muc-views`` plugins can all be removed from the
build without breaking the app.
To more deeply understand how the plugin architecture works, read the
`pluggable.js documentation <https://jcbrand.github.io/pluggable.js/>`_
and to understand its inner workings, refer to the `annotated source code
<https://jcbrand.github.io/pluggable.js/docs/pluggable.html>`_.
Advantages of plugins
---------------------
Writing a plugin is the recommended way to customize or add new features to Converse.
The main benefit of plugins is that they allow for **isolation of concerns** (and features).
From this benefit flows various 2nd order advantages, such as the ability to
make smaller production builds (by excluding unused plugins) and an easier
upgrade path by avoiding touching Converse's internals.
Plugins are especially useful if you want to add proprietary modifications, since the
Mozilla Public License version 2 doesn't require you to open source your
plugin files. Be aware that this doesn't apply when you intend to use libsignal for
OMEMO encryption because libsignal's license is GPLv3 (and turns the entire app
into a GPLv3 app).
Each plugin comes in its own file, and Converse's plugin architecture,
`pluggable.js <https://github.com/jcbrand/pluggable.js/>`_, provides you
with the ability to "hook in" to the core code and other plugins.
Plugins enable developers to extend and override existing objects,
functions and the models and views that make up
Converse. You can also create new models and views.
.. note:: **Trying out a plugin in JSFiddle**
Because Converse consists only of JavaScript, HTML and CSS (with no backend
code required like PHP, Python or Ruby) it runs fine in JSFiddle.
Here's a Fiddle with a Converse plugin that calls ``alert`` once it gets
initialized and also when a chat message gets rendered: https://jsfiddle.net/4drfaok0/15/
.. note:: **Generating a plugin with Yeoman**
The rest of this document explains how to write a plugin for Converse and
ends with a documented example of a plugin.
There is a `Yeoman <http://yeoman.io/>`_ code generator, called
`generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_, which
you can use to generate plugin scaffolding/boilerplate that serves as a
starting point and basis for writing your plugin.
Please refer to the `generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_
README for information on how to use it.
Registering a plugin
--------------------
Plugins need to be registered (and whitelisted) before they can be loaded and
initialized.
You register a Converse plugin by calling ``converse.plugins.add``.
The plugin itself is a JavaScript object which usually has at least an
``initialize`` method, which gets called at the end of the
``converse.initialize`` method which is the top-level method that gets called
by the website to configure and initialize Converse itself.
Here's an example code snippet:
.. code-block:: javascript
converse.plugins.add('myplugin', {
initialize: function () {
// This method gets called once converse.initialize has been called
// and the plugin itself has been loaded.
// Inside this method, you have access to the closured
// _converse object as an attribute on "this".
// E.g. this._converse
},
});
.. note:: It's important that `converse.plugins.add` is called **before**
`converse.initialize` is called. Otherwise the plugin will never get
registered and never get called.
Whitelisting of plugins
-----------------------
As of Converse 3.0.0 and higher, plugins need to be whitelisted before they
can be used. This is because plugins have access to a powerful API. For
example, they can read all messages and send messages on the user's behalf.
To avoid malicious plugins being registered (i.e. by malware infected
advertising networks) we now require whitelisting.
To whitelist a plugin simply means to specify :ref:`whitelisted_plugins` when
you call ``converse.initialize``.
If you're adding a "core" plugin, which means a plugin that will be
included in the default, open-source version of Converse, then you'll
instead whitelist the plugin by adding its name to the `core_plugins` array in
`./src/headless/converse-core.js <https://github.com/jcbrand/converse.js/blob/master/src/headless/converse-core.js>`_.
or the `WHITELISTED_PLUGINS` array in `./src/converse.js <https://github.com/jcbrand/converse.js/blob/master/src/converse.js>`_.
Where you add it depends on whether your plugin is part of the headless build
(which means it doesn't contain any view code) or not.
Security and access to the inner workings
-----------------------------------------
The globally available ``converse`` object, which exposes the API methods, such
as ``initialize`` and ``plugins.add``, is a wrapper that encloses and protects
a sensitive inner object, named ``_converse`` (not the underscore prefix).
This inner ``_converse`` object contains all the models and views,
as well as various other attributes and functions.
Within a plugin, you will have access to this internal
`"closured" <https://developer.mozilla.org/en-US/docs/Web/JavaScript/Closures>`_
``_converse`` object, which is normally not exposed in the global variable scope.
The inner ``_converse`` object is made private in order to safely hide and
encapsulate sensitive information and methods which should not be exposed
to any 3rd-party scripts that might be running in the same page.
Accessing 3rd party libraries
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Immediately inside the module shown above you can access 3rd party libraries (such
dayjs) via the ``converse.env`` map.
The code for it could look something like this:
.. code-block:: javascript
// Commonly used utilities and variables can be found under the "env"
// namespace of the "converse" global.
const { Promise, Strophe, dayjs, sizzle, $build, $iq, $msg, $pres } = converse.env;
These dependencies are closured so that they don't pollute the global
namespace, that's why you need to access them in such a way inside the module.
Overriding templates
--------------------
Converse uses `lit-html <https://lit-html.polymer-project.org/guide>`_
templates and templates are imported as separate files.
It's possible to configure your module bundler (e.g. Webpack) in such as way that a
different file is loaded when a template is imported.
This allows you to create your own templates that are used instead of the ones
that would have originally been imported.
With Webpack (which Converse uses internally), you can specify an
``alias`` for the template you want to override. This alias then points to your
own custom template.
For example, in your webpack config file, you could add the following to the
``config`` object that gets exported:
.. code-block:: javascript
resolve: {
extensions: ['.js'],
modules: [
path.join(__dirname, 'node_modules'),
path.join(__dirname, 'node_modules/converse.js/src')
],
alias: {
'plugins/profile/templates/profile.js$': path.resolve(__dirname, 'templates/custom-profile.js')
}
}
This will override the template that gets imported at the path ``plugins/profile/templates/profile.js``
with your own template at the path ``templates/custom-profile.js`` (relative to your webpack config file).
Object and class Overrides
--------------------------
.. note:: Using the `overrides` feature from pluggable.js is discouraged. It's
much better to use events, promises and `hooks`_ to modify the behaviour of
Converse.
The pluggable.js `overrides` will only work on objects and classes that are
set as attributes on the `_converse` object, which doesn't apply to many
newer classes and objects, such as the web components. For these clasess,
overrides won't work at all.
This section is left here for completeness, because in some special cases
overrides are still used.
Plugins can override core code or code from other plugins. You can specify
overrides in the object passed to ``converse.plugins.add``.
In an override you can still call the overridden function, by calling
``this.__super__.methodName.apply(this, arguments);`` where ``methodName`` is
the name of the function or method you're overriding.
The following code snippet provides an example of two different overrides:
.. code-block:: javascript
overrides: {
/* The *_converse* object has a method "onConnected".
* You can override that method as follows:
*/
onConnected: function () {
// Overrides the onConnected method in Converse
// Top-level functions in "overrides" are bound to the
// inner "_converse" object.
const _converse = this;
// Your custom code can come here ...
// You can access the original function being overridden
// via the __super__ attribute.
// Make sure to pass on the arguments supplied to this
// function and also to apply the proper "this" object.
_converse.__super__.onConnected.apply(this, arguments);
// Your custom code can come here ...
},
/* On the XMPPStatus model is a method sendPresence.
* We can override is as follows:
*/
XMPPStatus: {
sendPresence: function (type, status_message, jid) {
// The "_converse" object is available via the __super__
// attribute.
const _converse = this.__super__._converse;
// Custom code can come here ...
// You can call the original overridden method, by
// accessing it via the __super__ attribute.
// When calling it, you need to apply the proper
// context as reference by the "this" variable.
this.__super__.sendPresence.apply(this, arguments);
}
}
}
Use the ``overrides`` feature with caution. It basically resorts to
monkey patching which pollutes the call stack and can make your code fragile
and prone to bugs when Converse gets updated. Too much use of ``overrides``
is therefore a "code smell" which should ideally be avoided.
A better approach is to use the events and `hooks`_ emitted by Converse, and to add
your code in event handlers. This is however not always possible, in which case
the overrides are a powerful tool.
Also, while it's possible to add new methods to classes via the ``overrides``
feature, it's better and more explicit to use composition with
``Object.assign``.
For example:
.. code-block:: javascript
function doSomething () {
// Your code comes here
}
Object.assign(_converse.ChatBoxView.prototype, { doSomething });
.. _`dependencies`:
Plugin dependencies
-------------------
When using ``overrides``, the code that you want to override (which is either
in ``converse-core`` or in other plugins), needs to be parsed already by the
time your ``overrides`` are being parsed.
Additionally, when you register event or promise handlers in your plugin for
events/promises that fire in other plugins, then you want those plugins to have
been loaded before your plugin gets loaded.
To resolve this problem we have the ``dependencies`` Array attribute.
With this you can specify those dependencies which need to be loaded before
your plugin is loaded.
In some cases, you might want to depend on another plugin if it's available,
but don't care when it's not available.
An example is the `converse-dragresize <https://github.com/jcbrand/converse.js/blob/master/src/converse-dragresize.js>`_
plugin, which will add drag-resize handles to the headlines box (which shows
messages of type ``headline``) but doesn't care when that particular plugin is
not available.
If the :ref:`strict_plugin_dependencies` setting is set to ``false`` (which is
its default value), then no error will be raised if the plugin is not found.
In this case, you can't specify the plugin as a dependency in the ``define``
statement at the top of the plugin, since it might not always be available,
which would cause ``require.js`` to throw an error.
Extending Converse's configuration settings
----------------------------------------------
Converse comes with various :ref:`configuration-settings` that can be used to
modify its functionality and behavior.
All configuration settings have default values which can be overridden when
`converse.initialize` (see `converse.initialize </docs/html/api/converse.html#.initialize>`_)
gets called.
Plugins often need their own additional configuration settings and you can add
these settings with the `_converse.api.settings.update </docs/html/api/-_converse.api.settings.html#.update>`_
method.
Exposing promises
-----------------
Converse has a `waitUntil </docs/html/api/-_converse.api.html#.waitUntil>`_ API method
which allows you to wait for various promises to resolve before executing a
piece of code.
You can add new promises for your plugin by calling
`_converse.api.promises.add </docs/html/api/-_converse.api.promises.html#.add>`_.
Generally, your plugin will then also be responsible for making sure these
promises are resolved. You do this by calling
`_converse.api.trigger </docs/html/api/-_converse.api.html#.trigger>`_, which not
only resolves the plugin but will also emit an event with the same name.
Dealing with asynchronicity
---------------------------
Due to the asynchronous nature of XMPP, many subroutines in Converse execute
at different times and not necessarily in the same order.
In many cases, when you want to execute a piece of code in a plugin, you first
want to make sure that the supporting data-structures that your code might rely
on have been created and populated with data.
There are two ways of waiting for the right time before executing your code.
You can either listen for certain events, or you can wait for promises to
resolve.
For example, when you want to query the message archive between you and a
friend, you would call ``this._converse.api.archive.query({'with': 'friend@example.org'});``
However, simply calling this immediately in the ``initialize`` method of your plugin will
not work, since the user is not logged in yet.
In this case, you should first listen for the ``connection`` event, and then do your query, like so:
.. code-block:: javascript
converse.plugins.add('myplugin', {
initialize: function () {
const _converse = this._converse;
_converse.api.listen.on('connected', function () {
_converse.api.archive.query({'with': 'admin2@localhost'});
});
}
});
Another example is in the ``Bookmarks`` plugin (in
`src/converse-bookmarks.js <https://github.com/jcbrand/converse.js/blob/6c3aa34c23d97d679823a64376418cd0f40a8b94/src/converse-bookmarks.js#L528>`_).
Before bookmarks can be fetched and shown to the user, we first have to wait until
the `"Rooms"` panel of the ``ControlBox`` has been rendered and inserted into
the DOM. Otherwise we have no place to show the bookmarks yet.
Therefore, there are the following lines of code in the ``initialize`` method of
`converse-bookmarks.js <https://github.com/jcbrand/converse.js/blob/6c3aa34c23d97d679823a64376418cd0f40a8b94/src/converse-bookmarks.js#L528>`_:
.. code-block:: javascript
Promise.all([
_converse.api.waitUntil('chatBoxesFetched'),
_converse.api.waitUntil('roomsPanelRendered')
]).then(initBookmarks);
What this means, is that the plugin will wait until the ``chatBoxesFetched``
and ``roomsPanelRendered`` promises have been resolved before it calls the
``initBookmarks`` method (which is defined inside the plugin).
This way, we know that we have everything in place and set up correctly before
fetching the bookmarks.
As yet another example, there is also the following code in the ``initialize``
method of the plugin:
.. code-block:: javascript
_converse.api.listen.on('chatBoxOpened', function renderMinimizeButton (view) {
// Inserts a "minimize" button in the chatview's header
// Implementation code removed for brevity
// ...
});
In this case, the plugin waits for the ``chatBoxOpened`` event, before it then
calls ``renderMinimizeButton``, which adds a new button to the chatbox (which
enables you to minimize it).
Finding the right promises and/or events to listen to, can be a bit
challenging, and sometimes it might be necessary to create new events or
promises.
Please refer to the `API documentation </docs/html/api/http://localhost:8008/docs/html/api/>`_
for an overview of what's available to you. If you need new events or promises, then
`please open an issue or make a pull request on Github <https://github.com/jcbrand/converse.js>`_
Hooks
-----
Converse has the concept of ``hooks``, which are special events that allow you
to modify it's behaviour at runtime.
A hook is similar to an event, but it differs in two meaningful ways:
1. Converse will wait for all handlers of a hook to finish before continuing inside the function from where the hook was triggered.
2. Each hook contains a payload, which the handlers can modify or extend, before returning it (either to the function that triggered the hook or to subsequent handlers).
These two properties of hooks makes it possible for 3rd party plugins to
intercept and update data, allowing them to modify Converse without the need of
resorting to `overrides`_.
A hook is triggered in the following way:
.. code-block:: javascript
async function hookTriggerExample () {
const payload = { foo: 'bar' };
const updated_payload = await api.hook('hookName', this, payload);
return updated_payload;
}
The above could be shortened:
.. code-block:: javascript
async function hookTriggerExample () {
return await api.hook('hookName', this, { foo: 'bar' });
}
The ``async/await`` syntax could also be removed, but then it's less clear to
the reader that this function returns a promise.
Let's assume that in a plugin somewhere a listener is registered for this hook:
.. code-block:: javascript
function hookListenerExample () {
api.listen.on('hookname', (context, payload) => {
return {...payload, 'baz': 'buzz'};
});
}
The ``context`` parameter in our listener is usually the ``this`` of the function
that triggered the hook (as is the case in ``hookTriggerExample``),
but could also be a ``Model`` instance.
The ``payload`` parameter is the same payload that was passed in in
``hookTriggerExample``.
The ``hookListenerExample`` function accepts the payload and returns a new one
which contains the original payload together with a new key and value.
The ``updated_payload`` that is now returned from ``hookTriggerExample`` looks
as follows:
::
{ foo: 'bar', bazz: 'buzz' }
Our plugin was able to add data to the payload without requiring any kind of
knowledge from ``hookTriggerExample`` about ``hookListenerExample`` and
without any kind of coupling betwee the code.
A good example of a real-world hook in Converse, is the
`getMessageActionButtons <https://conversejs.org/docs/html/api/-_converse.html#event:getMessageActionButtons>`_
which allows you to add, modify or delete the actions you can take on a message
in a chat.
The `Actions <https://github.com/conversejs/community-plugins/tree/master/packages/actions>`_
3rd party community plugin makes use of this hook to add extra actions such as
``like`` or ``dislike`` to chat messages.
An example plugin
-----------------
Below follows a documented example of a plugin. This is the same code that gets
generated by `generator-conversejs <https://github.com/jcbrand/generator-conversejs>`_.
.. code-block:: javascript
import converse from "@converse/headless/converse-core";
// Commonly used utilities and variables can be found under the "env"
// namespace of the "converse" global.
const { Promise, Strophe, dayjs, sizzle, _, $build, $iq, $msg, $pres } = converse.env;
// The following line registers your plugin.
converse.plugins.add("myplugin", {
/* Dependencies are other plugins which might be
* overridden or relied upon, and therefore need to be loaded before
* this plugin. They are "optional" because they might not be
* available, in which case any overrides applicable to them will be
* ignored.
*
* NB: These plugins need to have already been imported or loaded,
* either in your plugin or somewhere else.
*
* It's possible to make these dependencies "non-optional".
* If the setting "strict_plugin_dependencies" is set to true,
* an error will be raised if the plugin is not found.
*/
dependencies: [],
/* Converse's plugin mechanism will call the initialize
* method on any plugin (if it exists) as soon as the plugin has
* been loaded.
*/
initialize: function () {
/* Inside this method, you have access to the private
* `_converse` object.
*/
const _converse = this._converse;
_converse.log("The \"myplugin\" plugin is being initialized");
/* From the `_converse` object you can get any configuration
* options that the user might have passed in via
* `converse.initialize`.
*
* You can also specify new configuration settings for this
* plugin, or override the default values of existing
* configuration settings. This is done like so:
*/
_converse.api.settings.update({
'initialize_message': 'Initializing myplugin!'
});
/* The user can then pass in values for the configuration
* settings when `converse.initialize` gets called.
* For example:
*
* converse.initialize({
* "initialize_message": "My plugin has been initialized"
* });
*/
alert(this._converse.initialize_message);
/* Besides `_converse.api.settings.update`, there is also a
* `_converse.api.promises.add` method, which allows you to
* add new promises that your plugin is obligated to fulfill.
*
* This method takes a string or a list of strings which
* represent the promise names:
*
* _converse.api.promises.add('myPromise');
*
* Your plugin should then, when appropriate, resolve the
* promise by calling `_converse.api.trigger`, which will also
* trigger an event with the same name as the promise.
* For example:
*
* _converse.api.trigger('operationCompleted');
*
* Other plugins can then either listen for the event
* `operationCompleted` like so:
*
* _converse.api.listen.on('operationCompleted', function { ... });
*
* or they can wait for the promise to be fulfilled like so:
*
* _converse.api.waitUntil('operationCompleted', function { ... });
*/
/* In your plugin, you can also listen for hooks.
* Hooks allow you to add or modify data and properties used by
* Converse.
*
* For example, the getToolbarButtons hook allows you to add new buttons to the chat toolbar.
* https://conversejs.org/docs/html/api/-_converse.html#event:getToolbarButtons
*/
api.listen.on('getToolbarButtons', (toolbar_el, buttons) => {
buttons.push(html`
<button class="my-button" @click=${alert('hello world!')}>
<converse-icon class="fa fa-eye" size="1em" color="blue"></converse-icon>
</button>
`);
return buttons;
});
}
});

159
docs/source/quickstart.rst Normal file
View File

@ -0,0 +1,159 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/quickstart.rst">Edit me on GitHub</a></div>
==========
Quickstart
==========
Getting a demo up and running
=============================
You can try out the latest version of Converse at `conversejs.org <https://conversejs.org>`_
for the overlayed version and `conversejs.org/fullscreen.html <https://conversejs.org/fullscreen.html>`_
for the full page version.
If you want to host and serve Converse yourself, there are a few options available.
Let your XMPP server serve Converse for you
-------------------------------------------
If you run your own XMPP server, you might first want to check whether it has
a plugin or module for hosting Converse.
* `Openfire <http://www.igniterealtime.org/projects/openfire/>`_ has the `inverse <https://www.igniterealtime.org/projects/openfire/plugin-archive.jsp?plugin=inverse>`_ plugin.
* `Prosody <https://prosody.im/>`_ has `mod_conversejs <https://modules.prosody.im/mod_conversejs.html>`_.
* `ejabberd <http://www.ejabberd.im/>`_ has `mod_conversejs <https://docs.ejabberd.im/admin/configuration/modules/#mod-conversejs>`_.
Serving Converse yourself
-------------------------
Alternative you can serve only Converse without requiring any particular XMPP server.
To do so, you'll need to get the right files to host, for which you have four options.
.. note::
Pro-tip, if you just want to quickly test things locally, you can run ``make serve`` inside a checkout of the Converse repo.
Converse is then hosted at http://localhost:8000
Option 1: Use the content delivery network
******************************************
Converse has a `CDN <https://en.wikipedia.org/wiki/Content_delivery_network>`_, provided by `KeyCDN <http://keycdn.com/>`_,
which hosts its JavaScript and CSS files.
The latest versions of these files are available at these URLs:
* https://cdn.conversejs.org/dist/converse.min.js
* https://cdn.conversejs.org/dist/converse.min.css
If you are integrating Converse into an existing website or app, then we recommend
that you load a specific version of Converse. Otherwise your website or app
might break when a new backwards-incompatible version of Converse is released.
To load a specific version of Converse you can put the version in the URL:
* https://cdn.conversejs.org/10.1.6/dist/converse.min.js
* https://cdn.conversejs.org/10.1.6/dist/converse.min.css
You can include these two URLs inside the *<head>* element of your website
via the *script* and *link* tags:
.. code-block:: html
<link rel="stylesheet" type="text/css" media="screen" href="https://cdn.conversejs.org/10.1.6/dist/converse.min.css">
<script src="https://cdn.conversejs.org/10.1.6/dist/converse.min.js" charset="utf-8"></script>
Option 2: Download the builds from Github
*****************************************
The `Converse releases page on Github <https://github.com/conversejs/converse.js/releases>`_
has the release notes for every release as well as links to downloadable zip files
containing all the files you need to host Converse yourself.
Extract the zip file and include converse.min.js and converse.min.css files in
the *<head>* element of your page, similar as shown in option 1 above.
Option 3: Building the files yourself
*************************************
Instead of using the CDN, you can also create your own builds and host them yourself.
Have a look at the :ref:`creating_builds` section on how to create your own builds.
In short, you should be able to do it by running ``make dist`` inside a
checkout of the `Converse repo <http://github.com/conversejs/converse.js/>`_.
To build the files and also start an HTTP server, you can run ``make serve``.
The distribution files will be added to the ``./dist`` folder inside the repo.
Initializing Converse
=====================
You'll need to initialize Converse with configuration settings relevant to your requirements.
Take a look at the :ref:`configuration-settings` section for info on all the available settings.
To quickly get started, you can put the following JavaScript code at the
bottom of your page (after the closing *</body>* element)::
<script>
converse.initialize({
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
show_controlbox_by_default: true
});
</script>
The `index.html <https://github.com/jcbrand/converse.js/blob/master/index.html>`_ file inside the
Converse repository serves as a nice, usable example.
Fullscreen version
------------------
Converse also comes in a fullscreen version.
A hosted version is available online at `conversejs.org/fullscreen <https://conversejs.org/fullscreen.html>`_.
Originally this version was available as a separate build file, but
as of version 4.0.0 and higher, the difference between the "overlay" and the
"fullscreen" versions of converse.js is simply a matter of configuring the
:ref:`view_mode`.
For example::
<script>
converse.initialize({
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
view_mode: 'fullscreen'
});
</script>
Where to go from here?
======================
Have a look at the various :ref:`features <features>` that Converse provides, for some of
them you might have to do more setup work, like configuring an XMPP server or
webserver.
You might want to implement some kind of persistent single-session solution for
your website, where users authenticate once in your website and are then
automatically logged in to the XMPP server as well. For more info on how this
can be achieved, read: :ref:`session-support`.
For end-to-end encryption via OMEMO, you'll need to load `libsignal-protocol.js
<https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in
your page. Take a look at the section on :ref:`libsignal <dependency-libsignal>` and the
:ref:`security considerations around OMEMO <feature-omemo>`.
Perhaps you want to create your own custom build of Converse? Then head over
to the :doc:`builds` section, or more generally the :doc:`development <development>`
documentation.
Do you want to know how to theme Converse? Then read the :doc:`theming <theming>`
documentation.

93
docs/source/security.rst Normal file
View File

@ -0,0 +1,93 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/security.rst">Edit me on GitHub</a></div>
=======================
Security considerations
=======================
.. note::
Converse comes with no warranty of any kind and the authors are not liable for any damages.
The data-structures of Converse encapsulate sensitive user data such as
XMPP account details (in case of manual login) and personal conversations.
In an environment where, besides Converse, other untrusted 3rd party scripts
might also be running, it's important to guard against malicious or invasive
access to user data and/or the API.
The threat model
================
The following threat model is considered:
Malicious 3rd party scripts served through compromised side-channels, such as ad-networks,
which attempt to access Converse's API and/or data-structures in order to personify users
or to pilfer their data.
Mitigating measures
===================
As of version 3.0.0, the following actions were taken to harden Converse against attacks:
Separate code/data into public and private parts
------------------------------------------------
1. Encapsulate Converse's data structures into a private closured object (named ``_converse``).
2. Split the API into public and private parts.
Restrict access to private code/data
------------------------------------
3. Only plugins are allowed to access the private API and the closured ``_converse`` object.
4. TODO: Whitelist plugins that have access to the private API and closured ``_converse`` object.
5. Prevent the removal of registered plugins (otherwise the whitelist could be circumvented).
6. Throw an error when multiple plugins try to register under the same name
(otherwise the whitelist could be circumvented).
.. note::
Care should be taken when using a custom build of Converse where some
of the core plugins contained in the default build are omitted. In this case
the omitted plugins should also be removed from the whitelist, otherwise
malicious plugins could be registered under their names.
Addititional measures
=====================
Besides the measures mentioned above, integrators and hosts can also take
further security precautions.
The most effective is to avoid serving untrusted 3rd party JavaScript (e.g.
advertisements and analytics).
Another option is to forego the use of a global ``converse`` object (which
exposes the public API) and instead to encapsulate it inside a private closure,
in order to keep it inaccessible to other scripts.
Other considerations
====================
Locally cached data
-------------------
Besides the "hot" data stored in models and collections, which are all
encapsulated in the private ``_converse`` object, there is also the cached data
stored in the browser's ``sessionStorage`` and ``localStorage`` stores.
Examples of sensitive cached data are chat messages and the contacts roster,
both which are in session storage, which means that the cache is cleared as
soon as the last tab or window is closed. User credentials are not cached at
all.
Perhaps the ability to encrypt this cached data could be added in future
versions of Converse, if there is sufficient demand for it.
However to date no significant mitigation or hardening measures have been taken to
secure this cached data.
Therefore, the best defence as website host is to avoid serving Converse with
untrusted 3rd party code, and the best defence as an end-user is to avoid chatting
on websites that host untrusted 3rd party code. The most common examples of such
being advertising and analytics scripts.

205
docs/source/session.rst Normal file
View File

@ -0,0 +1,205 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/session.rst">Edit me on GitHub</a></div>
==================
Session Management
==================
.. _`session-support`:
Shared Sessions
===============
It's possible to enable shared sessions whereby users already
logged in to your website will also automatically be logged in on the XMPP server,
Once a user is logged in, the session will be kept alive across page loads.
There are a few ways to let your users be automatically authenticated to an
XMPP server once they've logged in to your site.
Option 1). Server-side authentication via BOSH prebinding
---------------------------------------------------------
To **prebind** refers to a technique whereby your web application sets up an
authenticated BOSH session with the XMPP server or a standalone `BOSH <https://xmpp.org/about-xmpp/technology-overview/bosh/>`_
connection manager.
Once authenticated, it receives RID and SID tokens which need to be passed
on to Converse. Converse will then attach to that same session using
those tokens.
It's called "prebind" because you bind to the BOSH session beforehand, and then
later in the page you just attach to that session again.
The RID and SID tokens can be passed in manually when calling
`converse.initialize`, but a more convenient way is to pass Converse a :ref:`prebind_url`
which it will call when it needs the tokens. This way it will be able to
automatically reconnect whenever the connection drops, by simply calling that
URL again to fetch new tokens.
Prebinding reduces network traffic and also speeds up the startup time for
Converse. Additionally, because prebind works with tokens, it's not necessary
for the XMPP client to know or store users' passwords.
One potential drawback of using prebind is that in order to establish the
authenticated BOSH session server-side, you'll need to access and pass on the XMPP
credentials server-side, which, unless you're using tokens, means that you'll
need to store XMPP passwords in cleartext.
This is however not the case if you for example use LDAP or Active Directory as
your authentication backend, since you could then configure your XMPP server to
use that as well.
To prebind you will require a BOSH-enabled XMPP server for Converse to connect to
(see the :ref:`bosh-service-url` under :ref:`configuration-settings`)
as well as a BOSH client in your web application (written for example in
Python, Ruby or PHP) that will set up an authenticated BOSH session, which
Converse can then attach to.
.. note::
A BOSH server acts as a bridge between HTTP, the protocol of the web, and
XMPP, the instant messaging protocol.
Converse can only communicate via HTTP (or websocket, in which case BOSH can't be used).
It cannot open TCP sockets to communicate to an XMPP server directly.
So the BOSH server acts as a middle man, translating our HTTP requests into XMPP stanzas and vice versa.
Jack Moffitt has a great `blogpost <http://metajack.im/2008/10/03/getting-attached-to-strophe>`_
about this and even provides an
`example Django application <https://github.com/metajack/strophejs/tree/master/examples/attach>`_
to demonstrate it.
When you authenticate to the XMPP server on your backend application (for
example via a BOSH client in Django), you'll receive two tokens, RID (request ID) and SID (session ID).
The **Session ID (SID)** is a unique identifier for the current *session*. This
number stays constant for the entire session.
The **Request ID (RID)** is a unique identifier for the current *request* (i.e.
page load). Each page load is a new request which requires a new unique RID.
The best way to achieve this is to simply increment the RID with each page
load.
You'll need to configure Converse with the :ref:`prebind` :ref:`prebind_url` settings.
Please read the documentation on those settings for a fuller picture of what
needs to be done.
Example code for server-side prebinding
***************************************
* PHP:
See `xmpp-prebind-php <https://github.com/candy-chat/xmpp-prebind-php>`_ by
Michael Weibel and the folks from Candy chat.
* Python:
See this `example Django application`_ by Jack Moffitt.
Option 2). Delegated authentication, also called external authentication
------------------------------------------------------------------------
Delegated authentication refers to the usecase where the XMPP server delegates
authentication to some other service.
This could be to LDAP or Active Directory (as shown in the diagram at the top
of the page), or it could be to an OAuth provider, a SQL server to a specific
website.
The Prosody webserver has various user-contributed modules which delegate
authentication to external services. They are listed in the `Prosody community modules
page <https://modules.prosody.im/>`_. Other XMPP servers have similar plugin modules.
If your web-application has access to the same credentials, it can send those
credentials to Converse so that user's are automatically logged in when the
page loads.
This is can be done by setting :ref:`auto_login` to true and configuring the
the :ref:`credentials_url` setting.
Option 3). Temporary authentication tokens
------------------------------------------
The first option has the drawback that your web-application needs to know the
XMPP credentials of your users and that they need to be stored in the clear.
The second option has that same drawback and it also needs to pass those
credentials to Converse.
To avoid these drawbacks, you can instead let your backend web application
generate temporary authentication tokens which are then sent to the XMPP server
which in turn delegates authentication to an external authentication provider
(generally the same web-app that generated the tokens).
This can be combined with prebind or with the :ref:`credentials_url` setting.
Option 4). Cryptographically signed tokens
------------------------------------------
A third potential option is to generate cryptographically signed tokens (e.g.
HMAC tokens) which the XMPP server could authenticate by checking that they're
signed with the right key and that they conform to some kind of pre-arranged
format.
In this case, you would also use the :ref:`credentials_url` setting, to specify a
URL from which Converse should fetch the username and token.
Keeping users logged-in across page reloads
===========================================
If you've properly set up :ref:`shared session support <session-support>`, then
your users will stay logged-in to the XMPP server upon page reloads.
However, if users are logging in manually, then users might get logged out between requests.
Credential Management API
-------------------------
Users with modern browsers which properly support the
`Credential Management API <https://w3c.github.io/webappsec-credential-management>`_
should be automatically logged-in across page reloads and therefore maintain
their sessions.
Using a cookie
--------------
The main reason why users can get logged-out between page reloads is because we
don't (and can't) use cookies to maintain user sessions as is usually done with
websites.
This is because XMPP servers generally don't have support for logging in with a
cookie. It would be theoretically possible to login with SASL-EXTERNAL and a
cookie which the XMPP server looks up as part of the BOSH HTTP request or the
websocket connection, but no XMPP servers currently support this out of the
box.
Prosody does have a plugin called `mod_auth_http_cookie <https://modules.prosody.im/mod_auth_http_cookie.html>`_
which does the above. You'd have to `configure Converse.js to use SASL-EXTERNAL <https://opkode.com/blog/strophe_converse_sasl_external/>`_
and then set up Prosody with that plugin. (Note, I haven't yet tested this setup personally).
This is however not a cross-platform solution and won't work for hosters who
want to support all or multple XMPP servers.
Storing the password in localStorage
------------------------------------
Since cookies are usually not an option, people have suggested storing the
password in localStorage and logging in with it again when the user reloads the
page.
We've purposefully not put this functionality in Converse.js due to the
security implications of storing plaintext passwords in localStorage.
Storing the SASL SCRAM-SHA1 hash in IndexedDB
---------------------------------------------
Another suggestion that's been suggested is to store the SCRAM-SHA1 computed
``clientKey`` in localStorage and to use that upon page reload to log the user in again.
This has been implemented since version 10, see documentation on `reuse_scram_keys <https://conversejs.org/docs/html/configuration.html#reuse-scram-keys>`_

284
docs/source/setup.rst Normal file
View File

@ -0,0 +1,284 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/setup.rst">Edit me on GitHub</a></div>
.. _what-you-will-need:
=====================
Setup and integration
=====================
This page documents what you'll need to do to be able to connect Converse with
your own XMPP server and to better integrate it into your website.
At the very least you'll need Converse and an :ref:`XMPP server` with
:ref:`websocket-section` or :ref:`BOSH-section` enabled. That's definitely
enough to simply demo Converse or to do development work on it.
For end-to-end encryption via OMEMO, you'll need to load `libsignal-protocol.js
<https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in
your page. Take a look at the section on :ref:`libsignal <dependency-libsignal>` and the
:ref:`security considerations around OMEMO <feature-omemo>`.
If you want to more fully integrate it into a website
then you'll likely need to set up more services and components.
The diagram below shows a fairly common setup for a website or intranet:
* Converse runs in the web-browser on the user's device.
* It communicates with the XMPP server via BOSH or websocket which is usually
reverse-proxied by a web-server in order to overcome cross-site scripting
restrictions in the browser.
* Optionally the XMPP server is configured to use a SQL database for storing
archived chat messages.
* Optionally there is a user directory such as Active Directory or LDAP, which
the XMPP server is configured to use, so that users can log in with those
credentials.
* Usually (but optionally) there is a backend web application which hosts a
website in which Converse appears.
.. figure:: images/diagram.png
:align: center
:alt: A diagram of a possible setup, consisting of Converse, a web server, a backend web application, an XMPP server, a user directory such as LDAP and an XMPP server.
This diagram shows the various services in a fairly common setup (image generated with `draw.io <https://draw.io>`_).
----------------------
The various components
----------------------
.. _`XMPP server`:
An XMPP server
==============
Converse uses `XMPP <https://xmpp.org/about-xmpp/>`_ as its
messaging protocol, and therefore needs to connect to an XMPP/Jabber
server (Jabber® is an older and more user-friendly synonym for XMPP).
You can connect to public XMPP servers like ``conversejs.org`` but if you want to
integrate Converse into your own website and to use your website's
authentication sessions to log in users to the XMPP server (i.e. :ref:`session support <session-support>`)
then you'll have to set up your own XMPP server.
You can find a list of public XMPP servers/providers on `compliance.conversations.im <http://compliance.conversations.im/>`_
and a list of servers that you can set up yourself on `xmpp.org <https://xmpp.org/xmpp-software/servers/>`_.
.. _`BOSH-section`:
BOSH (XMPP-over-HTTP)
=====================
Web-browsers do not allow the persistent, direct TCP socket connections used by
desktop XMPP clients to communicate with XMPP servers.
Instead, we have HTTP and websocket as available protocols.
`BOSH`_ can be seen as XMPP-over-HTTP. In other words, it allows for XMPP
stanzas to be sent over an HTTP connection.
HTTP connections are stateless and usually shortlived.
XMPP connections on the other hand are stateful and usually last much longer.
So to enable a web application like Converse to communicate with an XMPP
server, we need a proxy which acts as a bridge between these two protocols.
This is the job of a BOSH connection manager. BOSH (Bidirectional-streams Over
Synchronous HTTP) is a protocol for allowing XMPP communication over HTTP. The
protocol is defined in `XEP-0206: XMPP Over BOSH <https://xmpp.org/extensions/xep-0206.html>`_.
Popular XMPP servers such as `Ejabberd <http://www.ejabberd.im>`_,
Prosody `(mod_bosh) <http://prosody.im/doc/setting_up_bosh>`_ and
`OpenFire <http://www.igniterealtime.org/projects/openfire/>`_ all include
their own BOSH connection managers (but you usually have to enable them in the
configuration).
However, if you intend to support multiple different servers (like
https://conversejs.org does), then you'll need a standalone connection manager.
For a standalone manager, see for example `Punjab <https://github.com/twonds/punjab>`_
and `node-xmpp-bosh <https://github.com/dhruvbird/node-xmpp-bosh>`_.
The demo on the `Converse homepage <https://conversejs.org>`_ uses a connection
manager located at https://conversejs.org/http-bind.
This connection manager is available for testing purposes only, please don't
use it in production.
Refer to the :ref:`bosh-service-url` configuration setting for information on
how to configure Converse to connect to a BOSH URL.
Configuring your webserver for BOSH
-----------------------------------
Lets say the domain under which you host Converse is *example.org:80*,
but the domain of your connection manager or the domain of
your HTTP file server (for `XEP-0363 HTTP File Upload <https://xmpp.org/extensions/xep-0363.html>`_)
is at a different domain, either a different port like *example.org:5280* or a
different name like *elsehwere.org*.
In such a situation the same-origin security policy of the browser comes into force.
For security purposes a browser does not by default allow a website to
make certain types of requests to other domains.
There are two ways in which you can solve this problem.
.. _CORS:
1. Cross-Origin Resource Sharing (CORS)
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
CORS is a technique for overcoming browser restrictions related to the
`same-origin security policy <https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy>`_.
CORS is enabled by adding an ``Access-Control-Allow-Origin`` header. Where this
is configured depends on what webserver is used for your file upload server.
2. Reverse-proxy
~~~~~~~~~~~~~~~~
Another possible solution is to add a reverse proxy to a webserver such as Nginx or Apache to ensure that
all services you use are hosted under the same domain name and port.
Examples:
*********
Assuming your site is accessible on port ``80`` for the domain ``mysite.com``
and your connection manager manager is running at ``someothersite.com/http-bind``.
The *bosh_service_url* value you want to give Converse to overcome
the cross-domain restriction is ``mysite.com/http-bind`` and not
``someothersite.com/http-bind``.
Your ``nginx`` or ``apache`` configuration will look as follows:
Nginx
^^^^^
.. code-block:: nginx
http {
server {
listen 80
server_name mysite.com;
location = / {
root /path/to/converse.js/; # Properly set the path here
index index.html;
}
location ~ ^/http-bind/ {
proxy_pass http://someothersite.com;
}
# CORS
location ~ .(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$ {
add_header Access-Control-Allow-Origin "*"; # Decide here whether you want to allow all or only a particular domain
root /path/to/converse.js/; # Properly set the path here
}
}
}
Apache
^^^^^^
.. code-block:: apache
<VirtualHost *:80>
ServerName mysite.com
RewriteEngine On
RewriteRule ^/http-bind(.*) http://someothersite.com/http-bind$1 [P,L]
</VirtualHost>
.. note::
If you're getting XML parsing errors for your BOSH endpoint, for
example::
XML Parsing Error: mismatched tag. Expected: </hr>.
Location: https://example.org/http-bind/
Line Number 6, Column 3: bosh-anon:6:3
Also ERROR: request id 12.2 error 504 happened
Then your BOSH proxy is returning an HTML error page (for a 504 error in
the above example).
This might be because your webserver and BOSH proxy have the same timeout
for BOSH requests. Because the webserver receives the request slightly earlier,
it gives up a few microseconds before the XMPP servers empty result and thus returns a
504 error page containing HTML to browser, which then gets parsed as if its
XML.
To fix this, make sure that the webserver's timeout is slightly higher.
In Nginx you can do this by adding ``proxy_read_timeout 61;``;
From Converse 4.0.0 onwards the default ``wait`` time is set to 59 seconds, to avoid
this problem.
.. _`websocket-section`:
Websocket
=========
Websockets provide an alternative means of connection to an XMPP server from
your browser.
Websockets provide long-lived, bidirectional connections which do not rely on
HTTP. Therefore BOSH, which operates over HTTP, doesn't apply to websockets.
`Prosody <http://prosody.im>`_ (from version 0.10) and `Ejabberd <http://www.ejabberd.im>`_ support websocket connections, as
does the node-xmpp-bosh connection manager.
Refer to the :ref:`websocket-url` configuration setting for information on how to
configure Converse to connect to a websocket URL.
Reverse-proxy for a websocket connection
----------------------------------------
Assuming your website is accessible on port ``443`` on the domain ``mysite.com``
and your XMPP server's websocket server is running at ``localhost:5280/xmpp-websocket``.
You can then set up your webserver as an SSL enabled reverse proxy in front of
your websocket endpoint.
The :ref:`websocket-url` value you'll want to pass in to ``converse.initialize`` is ``wss://mysite.com/xmpp-websocket``.
Your ``nginx`` will look as follows:
.. code-block:: nginx
http {
server {
listen 443
server_name mysite.com;
ssl on;
ssl_certificate /path/to/fullchain.pem; # Properly set the path here
ssl_certificate_key /path/to/privkey.pem; # Properly set the path here
location = / {
root /path/to/converse.js/; # Properly set the path here
index index.html;
}
location /xmpp-websocket {
proxy_http_version 1.1;
proxy_pass http://127.0.0.1:5280;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "upgrade";
proxy_read_timeout 86400;
}
# CORS
location ~ .(ttf|ttc|otf|eot|woff|woff2|font.css|css|js)$ {
add_header Access-Control-Allow-Origin "*"; # Decide here whether you want to allow all or only a particular domain
root /path/to/converse.js/; # Properly set the path here
}
}
}

View File

@ -0,0 +1,140 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/setup_dev_environment.rst">Edit me on GitHub</a></div>
.. _`setup_dev_environment`:
============================
Setting up a dev environment
============================
Installing the 3rd party dependencies
=====================================
To develop and customize Converse, you'll first need to check out Converse's Git
repository:
::
git clone https://github.com/conversejs/converse.js.git
cd converse.js
We use development tools which depend on Node.js and NPM (the Node package manager).
It's recommended that you use `NVM <https://github.com/nvm-sh/nvm>`_ (the Node version manager)
to make sure you have the right version of Node.
Refer to the `NVM Github page <https://github.com/nvm-sh/nvm#install--update-script>`_ for instructions on how to install it.
Once NVM is installed, you can run the following inside your checkout of the Converse Git repository:
::
nvm install
.. note::
You will always have to first run ``nvm install`` in a new terminal session in order to use the
recommended version of Node before working on Converse.
To set up the Converse development environment, you now run ``make dev``.
::
make dev
Alternatively, if you're using Windows, or don't have GNU Make installed, you can run the
following:
::
npm install
npm run lerna
This will install the Node development tools and Converse's dependencies.
The front-end dependencies are those JavaScript files on which
Converse directly depends and which will be loaded in the browser as part of
the bundle in ``dist/converse.js`` (or ``dist/converse.min.js``).
To see the 3rd party dependencies (not just the front-end dependencies, but
also ones necessary for development tasks like making builds), take a look at
the list under the ``devDependencies`` in `package.json <https://github.com/jcbrand/converse.js/blob/master/package.json>`_.
.. note::
After running ```make dev```, you should now have a new *node_modules* directory
which contains all the external dependencies of Converse.
If this directory does NOT exist, something must have gone wrong.
Double-check the output of ```make dev``` to see if there are any errors
listed. For support, you can ask in our chatroom: `dicuss@conference.conversejs.org <xmpp:discuss@conference.conversejs.org>`_.
If you don't have an XMPP client installed, follow this link to
`conversejs.org <https://conversejs.org/fullscreen#converse/room?jid=discuss@conference.conversejs.org>`_
where you can log in and be taken directly to the chatroom.
.. _`dependency-libsignal`:
Libsignal
---------
If you want OMEMO encryption, you need to load `libsignal <https://github.com/signalapp/libsignal-protocol-javascript>`_ separately in your page.
For example::
<script src="3rdparty/libsignal-protocol-javascript/dist/libsignal-protocol.js"></script>
The reason libsignal needs to be loaded separately is because it's released
under the `GPLv3 <https://github.com/signalapp/libsignal-protocol-javascript/blob/master/LICENSE>`_
which requires all other dependent JavaScript code to also be open sourced under the same
license. You might not be willing to adhere to those terms, which is why you
need to decide for yourself whether you're going to load libsignal or not.
.. _`webserver`:
Setting up a webserver
======================
When making changes to Converse, either development or theming changes,
you'll want to preview them in your browser.
For this, you'll need to serve the development files via a web server,
so that you can see your local changes in the browser.
Manually starting a web server
------------------------------
To both set up the development environment and also start up a web browser to
serve the files for you, you can run::
make serve
.. note::
To run the "make" commands, you'll need `GNUMake <https://www.gnu.org/software/make>`_
installed on your computer. If you use GNU/Linux or \*BSD, it should be installed or
available via your package manager. For Mac, you'll need to install XCode and in
Windows you can use `Chocolatey <https://chocolatey.org/>`_.
After running ``make serve`` you can open http://localhost:8000 in your webbrowser to see the Converse website.
When developing or changing the theme, you'll want to load all the
unminified JS and CSS resources as separate files. To do this, open http://localhost:8000/dev.html instead.
You might want to open `dev.html <https://github.com/conversejs/converse.js/blob/master/dev.html>`_ in your text editor or IDE as well, to see
how ``converse.initialize`` is called and to potentially change any of the
settings.
Starting a web server with live reloading
-----------------------------------------
Alternatively, if you want to have live reloading whenever any of the source files change, you
can run ``make devserver`` (which will use `webpack-dev-server <https://github.com/webpack/webpack-dev-server>`_).
Instead of ``dev.html`` being used, `webpack.html <https://github.com/conversejs/converse.js/blob/master/webpack.html>`_
is now being used as the HTML template, and you'll need to modify that file if
you want to change the settings passed to ``converse.initialize``.
If you're running ``make devserver``, you need to open http://localhost:8080.

165
docs/source/style_guide.rst Normal file
View File

@ -0,0 +1,165 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/style_guide.rst">Edit me on GitHub</a></div>
Software Style Guide
====================
Most of the style guide recommendations here come from Douglas Crockford's book
`JavaScript, the good parts <http://shop.oreilly.com/product/9780596517748.do>`_
Tabs or spaces?
---------------
We always indent 4 spaces.
Underscores or camelCase?
-------------------------
We use camelCase for function names and underscores for variables names.
For example:
.. code-block:: javascript
function thisIsAFunction () {
let this_is_a_variable;
...
}
const versus let
----------------
Try to use `const` whenever possible. If a variable won't be reassigned, use
`const`, otherwise use `let`.
Spaces around operators
-----------------------
In general, spaces are put around operators, such as the equals ``=`` or plus ``+`` signs.
For example:
.. code-block:: javascript
if (sublocale != locale) {
// do something
}
An exception is when they appear inside for-loop expressions, for example:
.. code-block:: javascript
for (i=0; i<msgs_length; i++) {
// do something
}
Generally though, rather err on the side of adding spaces, since they make the
code much more readable.
destructuring
-------------
When assigning to a variable via destructuring, add spaces between the curly
brackets.
For example:
.. code-block:: javascript
const { foo } = bar;
Global constants are written in ALL_CAPS
----------------------------------------
Global identifiers that denote constant values should be written in
all capital letters, with underscores between words.
For example:
.. code-block:: javascript
const SECONDS_IN_HOUR = 3600;
function update () {
const timeout = 20;
let seconds_since_message = 0;
// other stuff here
}
Function declaration and invocation
-----------------------------------
When declaring a function, the function name and the brackets after it are separated
with a space. Like so:
.. code-block:: javascript
function update (model) {
model.foo = 'bar';
}
When calling the same function, the brackets are written without a space in
between:
.. code-block:: javascript
update(model);
This is to make a more explicit visual distinction between method declarations
and method invocations.
Checking for equality
---------------------
JavaScript has a strict ``===`` and less strict ``==`` equality operator. The
stricter equality operator also does type checking. To avoid subtle bugs when
doing comparisons, always use the strict equality check.
Curly brackets
--------------
Curly brackets must appear on the same lines as the ``if`` and ``else`` keywords.
The closing curly bracket appears on its own line.
For example:
.. code-block:: javascript
if (locales[locale]) {
return locales[locale];
} else {
sublocale = locale.split("-")[0];
if (sublocale != locale && locales[sublocale]) {
return locales[sublocale];
}
}
Always enclose blocks in curly brackets
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
When writing a block such as an ``if`` or ``while`` statement, always use
curly brackets around that block of code. Even when not strictly required by
the compiler (for example if its only one line inside the ``if`` statement).
For example, like this:
.. code-block:: javascript
if (condition === true) {
this.updateRoomsList();
}
somethingElse();
and NOT like this:
.. code-block:: javascript
if (converse.auto_list_rooms)
this.updateRoomsList();
somethingElse();
This is to aid in readability and to avoid subtle bugs where certain lines are
wrongly assumed to be executed within a block.

64
docs/source/testing.rst Normal file
View File

@ -0,0 +1,64 @@
Automated tests
===============
Converse uses the `Karma <https://karma-runner.github.io/latest/index.html>`_ test runner and
`Jasmine <https://jasmine.github.io/>`_ testing library for running tests.
In addition, we use `ESlint <https://eslint.org/>`_ to run a static analysis (aka
linting) of the source files and report errors.
Whenever a commit is pushed to the Converse Github repo, all ESlint checks and
Jasmine tests are run on `Travis CI <https://travis-ci.org/github/conversejs/converse.js>`_.
Running tests
-------------
You can run ESlint by typing ``make eslint``. Similarly the tests can be run via ``make tests``.
To run both eslint and the tests, you can use ``make check``.
When running ``make test`` or ``make check``, a browser will automatically
start up, open a tab at http://localhost:9876 and start running the tests.
You'll see a green bar at the top of the page, and on the right inside it is a ``Debug`` button.
It's often helpful to click that button and run the tests in debug mode. This
way, you see better error output for failed tests.
Automatically run tests on file changes
***************************************
To automatically run the tests whenever you make a change to any of the
Converse source code, you can run ``make watch`` in one terminal, and ``make tests`` in another.
``make watch`` will build development bundles of Converse (in ``dist/converse.js`` and ``dist/converse.css``)
and automatically rebuild them whenever a source file is modified.
Similarly, Karma will make sure that the tests are re-executed when the bundle files are rebuilt.
Running individual tests
************************
Converse has over 400 tests, and it can take a while to run through all of them.
When developing on Converse, it's often preferable to have a more rapid
turnaround time between editing a file and checking whether the most relevant
tests have passed.
Jasmine tests are described by `it` functions and the tests names are written to
be read as plain English sentences that start with the word ``it``.
For example:
.. code-block:: javascript
it("is rejected if it's an unencapsulated forwarded message",
Tests are grouped by `describe` functions, and contained in spec files inside
the `spec <https://github.com/jcbrand/converse.js/blob/master/spec/>`_ directory.
To run only a single test, you can replace ``it(`` with ``fit(`` for the particular
test that you want to run. You can also do this for multiple tests. All of them
will be run whenever ``make test`` executes.
To run only a group of tests, you can similarly replace ``describe(`` with ``fdescribe``.

145
docs/source/theming.rst Normal file
View File

@ -0,0 +1,145 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/theming.rst">Edit me on GitHub</a></div>
.. _theming:
=======
Theming
=======
Setting up your environment
===========================
In order to theme Converse, you first need to follow the steps for :ref:`setup_dev_environment`, including :ref:`webserver`.
Creating a custom theme
=======================
Converse can be themed via CSS custom properties (aka CSS variables) and it has
some themes available in its source repository.
A theme is a CSS file with a specific rule that defines the theme's CSS properties.
The rule has a specific selector that must include (and determines) the theme name.
Inside this CSS rule, various CSS variables are assigned values.
The CSS variables mainly refer to the colors that comprise the theme.
If you don't specify a value for a specific CSS variable, then the value from
the ``classic`` theme is used, as defined in `classic.scss <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes/classic.scss>`_.
The native theme files can be found in `shared/styles/themes <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes>`_.
Note, the Converse theme files have a ``.scss`` extension because they are compiled
by the Sass compiler into normal CSS files. It's however not necessary to use
Sass, basic CSS files will also suffice.
The theme that Converse uses can be set via the :ref:`theme` configuration
setting (and the :ref:`dark_theme` configuration setting for dark mode).
How are themes applied?
-----------------------
When you set a value for the :ref:`theme` configuration setting, Converse will add
a class ``theme-${api.settings.get('theme')}`` on the ``converse-root`` DOM
element.
So, for example, if you set the ``theme`` setting to ``"dracula"``, then the
``converse-root`` element will get the class ``theme-dracula``.
.. code-block:: javascript
converse.initialize({ theme: "dracula" });
.. code-block:: html
<converse-root class="conversejs theme-dracula"></converse-root>
The apply a theme, there then needs to be a CSS rule with a selector that matches the
``theme-dracula`` class on the ``converse-root`` element.
If you take a look at the theme file `dracula.scss <https://github.com/conversejs/converse.js/tree/master/src/shared/styles/themes/dracula.scss>`_
you'll see that it defines a CSS rule with the selector
``.conversejs.theme-dracula``.
This selector matches any DOM element with both the classes ``.conversejs`` and
``.theme-dracula``. The ``converse-root`` element will already have the class
``.conversejs`` and it will have the class ``.theme-dracula`` if the ``theme``
(or ``dark_theme`` in dark mode) configuration setting is set to ``"dracula"``.
This is how themes are applied, by defining a CSS selector that matches the
class ``.theme-${name}`` (where ``name`` is a variable containing the name of
the theme), and then setting the ``theme`` (and/or ``dark_theme``) configuration
setting.
To create your own theme, you can create a similar CSS rule that matches
your theme's name and then you set the ``theme`` configuration setting to that
name. This CSS rule can be in any CSS file that is loaded in your website, or
you can even put it in the DOM as an inline style.
Modifying the CSS
=================
To create a new theme with different colors, it should be enough to create a
theme file that sets the various CSS variables (as described above).
For other CSS-related changes, you can make a specific
CSS rule with that matches the element you want to change.
Sometimes it might however be neccessary to modify the core CSS files from
Converse, for example if you're developing new features or fixing styling bugs.
The CSS files are generated from `Sass <http://sass-lang.com>`_ files that end in ``.scss`` and
which are distributed throughout the source code.
The CSS that is relevant to a particular plugin
is usually inside the ``./styles`` directory inside the relevant plugin directory.
For example: `src/plugins/controlbox/styles <https://github.com/conversejs/converse.js/tree/master/src/plugins/controlbox/styles>`_.
If you're running ``make watch``, then the CSS will automatically be
regenerated when you've changed any of the ``.scss``.
You can also manually generate the CSS::
make css
Modifying the HTML templates of Converse
========================================
Converse uses `lit-html <https://lit.dev/docs/libraries/standalone-templates/>`_ as HTML
templating library, and the HTML source code is contained in JavaScript ``.js``
files in various ``./template`` directories in the source code.
Some top-level templates are also in the ``./src/templates`` directory, but
the templates that are relevant to a specific plugin should be inside that plugin's subdirectory.
For example: `src/plugins/chatview/templates <https://github.com/conversejs/converse.js/tree/master/src/plugins/chatview/templates>`_.
You can modify HTML markup that Converse generates by modifying these files.
Use webpack aliases to modify templates without changing the original files
---------------------------------------------------------------------------
Generally what I do when creating a modified version of Converse for a project
or customer, is that I create a new JavaScript package with its own
``package.json`` and I then add ``converse.js`` as a dependency (e.g. via ``npm
install --save converse.js``) to the ``package.json``.
Then I add a Webpack configuration and use `webpack aliases <https://webpack.js.org/configuration/resolve/#resolvealias>`_
to resolve template paths to my own modified files.
For example, in the webpack configuration snippet below, I add two aliases, so
that the ``message-body.js`` and ``message.js`` templates can be replaced with
two of my own custom templates.
.. code-block:: javascript
resolve: {
extensions: ['.js'],
alias: {
'./message-body.js': path.resolve(__dirname, 'path/to/my/custom/message-body.js'),
'./templates/message.js': path.resolve(__dirname, 'path/to/my/custom/chat_message.js'),
}
}

View File

@ -0,0 +1,164 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/translations.rst">Edit me on GitHub</a></div>
============
Translations
============
Converse supports localization of its user interface and date formats. As
of writing, 17 languages are supported.
The translations of Converse can be found in the `locale
<https://github.com/jcbrand/converse.js/tree/master/locale>`_ directory.
Translations of Converse are very welcome. You can add translations either
manually by editing the ``.po`` files in the above-mentioned ``locale``
directory, or through the web at `weblate <https://hosted.weblate.org/projects/conversejs/#languages>`_.
As of version 3.3.0, Converse no longer automatically bundles translations
in its source file and instead fetches only the relevant locale for the current
session from a URL as specified by the :ref:`assets_path` setting.
There are three configuration settings relevant to translations and
localisation. You're encouraged to read the documentation for each of them.
* :ref:`i18n`
* :ref:`locales`
* :ref:`assets_path`
Manually updating translations
==============================
If you simply want to add a few missing translations, then consider doing it
through the web at `weblate <https://hosted.weblate.org/projects/conversejs/#languages>`_.
Some things however cannot be done via weblate and instead have to be done
manually in a checkout of the Converse source repository.
These tasks are documented below.
Updating the translations template (.pot file)
----------------------------------------------
The gettext `.pot` file located in
`./locale/converse.pot <https://github.com/jcbrand/converse.js/blob/master/locale/converse.pot>`_
is the template containing all translations and from which for each language an individual PO
file is generated.
The `.pot` file contains all translateable strings extracted from Converse.
To make a user-facing string translateable, wrap it in the double underscore helper
function like so:
.. code-block:: javascript
__('This string will be translated at runtime');
After adding the string, you'll need to regenerate the POT file:
::
make pot
Making translations file for a new language
-------------------------------------------
To create a new translations file for a language in which Converse is not yet
translated into, do the following
.. note:: In this example we use Polish (pl), you need to substitute 'pl' to your own language's code.
::
mkdir -p ./locale/pl/LC_MESSAGES
msginit -i ./locale/converse.pot -o ./locale/pl/LC_MESSAGES/converse.po -l pl
Please make sure to add the following attributes at the top of the file (under
*Content-Transfer-Encoding*). They are required as configuration settings for Jed,
the JavaScript translations library that we're using.
.. code-block:: po
"domain: converse\n"
"lang: pl\n"
"Content-Type: text/plain; charset=UTF-8\n"
"plural_forms: nplurals=2; plural=(n != 1);\n"
Updating an existing translations file
--------------------------------------
You can update the `.po` file for a specific language by doing the following:
.. note:: In this example we use German (de), you need to substitute 'de' to your own language's code.
::
msgmerge ./locale/de/LC_MESSAGES/converse.po ./locale/converse.pot -U
To do this for ALL languages, run:
::
make po
The resulting `.po` file is then what gets translated.
Generating a JSON file from a translations file
-----------------------------------------------
Unfortunately `Jed <http://slexaxton.github.io/Jed>`_, which we use for
translations in Converse cannot use the `.po` files directly. We have
to generate from it a file in JSON format and then put that in a `.js` file
for the specific language.
To generate JSON from a PO file, you'll need po2json for node.js. Run the
following command to install it (npm being the node.js package manager):
::
npm install po2json
You can then convert the translations into JSON format:
::
po2json -p -f jed -d converse locale/de/LC_MESSAGES/converse.po locale/de/LC_MESSAGES/converse.json
To do this for ALL languages, run:
::
make po2json
.. note::
If you are adding translations for a new language that is not already supported,
you'll have to add the language path in main.js and make one more edit in ./src/locales.js
to make sure the language is loaded by require.js.
Making sure the JSON file will get loaded
------------------------------------------
Finally, make sure that the language code is added to the list of default
values for the ``locales`` config setting.
This is done in ``src/converse-core.js``.
Look for the following section:
.. code-block:: javascript
// Default configuration values
// ----------------------------
this.default_settings = {
// ... Omitted for brevity
locales_url: 'locale/{{{locale}}}/LC_MESSAGES/converse.json',
locales: [
'af', 'ar', 'bg', 'ca', 'de', 'es', 'en', 'fr', 'he',
'hu', 'id', 'it', 'ja', 'nb', 'nl',
'pl', 'pt_BR', 'ru', 'tr', 'uk', 'zh_CN', 'zh_TW'
],
// ... Omitted for brevity
};

View File

@ -0,0 +1,224 @@
.. raw:: html
<div id="banner"><a href="https://github.com/jcbrand/converse.js/blob/master/docs/source/troubleshooting.rst">Edit me on GitHub</a></div>
=============================
Troubleshooting and debugging
=============================
General tips on debugging Converse
==================================
Enabling debug output
---------------------
Converse has a :ref:`loglevel` configuration setting which lets you to turn on
debug logging in the browser's developer console.
When debugging, you always want to make sure that this setting is set to
``true`` when calling ``converse.initialize``.
You can also enable debug output via the URL, which is useful when you don't
have access to the server where Converse is hosted.
To do so, add ``#converse?loglevel=debug`` to the URL in the browser's address bar.
Make sure to first remove any already existing URL fragment (the URL fragment
is the part that starts with a ``#``).
With debug logging on, you can open the browser's developer console and study the
data that is logged to it.
In Chrome you can right click in the developer console and save its contents to
a file for later study.
What is logged at the debug loglevel?
-------------------------------------
`Strope.js <http://strophe.im/>`_, the underlying XMPP library which Converse
uses, swallows errors so that messaging can continue in cases where
non-critical errors occur.
This is a useful feature and provides more stability, but it makes debugging
trickier, because the app doesn't crash when something goes wrong somewhere.
That's why checking the debug output in the browser console is important.
If something goes wrong somewhere, the error will be logged there and you'll be
able to see it.
Additionally, Converse will in debug mode also log all XMPP stanzas
(the XML snippets being sent between it and the server) to the console.
This is very useful for debugging issues relating to the XMPP protocol.
For example, if a message or presence update doesn't appear, one of the first
things you can do is to set ``loglevel: debug`` and then to check in the console
whether the relevant XMPP stanzas are actually logged (which would mean that
they were received by Converse). If they're not logged, then the problem is
more likely on the XMPP server's end (perhaps a misconfiguration?). If they
**are** logged, then there might be a bug or misconfiguration in Converse.
Performance issues with large rosters
=====================================
Effort has been made to benchmark and optimize Converse to work with large
rosters.
See for example the benchmarking tests in `spec/profiling.js
<https://github.com/jcbrand/converse.js/blob/master/spec/profiling.js>`_ which
can be used together with the `profiling features of
Chrome <https://developer.chrome.com/devtools/docs/cpu-profiling>`_ to find
bottlenecks in the code.
However, with large rosters (more than 1000 contacts), rendering in
Converse slows down a lot and it may become intolerably slow.
One simple trick to improve performance is to set ``show_only_online_users: true``.
This will (usually) reduce the amount of contacts that get rendered in the
roster, which eases one of the remaining performance bottlenecks.
File upload is not working
==========================
One of the most common causes for file upload not working is a lack of CORS
support by the file server to which the file should be uploaded.
CORS stands for `Cross-Origin Resource Sharing (CORS) <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`_
and is a technique for overcoming browser restrictions related to the
`same-origin security policy <https://developer.mozilla.org/en-US/docs/Web/Security/Same-origin_policy>`_.
For example, if the domain under which you host Converse is *example.org*,
but the domain of your of your HTTP file server (for `XEP-0363 HTTP File Upload <https://xmpp.org/extensions/xep-0363.html>`_)
is *upload.example.org*, then the HTTP file server needs to enable CORS.
If you're not sure what the domain of the HTTP file server is, take a look at
the console of your browser's developer tools.
You might see an error like this one::
Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at https://example.de:5443/...
You might also see a 404 HTTP response for an OPTIONS request in the `Network Tab` of your browser's developer tools.
An OPTIONS request is usually a so-called
`CORS pre-flight request <https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods/OPTIONS#Preflighted_requests_in_CORS>`_
which is used by the browser to find out whether the endpoint supports
`Cross-Origin Resource Sharing (CORS) <https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS>`_.
If you get a 404 response for such a request, then the endpoint does NOT
support CORS and the browser will prevent requests from being made to it.
This will prevent you from uploading files to it.
How you solve a CORS-related issue depends on your particular setup, specifically it depends on
what you're using as the HTTP file server.
CORS is enabled by adding an ``Access-Control-Allow-Origin`` header, so you'll
have to configure your file server to add this header.
Users don't stay logged in across page reloads
==============================================
A common complaint in the Converse chat room (`<xmpp:discuss@conference.conversejs.org?join>`_)
is that users are logged out when they reload the page.
The main way in which websites and web apps maintain a user's login session is via
authentication cookies, which are included in every HTTP request sent to the server.
XMPP is however not HTTP, cookies aren't automatically included in traffic to
the XMPP server and XMPP servers don't rely on cookies for authentication.
Instead, an XMPP client is expected to store the user credentials (username and
password, either plaintext or hashed and salted if
`SCRAM <https://en.wikipedia.org/wiki/Salted_Challenge_Response_Authentication_Mechanism>`_
is being used) and to then present those credentials to the XMPP server when authenticating.
This works well for non-web XMPP clients, but Converse has so far avoided
storing user credentials in browser storage, since they can then be accessed by
any scripts running in the browser under the same domain.
So what does Converse do to keep users logged in?
-------------------------------------------------
Use the Web Auth API
********************
Converse supports the `Web Authentication API <https://developer.mozilla.org/en-US/docs/Web/API/Web_Authentication_API>`_
which let's it use the secure credential management of the browser to get the
uesr credentials to automatically log the user in. This however requires that
the user saves his or her username and password in the browser. Often the user
is automatically asked by the browser whether he/she wants to store the
credentials. If that doesn't happen, the user has to do so manually, usually by
clicking the key icon in the address bar. This works well on most modern browsers,
but not on Firefox, which has insufficient support for the Web Authentication API.
What can users do to stay logged in?
------------------------------------
Outsource credential management to something else
*************************************************
The issues mentioned above mostly related to users logging in manually, and not
to integrations where Converse automatically fetches user credentials from the
backend via the :ref:`credentials_url` setting.
Use BOSH instead of websocket
*****************************
`BOSH <https://xmpp.org/extensions/xep-0206.html>`_ can be thought of
XMPP-over-HTTP and because HTTP is stateless, BOSH needs to maintain login
sessions for a certain amount of time (usually 60 seconds) even if there is no
HTTP traffic between the client and server. This means that if you have a BOSH
session running, you can reload the page and you will stay logged in.
Note, Websocket connections are however faster and have less overhead than BOSH.
User a browser with adequate support for the Web Auth API
*********************************************************
Another option is to only use a browser with proper support for the Web Auth
API (which mainly means avoiding Firefox) and then to save your credentials in the browser.
Use Converse Desktop
********************
The `desktop version of Converse <https://github.com/conversejs/converse-desktop>`_
also doesn't have this problem, since the credentials are stored in Electron
and there is no significant risk of other malicious scripts running.
What else can Converse do to keep users logged in?
--------------------------------------------------
This problem could also potentially be fixed by storing the
XMPP credentials securely with web crypto and IndexedDB. This could be done by
generating a private encryption key in non-exportable format, and then using that
to encrypt the credentials before storing them in IndexedDB.
This would protect the credentials from someone who has access to your
computer (or harddrive), but it still won't protect them from malicious scripts
running in the same domain as Converse is being hosted, since they would have the
same level of access as Converse itself (which legitimately needs access to the
credentials).
Common errors
=============
Error: A "url" property or function must be specified
-----------------------------------------------------
That's a relatively generic `Skeletor <https://github.com/conversejs/skeletor>`_ (or `Backbone <http://backbonejs.org/>_`)
error and by itself it usually doesn't give enough information to know how to fix the underlying issue.
Generally, this error happens when a Model is being persisted (e.g. when model.save() is called,
but there is no information specifying where/how it should be persisted.
The Converse models are persisted to browser storage (e.g. sessionStorage, localStorage or IndexedDB),
and this happens by adding a browserStorage attribute on the model, or on the collection containing the model.
See for example here: https://github.com/conversejs/converse.js/blob/395aa8cb959bbb7e26472ed3356160c8044be081/src/headless/converse-chat.js#L359
If this error occurs, it means that a model being persisted doesn't have the ``browserStorage`` attribute,
and it's containing collection (if there is one) also doesn't have that attribute.
This usually happens when a model has been removed from a collection, and then ``.save()`` is called on it.
In the context of Converse it might mean that there's an attempt to persist data before all models have been properly initialized,
or conversely after models have been removed from their containing collections.

62
fullscreen.html Normal file
View File

@ -0,0 +1,62 @@
<!doctype html>
<html class="no-js" lang="en">
<head>
<title>Converse</title>
<meta charset="utf-8"/>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<meta name="description" content="Converse XMPP/Jabber Chat"/>
<meta name="author" content="JC Brand" />
<meta name="keywords" content="xmpp chat webchat converse.js" />
<link rel="shortcut icon" type="image/ico" href="/dist/favicon.ico"/>
<script type="text/javascript" src="inverse-analytics.js"></script>
<noscript><p><img src="//stats.opkode.com/piwik.php?idsite=5" style="border:0;" alt="" /></p></noscript>
<link rel="manifest" href="./manifest.json">
<link type="text/css" rel="stylesheet" media="screen" href="/dist/converse.min.css" />
<script src="https://cdn.conversejs.org/3rdparty/libsignal-protocol.min.js"></script>
<script src="/dist/converse.min.js"></script>
</head>
<body class="converse-fullscreen">
<noscript>You need to enable JavaScript to run the Converse.js chat app.</noscript>
<div id="conversejs-bg"></div>
<script>
/*
@licstart
This is free and unencumbered software released into the public domain.
Anyone is free to copy, modify, publish, use, compile, sell, or
distribute this software, either in source code form or as a compiled
binary, for any purpose, commercial or non-commercial, and by any
means.
In jurisdictions that recognize copyright laws, the author or authors
of this software dedicate any and all copyright interest in the
software to the public domain. We make this dedication for the benefit
of the public at large and to the detriment of our heirs and
successors. We intend this dedication to be an overt act of
relinquishment in perpetuity of all present and future rights to this
software under copyright law.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
IN NO EVENT SHALL THE AUTHORS BE LIABLE FOR ANY CLAIM, DAMAGES OR
OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.
For more information, please refer to <http://unlicense.org/>
@licend
*/
converse.initialize({
authentication: 'login',
auto_away: 300,
auto_reconnect: true,
bosh_service_url: 'https://conversejs.org/http-bind/', // Please use this connection manager only for testing purposes
message_archiving: 'always',
view_mode: 'fullscreen'
});
</script>
</body>
</html>

View File

@ -1,10 +0,0 @@
{% extends "base.html" %}
{% block content %}
<h2>Page Not Found</h2>
<p>
The page you are looking for was not found.
</p>
{% endblock %}

View File

@ -1,12 +0,0 @@
{% extends "base.html" %}
{% block content %}
<h2>Server Error</h2>
<p>
The server had serious problems while serving your request. We've just sent our
trained monkeys to fix the issue.
</p>
{% endblock %}

View File

@ -1,70 +0,0 @@
{% load i18n %}
{% load url from future %}
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" xml:lang="{{ LANGUAGE_CODE }}" lang="{{ LANGUAGE_CODE }}">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<meta name="author" content="Michal Čihař" />
<meta name="copyright" content="Copyright &copy; 2003 - {{ current_year }} Michal Čihař" />
<title>{% include "title.html" %}</title>
{% if description %}
<meta name="description" content="{{ description }}" />
{% endif %}
<link rel="stylesheet" type="text/css" href="/media/css/style.css" />
<link rel="stylesheet" type="text/css" href="/media/css/blitzer/jquery-ui-1.8.18.custom.css" />
<script src="/media/js/jquery-1.7.1.min.js" type="text/javascript"></script>
<script src="/media/js/jquery-ui-1.8.18.custom.min.js" type="text/javascript"></script>
<script src="/media/js/loader.js" type="text/javascript"></script>
<link rel="shortcut icon" href="/favicon.ico" type="image/x-icon" />
<link rel="icon" href="/favicon.ico" type="image/x-icon" />
<meta name="robots" content="index, follow" />
</head>
<body>
<h1 class="ui-state-default"><a href="/">{% include "title.html" %}</a></h1>
<ul class="menu">
{% if user.is_authenticated %}
<li><a href="/accounts/profile/">{% blocktrans with user.get_full_name as name %}Logged in as {{ name }}{% endblocktrans %}</a></li>
<li><a href="/accounts/logout/">{% trans "Logout" %}</a></li>
{% else %}
<li><a href="/accounts/register/">{% trans "Register" %}</a></li>
<li><a href="/accounts/login/">{% trans "Login" %}</a></li>
{% endif %}
</ul>
<ul class="breadcums">
<li><a href="/">{% trans "Home" %}</a></li>
{% block breadcums %}
{% endblock %}
</ul>
<div class="content">
{% if messages %}
{% for message in messages %}
<div class="ui-widget">
<div style="padding: 0pt 0.7em;" class="ui-state-{% if message.tags == "error" %}error{% else %}highlight{% endif %} ui-corner-all">
<p><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-{% if message.tags == "error" or message.tags == "warning" %}alert{% else %}info{% endif %}"></span>
{{ message }}
</p>
</div>
</div>
{% endfor %}
{% endif %}
{% block content %}
{% endblock %}
</div>
<ul class="footer">
<li>{% blocktrans %}Powered by <a href="http://weblate.org">Weblate {{ version }}</a>{% endblocktrans %}</li>
<li><a href="{% url 'accounts.views.contact' %}">{% trans "Contact us" %}</a></li>
</ul>
</body>
</html>

View File

@ -1,18 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% load url from future %}
{% block content %}
<p>{% blocktrans %}Please contact us in English, otherwise we might be unable to understand your request.{% endblocktrans %}</p>
<form method="post" action="{% url 'accounts.views.contact' %}">
{% csrf_token %}
<table>
{{ form.as_table }}
<tr><td></td><td><input type="submit" class="button" value="{% trans "Send" %}" /></td></tr>
</table>
</form>
{% endblock %}

View File

@ -1,92 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
{% if usertranslations %}
<h2>{% trans "Your translations" %}</h2>
<table>
<thead>
<tr>
<th>{% trans "Language" %}</th>
<th colspan="2">{% trans "Translated" %}</th>
<th>{% trans "Fuzzy" %}</th>
</tr>
<tbody>
{% for trans in usertranslations %}
{% with trans.get_translated_percent as percent and trans.get_fuzzy_percent as fuzzy %}
<tr>
<th><a href="{{ trans.get_absolute_url }}">{{ trans.subproject }} - {% trans trans.language.name %}</a></th>
<td class="percent">{{ percent }}%</td>
<td class="progress"><div class="progress" id="{{ percent|floatformat:0 }}"></div></td>
<td class="percent">{{ fuzzy }}%</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
{% endif %}
<h2>{% trans "Projects" %}</h2>
<table>
<thead>
<tr>
<th>{% trans "Project" %}</th>
<th colspan="2">{% trans "Translated" %}</th>
</tr>
<tbody>
{% for prj in projects %}
{% with prj.get_translated_percent as percent %}
<tr>
<th><a href="{{ prj.get_absolute_url }}">{{ prj.name }}</a></th>
<td class="percent">{{ percent }}%</td>
<td class="progress"><div class="progress" id="{{ percent|floatformat:0 }}"></div></td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
<h2>{% trans "Users" %}</h2>
<h3>{% trans "Best translators" %}</h3>
<table>
<thead>
<tr>
<th>{% trans "User" %}</th>
<th>{% trans "Translated" %}</th>
</tr>
<tbody>
{% for u in top_translations %}
<tr>
<td>{{ u.user.get_full_name }}</td>
<td class="percent">{{ u.translated }}</td>
</tr>
{% endfor %}
</tbody>
</table>
<h3>{% trans "Best suggestions" %}</h3>
<table>
<thead>
<tr>
<th>{% trans "User" %}</th>
<th>{% trans "Suggested" %}</th>
</tr>
<tbody>
{% for u in top_suggestions %}
<tr>
<td>{{ u.user.get_full_name }}</td>
<td class="percent">{{ u.suggested }}</td>
</tr>
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -1,43 +0,0 @@
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}
{% block content %}
{% if form.errors or userform.errors %}
<div class="ui-widget">
<div style="padding: 0pt 0.7em;" class="ui-state-error ui-corner-all">
<p><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-alert"></span>
{% trans "Please fix errors in the form." %}
</p>
</div>
</div>
{% endif %}
<form method="post" action="{% url 'accounts.views.profile' %}">
{% csrf_token %}
<div class="accordion">
<h2><a href="#">{% trans "Preferences" %}</a></h2>
<div>
<table>
{{ form.as_table }}
</table>
</div>
<h2><a href="#">{% trans "Account" %}</a></h2>
<div>
<table>
{{ userform.as_table }}
</table>
<span class="helptext">{% trans "Your name and email will appear as author on Git commits." %}</span>
</div>
<h2><a href="#">{% trans "Password" %}</a></h2>
<div>
{% url 'django.contrib.auth.views.password_change' as pw_url %}
{% blocktrans %}You can change password on <a href="{{ pw_url }}">separate page</a>.{% endblocktrans %}
</div>
</div>
<input type="submit" value="{% trans "Save" %}" class="button" />
</form>
{% endblock %}

View File

@ -1,33 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block breadcums %}
<li><a href="{{ object.get_absolute_url }}">{{ object }}</a></li>
{% endblock %}
{% block content %}
{% include "project_info.html" %}
<h2>{% trans "Subprojects" %}</h2>
<table>
<thead>
<tr>
<th>{% trans "Subproject" %}</th>
<th colspan="2">{% trans "Translated" %}</th>
</tr>
<tbody>
{% for prj in object.subproject_set.all %}
{% with prj.get_translated_percent as percent %}
<tr>
<th><a href="{{ prj.get_absolute_url }}">{{ prj.name }}</a></th>
<td class="percent">{{ percent }}%</td>
<td class="progress"><div class="progress" id="{{ percent|floatformat:0 }}"></div></td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
{% endblock %}

View File

@ -1,11 +0,0 @@
{% load i18n %}
<h2>{% trans "Project Information" %}</h2>
<p>{% trans "Project website:" %} <a href="{{ object.web }}">{{ object.web }}</a></p>
{% if object.mail %}
<p>{% trans "Mailing list for translators:" %} <a href="mailto:{{ object.mail }}">{{ object.mail }}</a></p>
{% endif %}
{% if object.instructions %}
<p>{% trans "Instructions for translators:" %} <a href="{{ object.instructions }}">{{ object.instructions }}</a></p>
{% endif %}

View File

@ -1,36 +0,0 @@
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}
{% block content %}
{% if account %}
<p>
{% blocktrans with account.username as username %}Thank you. Your
account is now activated. Your username is
<b>{{ username }}</b>.{% endblocktrans %}
</p>
<p>
{% url 'accounts.views.profile' as profile_url %}
{% blocktrans %}You might want to <a href="{{ profile_url }}">adjust your profile</a> now.{% endblocktrans %}
</p>
{% else %}
<p>
{% url 'registration.views.register' as reg_url %}
{% blocktrans count expiration_days as days %}
Your account could not be activated.
This may be because it is already active or because you waited over
{{ days }} day to activate it.
If this is not the case, please contact the website administrator.
Otherwise, you may <a href="{{ reg_url }}">register again.</a>
{% plural %}
Your account could not be activated.
This may be because it is already active or because you waited over
{{ days }} days to activate it.
If this is not the case, please contact the website administrator.
Otherwise, you may <a href="{{ reg_url }}">register again.</a>
{% endblocktrans %}.
</p>
{% endif %}
{% endblock %}

View File

@ -1,18 +0,0 @@
{% load url from future %}{% load i18n %}{% load weblate %}{% filter wordwrap:72 %}{% blocktrans with site|site_title as site_title %}Hi,
This is an automatic email to help you complete your registration
with {{ site_title }}.
Please open the following link in your web browser. If the link
is split over several lines, you may need to copy it in the
address bar.{% endblocktrans %}
http://{{ site.domain }}{% url 'registration.views.activate' activation_key=activation_key %}
{% blocktrans with site|site_title as site_title %}
If there is a problem with your registration, please reply to
this email.
Best regards,
{{ site_title }}
{% endblocktrans %}{% endfilter%}

View File

@ -1 +0,0 @@
{% load i18n %}{% load weblate %}{% blocktrans with site|site_title as site_title %}Your registration on {{ site_title }}{% endblocktrans %}

View File

@ -1,44 +0,0 @@
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}
{% block content %}
{% if form.errors %}
<div class="ui-widget">
<div style="padding: 0pt 0.7em;" class="ui-state-error ui-corner-all">
<p><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-alert"></span>
{% trans "Your username and password didn't match. Please try again." %}
</p>
</div>
</div>
{% endif %}
<form method="post" action="{% url 'django.contrib.auth.views.login' %}">
{% csrf_token %}
<table>
<tr>
<td>{{ form.username.label_tag }}</td>
<td>{{ form.username }}</td>
</tr>
<tr>
<td>{{ form.password.label_tag }}</td>
<td>{{ form.password }}</td>
</tr>
</table>
<input type="submit" value="{% trans "Login" %}" class="button" />
<input type="hidden" name="next" value="{{ next }}" />
</form>
<p>
{% url 'registration.views.register' as register_url %}
{% blocktrans %}Do not have an account yet? You can <a href="{{ register_url }}">register</a>.{% endblocktrans %}
</p>
<p>
{% url 'auth_password_reset' as reset_url %}
{% blocktrans %}Forgot your password? You can <a href="{{ reset_url }}">reset it</a>.{% endblocktrans %}
</p>
{% endblock %}

View File

@ -1,12 +0,0 @@
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}
{% block content %}
<p>{% blocktrans %}Thanks for using Weblate!{% endblocktrans %}</p>
<p><a href="{% url 'django.contrib.auth.views.login' %}">{% trans "Login again" %}</a></p>
{% endblock %}

View File

@ -1,8 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<p>{% trans 'Your password was changed.' %}</p>
{% endblock %}

View File

@ -1,26 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<form action="" method="post">{% csrf_token %}
{% if form.errors %}
<div class="ui-widget">
<div style="padding: 0pt 0.7em;" class="ui-state-error ui-corner-all">
<p><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-alert"></span>
{% blocktrans count form.errors.items|length as counter %}Please correct the error below.{% plural %}Please correct the errors below.{% endblocktrans %}
</p>
</div>
</div>
{% endif %}
<p>{% trans "Please enter your old password, for security's sake, and then enter your new password twice so we can verify you typed it in correctly." %}</p>
<table>
{{ form.as_table }}
</table>
<input type="submit" value="{% trans 'Change my password' %}" class="button" />
</form>
{% endblock %}

View File

@ -1,10 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<p>{% trans "Your password has been set. You may go ahead and log in now." %}</p>
<p><a href="{{ login_url }}">{% trans 'Log in' %}</a></p>
{% endblock %}

View File

@ -1,23 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
{% if validlink %}
<p>{% trans "Please enter your new password twice so we can verify you typed it in correctly." %}</p>
<form action="" method="post">{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<input type="submit" value="{% trans 'Change my password' %}" class="button" />
</form>
{% else %}
<p>{% trans "The password reset link was invalid, possibly because it has already been used. Please request a new password reset." %}</p>
{% endif %}
{% endblock %}

View File

@ -1,9 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<p>{% trans "We've e-mailed you instructions for setting your password to the e-mail address you submitted. You should be receiving it shortly." %}</p>
{% endblock %}

View File

@ -1,14 +0,0 @@
{% load i18n %}{% load url from future %}{% autoescape off %}
{% blocktrans %}You're receiving this e-mail because you requested a password reset for your user account at {{ site_name }}.{% endblocktrans %}
{% trans "Please go to the following page and choose a new password:" %}
{% block reset_link %}
{{ protocol }}://{{ domain }}{% url 'django.contrib.auth.views.password_reset_confirm' uidb36=uid token=token %}
{% endblock %}
{% trans "Your username, in case you've forgotten:" %} {{ user.username }}
{% trans "Thanks for using our site!" %}
{% blocktrans %}The {{ site_name }} team{% endblocktrans %}
{% endautoescape %}

View File

@ -1,13 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% block content %}
<p>{% trans "Forgotten your password? Enter your e-mail address below, and we'll e-mail instructions for setting a new one." %}</p>
<form action="" method="post">{% csrf_token %}
{{ form.as_p }}
<input type="submit" value="{% trans 'Reset my password' %}" class="button" />
</form>
{% endblock %}

View File

@ -1,10 +0,0 @@
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}
{% block content %}
<p>{% blocktrans %}Thank you for registering. You will very soon receive an email with
a confirmation link. Please follow this link in order to complete your registration.{% endblocktrans %}</p>
{% endblock %}

View File

@ -1,27 +0,0 @@
{% extends "base.html" %}
{% load url from future %}
{% load i18n %}
{% block content %}
{% if form.errors %}
<div class="ui-widget">
<div style="padding: 0pt 0.7em;" class="ui-state-error ui-corner-all">
<p><span style="float: left; margin-right: 0.3em;" class="ui-icon ui-icon-alert"></span>
{% trans "Please fix errors in registration form." %}
</p>
</div>
</div>
{% endif %}
<form action="{% url 'weblate_register' %}" method="post" accept-charset="utf-8">
{% csrf_token %}
<table>
{{ form.as_table }}
</table>
<p>{% trans "By registering you agree to use your name and email in Git commits." %}</p>
<p><input type="submit" value="{% trans 'Register' %}" class="button" /></p>
</form>
{% endblock %}

View File

@ -1,41 +0,0 @@
{% extends "base.html" %}
{% load i18n %}
{% load url from future %}
{% block breadcums %}
<li><a href="{{ object.project.get_absolute_url }}">{{ object.project }}</a></li>
<li><a href="{{ object.get_absolute_url }}">{{ object.name }}</a></li>
{% endblock %}
{% block content %}
{% include "subproject_info.html" %}
<h2>{% trans "Translations" %}</h2>
<table>
<thead>
<tr>
<th>{% trans "Language" %}</th>
<th colspan="2">{% trans "Translated" %}</th>
<th>{% trans "Fuzzy" %}</th>
</tr>
<tbody>
{% for trans in object.translation_set.all %}
{% with trans.get_translated_percent as percent and trans.get_fuzzy_percent as fuzzy %}
<tr>
<th><a href="{{ trans.get_absolute_url }}">{% trans trans.language.name %}</a></th>
<td class="percent">{{ percent }}%</td>
<td class="progress"><div class="progress" id="{{ percent|floatformat:0 }}"></div></td>
<td class="percent">{{ fuzzy }}%</td>
</tr>
{% endwith %}
{% endfor %}
</tbody>
</table>
{% url 'accounts.views.contact' as contact_url %}
<p>{% blocktrans %}Should your language be missing, plese <a href="{{ contact_url }}?subject=New+language+request+for+{{ object }}">contact us</a>.{% endblocktrans %}</li>
{% endblock %}

View File

@ -1,6 +0,0 @@
{% load i18n %}
{% with object.project as object %}
{% include "project_info.html" %}
{% endwith %}
<p>{% trans "Git repository:" %} <code>{{ object.repo }}</code> ({% blocktrans with object.branch as branch %}{{ branch }} brach{% endblocktrans %})</p>

View File

@ -1,9 +0,0 @@
{% if title %}
{{ title }} @ {{ site_title }}
{% else %}
{% if object %}
{{ object }} @ {{ site_title }}
{% else %}
{{ site_title }}
{% endif %}
{% endif %}

Some files were not shown because too many files have changed in this diff Show More