mirror of
https://github.com/danielsogl/awesome-cordova-plugins.git
synced 2026-07-16 00:00:04 +08:00
Compare commits
119
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1d8ae5abab | ||
|
|
0fc534699b | ||
|
|
7f39af3af3 | ||
|
|
dd8888c369 | ||
|
|
e0138a10ab | ||
|
|
5492239ff4 | ||
|
|
18fe9c9825 | ||
|
|
3b804dfc6d | ||
|
|
959e132909 | ||
|
|
d498f9823a | ||
|
|
0c2e84c9c0 | ||
|
|
28a24f6413 | ||
|
|
78c4b6a85c | ||
|
|
bc7aef92f3 | ||
|
|
2b161bbbe0 | ||
|
|
4da9fab97e | ||
|
|
78c37f847a | ||
|
|
b93e321b1b | ||
|
|
b704d2875b | ||
|
|
56263e13fe | ||
|
|
a2f379e98e | ||
|
|
7a7b7b885a | ||
|
|
0a6ad5f231 | ||
|
|
15fb82730d | ||
|
|
699af1e1c2 | ||
|
|
a3cde90e2e | ||
|
|
230efdb728 | ||
|
|
7a02d61224 | ||
|
|
0103ebc288 | ||
|
|
ba3487dd55 | ||
|
|
c1bac59b07 | ||
|
|
37082cf783 | ||
|
|
91bc6380d0 | ||
|
|
760b238a6b | ||
|
|
da02a2ec51 | ||
|
|
a4078995db | ||
|
|
3fd0185d4e | ||
|
|
8aa19525cc | ||
|
|
96de5d9c31 | ||
|
|
63c34cade4 | ||
|
|
5b03b578dc | ||
|
|
2a4f228bdf | ||
|
|
d189a5bbc1 | ||
|
|
ec57f00d2b | ||
|
|
d36a8c8257 | ||
|
|
3665781b40 | ||
|
|
9108db7653 | ||
|
|
00d1ad7d3b | ||
|
|
de51ef8a82 | ||
|
|
9a68ea242c | ||
|
|
10daa1f1dd | ||
|
|
38bb8410e5 | ||
|
|
d35d176a79 | ||
|
|
fe8a380902 | ||
|
|
a8edd53d26 | ||
|
|
00a7fa547e | ||
|
|
b393c7448b | ||
|
|
46f80555f7 | ||
|
|
0aee729e8e | ||
|
|
06c8c44efc | ||
|
|
6df3383585 | ||
|
|
f912a452dc | ||
|
|
ea697bd884 | ||
|
|
6e7b087cff | ||
|
|
87b5327a42 | ||
|
|
1b1a0e99e8 | ||
|
|
2828319d0a | ||
|
|
d3c87fd95a | ||
|
|
964cc91548 | ||
|
|
a2e410c4cb | ||
|
|
9055154781 | ||
|
|
822a4120c7 | ||
|
|
bc60d0678b | ||
|
|
9aa7ad0221 | ||
|
|
e965d654c5 | ||
|
|
82d6efac76 | ||
|
|
de51746bfc | ||
|
|
157367ddb6 | ||
|
|
6de9697aa9 | ||
|
|
1dfdbaf1f0 | ||
|
|
1fe1cd6f75 | ||
|
|
dcd5e3ac9f | ||
|
|
aa44c09ec4 | ||
|
|
281e8b737e | ||
|
|
b5ce8e9fbb | ||
|
|
0b17b253d9 | ||
|
|
faffc76a76 | ||
|
|
20fbfb91ca | ||
|
|
4acdd41837 | ||
|
|
1f2dba0a3f | ||
|
|
76f07092df | ||
|
|
91a5b5bbfc | ||
|
|
e3164c95df | ||
|
|
1933ec66d9 | ||
|
|
742df16837 | ||
|
|
c742bdab85 | ||
|
|
cd6d166e76 | ||
|
|
e061219aff | ||
|
|
9f1ce45f06 | ||
|
|
dd04564335 | ||
|
|
03254ad4b7 | ||
|
|
f13a007a1c | ||
|
|
9802b7f2e4 | ||
|
|
a2dcca3815 | ||
|
|
7226bcad50 | ||
|
|
63ab1a205e | ||
|
|
b6ab01d100 | ||
|
|
ecb98e2e82 | ||
|
|
c733127134 | ||
|
|
0cce8e9ce7 | ||
|
|
b773c0709f | ||
|
|
d426b15c1c | ||
|
|
b05627d2d6 | ||
|
|
dbd9df41f0 | ||
|
|
abe5d58f9d | ||
|
|
c081433015 | ||
|
|
22563233a3 | ||
|
|
3aaf92090a | ||
|
|
0acbe56cfb |
+14
-14
@@ -1,15 +1,15 @@
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
# http://editorconfig.org
|
||||
|
||||
root = true
|
||||
|
||||
[*]
|
||||
charset = utf-8
|
||||
indent_style = space
|
||||
indent_size = 2
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
|
||||
[*.md]
|
||||
insert_final_newline = false
|
||||
trim_trailing_whitespace = false
|
||||
@@ -4,8 +4,8 @@
|
||||
#### There are no rules, but here are a few things to consider:
|
||||
###### Before you submit an issue:
|
||||
* Do a quick search to see if there are similar issues
|
||||
* Make sure that you are waiting for `deviceready` to fire before interacting with any plugin. If you are using Ionic, this can be done using [the `Platform.ready()` function](http://ionicframework.com/docs/api/platform/Platform/#ready).
|
||||
* **Check that you are using the latest version of** `ionic-native`, you can install the latest version by running `npm i --save @ionic-native/core@latest`
|
||||
* Make sure that you are waiting for `deviceready` to fire before interacting with any plugin. If you are using Ionic 2, this can be done using [the `Platform.ready()` function](http://ionicframework.com/docs/v2/api/platform/Platform/#ready).
|
||||
* **Check that you are using the latest version of** `ionic-native`, you can install the latest version by running `npm i --save ionic-native@latest`
|
||||
|
||||
###### Still having problems? submit an issue with the following details:
|
||||
* Short description of the issue
|
||||
@@ -16,4 +16,4 @@
|
||||
## Feature request?
|
||||
Have a plugin you'd like to see supported? Since Ionic Native is a thin wrapper around existing Cordova plugins, adding support for new plugins is as easy as creating a new wrapper for whatever plugin you'd like to add.
|
||||
|
||||
Take a look at our [Developer Guide](https://github.com/ionic-team/ionic-native/blob/master/DEVELOPER.md) for more info on adding new plugins.
|
||||
Take a look at our [Developer Guide](https://github.com/driftyco/ionic-native/blob/master/DEVELOPER.md) for more info on adding new plugins.
|
||||
@@ -1,28 +0,0 @@
|
||||
**I'm submitting a ...** (check one with "x")
|
||||
[ ] bug report
|
||||
[ ] feature request
|
||||
[ ] support request => Please do not submit support requests here, use one of these channels: https://forum.ionicframework.com/ or https://ionicworldwide.herokuapp.com/
|
||||
|
||||
**Current behavior:**
|
||||
<!-- Describe how the bug manifests. -->
|
||||
|
||||
**Expected behavior:**
|
||||
<!-- Describe what the behavior would be without the bug. -->
|
||||
|
||||
**Steps to reproduce:**
|
||||
<!-- If you are able to illustrate the bug or feature request with an example, please provide steps to reproduce. -->
|
||||
|
||||
**Related code:**
|
||||
|
||||
```
|
||||
insert any relevant code here
|
||||
```
|
||||
|
||||
**Other information:**
|
||||
<!-- List any other information that is relevant to your issue. Stack traces, related issues, suggestions on how to fix, Stack Overflow links, forum links, etc. -->
|
||||
|
||||
**Ionic info:** (run `ionic info` from a terminal/cmd prompt and paste output below):
|
||||
|
||||
```
|
||||
insert the output from ionic info here
|
||||
```
|
||||
+1
-6
@@ -3,10 +3,5 @@ node_modules/
|
||||
.idea
|
||||
.tmp
|
||||
aot/
|
||||
scripts/ionic-native-bower
|
||||
scripts/docs-json/*.json
|
||||
dist/
|
||||
src/@ionic-native/plugins/**/ngx
|
||||
*.d.ts
|
||||
injectable-classes.json
|
||||
|
||||
scripts/ionic-native-bower
|
||||
|
||||
+662
-1958
File diff suppressed because it is too large
Load Diff
@@ -1,11 +0,0 @@
|
||||
# Contributor Code of Conduct
|
||||
|
||||
As contributors and maintainers of the Ionic project, we pledge to respect everyone who contributes by posting issues, updating documentation, submitting pull requests, providing feedback in comments, and any other activities.
|
||||
|
||||
Communication through any of Ionic's channels (GitHub, Slack, Forum, IRC, mailing lists, Twitter, etc.) must be constructive and never resort to personal attacks, trolling, public or private harassment, insults, or other unprofessional conduct.
|
||||
|
||||
We promise to extend courtesy and respect to everyone involved in this project regardless of gender, gender identity, sexual orientation, disability, age, race, ethnicity, religion, or level of experience. We expect anyone contributing to the Ionic project to do the same.
|
||||
|
||||
If any member of the community violates this code of conduct, the maintainers of the Ionic project may take action, removing issues, comments, and PRs or blocking accounts as deemed appropriate.
|
||||
|
||||
If you are subject to or witness unacceptable behavior, or have any other concerns, please email us at [hi@ionicframework.com](mailto:hi@ionicframework.com).
|
||||
+7
-76
@@ -17,7 +17,6 @@ gulp plugin:create -n PluginName
|
||||
gulp plugin:create -m -n PluginName
|
||||
```
|
||||
|
||||
Running the command above will create a new directory `src/@ionic-native/plugins/plugin-name/` with a single file in there: `index.ts`. This file is where all the plugin definitions should be.
|
||||
|
||||
Let's take a look at the existing plugin wrapper for Geolocation to see what goes into an Ionic Native plugin (comments have been removed for clarity):
|
||||
|
||||
@@ -88,6 +87,8 @@ It's just a stub. The `return` is only there to keep the TypeScript type-checker
|
||||
|
||||
By default, the `@Cordova` decorator wraps the plugin callbacks in a Promise that resolves when the success callback is called and rejects when the error callback is called. It also ensures that Cordova and the underlying plugin are available, and prints helpful diagnostics if they aren't.
|
||||
|
||||
You'll also notice that `getCurrentPosition` is a static method. That's because the plugin class is just a utility class to call the underlying Cordova plugin methods, it's not an instance and has no state.
|
||||
|
||||
Next, let's look at the `watchPosition` method.
|
||||
|
||||
```
|
||||
@@ -101,7 +102,7 @@ Next, let's look at the `watchPosition` method.
|
||||
|
||||
The `@Cordova` decorator has a few more options now.
|
||||
|
||||
`observable` indicates that this method may call its callbacks multiple times, so `@Cordova` wraps it in an [`Observable`](https://github.com/ionic-team/ionic-native#promises-and-observables) instead of a Promise.
|
||||
`observable` indicates that this method may call its callbacks multiple times, so `@Cordova` wraps it in an [`Observable`](https://github.com/driftyco/ionic-native#promises-and-observables) instead of a Promise.
|
||||
|
||||
`callbackOrder` refers to the method signature of the underlying Cordova plugin, and tells Ionic Native which arguments are the callbacks to map to the wrapping Promise or Observable. In this case, the signature is [`watchPosition(success, error, options)`](https://github.com/apache/cordova-plugin-geolocation#navigatorgeolocationwatchposition), so we need to tell `@Cordova` that the callbacks are the first arguments, not the last arguments. For rare cases, you can also specify the options `successIndex` and `errorIndex` to indicate where in the argument list the callbacks are located.
|
||||
|
||||
@@ -109,15 +110,15 @@ The `@Cordova` decorator has a few more options now.
|
||||
|
||||
### Testing your changes
|
||||
|
||||
You need to run `npm run build` in the `ionic-native` project, this will create a `dist` directory. The `dist` directory will contain a sub directory `@ionic-native` with all the packages compiled in there. Copy the package(s) you created/modified to your app's node_modules under the `@ionic-native` directory. (e.g. `cp -r dist/@ionic-native/plugin-name ../my-app/node_modules/@ionic-native/`).
|
||||
You need to run `npm run build` in the `ionic-native` project, this will create a `dist` directory. Then, you must go to your ionic application folder and replace your current `node_modules/ionic-native/dist/` with the newly generated one.
|
||||
|
||||
### Cleaning the code
|
||||
|
||||
You need to run `npm run lint` to analyze the code and ensure its consistency with the repository style. Fix any errors before submitting a PR.
|
||||
You need to run `npm run lint` to analyze the code and ensure it's consistency with the repository style. Fix any errors before submitting a PR.
|
||||
|
||||
### 'Wrapping' Up
|
||||
|
||||
That's it! The only thing left to do is rigorously document the plugin and its usage. Take a look at some of the other plugins for good documentation styles.
|
||||
That's it! The only thing left to do is rigorously document the plugin and it's usage. Take a look at some of the other plugins for good documentation styles.
|
||||
|
||||
## Commit Message Format
|
||||
|
||||
@@ -146,74 +147,4 @@ The subject contains succinct description of the change:
|
||||
* use the imperative, present tense: "change" not "changed" nor "changes"
|
||||
* do not capitalize first letter
|
||||
* do not place a period (.) at the end
|
||||
* entire length of the commit message must not go over 50 characters
|
||||
|
||||
|
||||
### Ionic Native Decorators
|
||||
|
||||
#### Plugin
|
||||
A decorator to wrap the main plugin class, and any other classes that will use `@Cordova` or `@CordovaProperty` decorators. This decorator accepts the following configuration:
|
||||
- *pluginName*: Plugin name, this should match the class name
|
||||
- *plugin*: The plugin's NPM package, or Github URL if NPM is not available.
|
||||
- *pluginRef*: The plugin object reference. Example: 'cordova.file'.
|
||||
- *repo*: The plugin's Github Repository URL
|
||||
- *install*: (optional) Install command. This is used in case a plugin has a custom install command (takes variables).
|
||||
- *platforms*: An array of strings indicating the supported platforms.
|
||||
|
||||
#### Cordova
|
||||
Checks if the plugin and the method are available before executing. By default, the decorator will wrap the callbacks of the function and return a Promise. This decorator takes the following configuration options:
|
||||
- **observable**: set to true to return an Observable
|
||||
- **clearFunction**: an optional name of a method to clear the observable we returned
|
||||
- **clearWithArgs**: This can be used if clearFunction is set. Set this to true to call the clearFunction with the same arguments used in the initial function.
|
||||
- **sync**: set to true if the method should return the value as-is without wrapping with Observable/Promise
|
||||
- **callbackOrder**: set to `reverse` if the success and error callbacks are the first two arguements of the method
|
||||
- **callbackStyle**: set to `node` if the plugin has one callback with a node style (e.g: `function(err, result){}`), or set to `object` if the callbacks are part of an object
|
||||
- **successName**: Success function property name. This must be set if callbackStyle is set to object.
|
||||
- **errorName**: Error function property name. This must be set if callbackStyle is set to object.
|
||||
- **successIndex**: Set a custom index for the success callback function. This doesn't work if callbackOrder or callbackStyle are set.
|
||||
- **errorIndex**: Set a custom index for the error callback function. This doesn't work if callbackOrder or callbackStyle are set.
|
||||
- **eventObservable**: set to true to return an observable that wraps an event listener
|
||||
- **event**: Event name, this must be set if eventObservable is set to true
|
||||
- **element**: Element to attach the event listener to, this is optional, defaults to `window`
|
||||
- **otherPromise**: Set to true if the wrapped method returns a promise
|
||||
- **platforms**: array of strings indicating supported platforms. Specify this if the supported platforms doesn't match the plugin's supported platforms.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
@Cordova()
|
||||
someMethod(): Promise<any> { return; }
|
||||
|
||||
@Cordova({ sync: true })
|
||||
syncMethod(): number { }
|
||||
```
|
||||
|
||||
#### CordovaProperty
|
||||
Checks if the plugin and property exist before getting/setting the property's value
|
||||
|
||||
Example:
|
||||
```ts
|
||||
@CordovaProperty()
|
||||
someProperty: string;
|
||||
```
|
||||
|
||||
#### CordovaCheck
|
||||
Checks if the plugin exists before performing a custom written method. By default, the method will return a promise that will reject with an error if the plugin is not available. This wrapper accepts two optional configurations:
|
||||
- **observable**: set to true to return an empty Observable if the plugin isn't available
|
||||
- **sync**: set to true to return nothing if the plugin isn't available
|
||||
|
||||
Example:
|
||||
```ts
|
||||
@CordovaCheck()
|
||||
someMethod(): Promise<any> {
|
||||
// anything here will only run if the plugin is available
|
||||
}
|
||||
```
|
||||
|
||||
#### CordovaFunctionOverride
|
||||
Wrap a stub function in a call to a Cordova plugin, checking if both Cordova and the required plugin are installed.
|
||||
|
||||
Example:
|
||||
```ts
|
||||
@CordovaFunctionOverride()
|
||||
someMethod(): Observable<any> { return; }
|
||||
```
|
||||
* entire length of the commit message must not go over 50 characters
|
||||
@@ -1,23 +1,23 @@
|
||||
Copyright 2015-present Drifty Co.
|
||||
http://drifty.com/
|
||||
|
||||
MIT License
|
||||
|
||||
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.
|
||||
Copyright 2015-present Drifty Co.
|
||||
http://drifty.com/
|
||||
|
||||
MIT License
|
||||
|
||||
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.
|
||||
|
||||
@@ -1,222 +1,95 @@
|
||||
[](https://circleci.com/gh/ionic-team/ionic-native) [](http://commitizen.github.io/cz-cli/) 
|
||||
[](https://circleci.com/gh/driftyco/ionic-native) [](http://commitizen.github.io/cz-cli/)
|
||||
[](https://www.npmjs.com/package/ionic-native)
|
||||
|
||||
[](https://nodei.co/npm/ionic-native/)
|
||||
[](https://nodei.co/npm/ionic-native/)
|
||||
|
||||
# Ionic Native
|
||||
|
||||
Ionic Native is a curated set of wrappers for Cordova plugins that make adding any native functionality you need to your [Ionic](https://ionicframework.com/) mobile app easy.
|
||||
Ionic Native is a curated set of wrappers for Cordova plugins that make adding any native functionality you need to your [Ionic](http://ionicframework.com/), Cordova, or Web View mobile app easy.
|
||||
|
||||
Ionic Native wraps plugin callbacks in a Promise or Observable, providing a common interface for all plugins and making it easy to use plugins with Angular change detection.
|
||||
### Documentation
|
||||
|
||||
## Installation
|
||||
For the full Ionic Native documentation, please visit [http://ionicframework.com/docs/v2/native/](http://ionicframework.com/docs/v2/native/).
|
||||
|
||||
Run following command to install Ionic Native in your project.
|
||||
### Promises and Observables
|
||||
|
||||
```bash
|
||||
npm install @ionic-native/core --save
|
||||
Ionic Native wraps plugin callbacks in a Promise or [Observable](https://gist.github.com/staltz/868e7e9bc2a7b8c1f754), providing a common interface for all plugins and ensuring that native events trigger change detection in Angular 2.
|
||||
|
||||
```
|
||||
import { Geolocation } from 'ionic-native';
|
||||
|
||||
Geolocation.getCurrentPosition().then(pos => {
|
||||
console.log('lat: ' + pos.coords.latitude + ', lon: ' + pos.coords.longitude);
|
||||
});
|
||||
|
||||
let watch = Geolocation.watchPosition().subscribe(pos => {
|
||||
console.log('lat: ' + pos.coords.latitude + ', lon: ' + pos.coords.longitude);
|
||||
});
|
||||
|
||||
// to stop watching
|
||||
watch.unsubscribe();
|
||||
```
|
||||
|
||||
You also need to install the Ionic Native package for each plugin you want to add. Please see the [Ionic Native documentation](https://ionicframework.com/docs/native/) for complete instructions on how to add and use the plugins.
|
||||
### Angular 1
|
||||
|
||||
## Documentation
|
||||
Ionic Native works as a stand-in for [ngCordova](http://ngcordova.com/). In many cases, the usage is identical, but we import `ionic.native` instead of `ngCordova` as our module.
|
||||
|
||||
For the full Ionic Native documentation, please visit [https://ionicframework.com/docs/native/](https://ionicframework.com/docs/native/).
|
||||
As a rule of thumb: take the ES6 class name of the plugin and add `$cordova` to get the service name. For example, `Geolocation` would be `$cordovaGeolocation`, and `Camera` will be `$cordovaCamera`:
|
||||
|
||||
### Basic Usage
|
||||
```javascript
|
||||
angular.module('myApp', ['ionic', 'ionic.native'])
|
||||
|
||||
#### Ionic/Angular apps
|
||||
To use a plugin, import and add the plugin provider to your `@NgModule`, and then inject it where you wish to use it.
|
||||
Make sure to import the injectable class from the `/ngx` directory as shown in the following examples:
|
||||
|
||||
```typescript
|
||||
// app.module.ts
|
||||
import { Camera } from '@ionic-native/camera/ngx';
|
||||
|
||||
...
|
||||
|
||||
@NgModule({
|
||||
...
|
||||
|
||||
providers: [
|
||||
...
|
||||
Camera
|
||||
...
|
||||
]
|
||||
...
|
||||
})
|
||||
export class AppModule { }
|
||||
```
|
||||
|
||||
```typescript
|
||||
import { Geolocation } from '@ionic-native/geolocation/ngx';
|
||||
import { Platform } from 'ionic-angular';
|
||||
|
||||
@Component({ ... })
|
||||
export class MyComponent {
|
||||
|
||||
constructor(private geolocation: Geolocation, private platform: Platform) {
|
||||
|
||||
this.platform.ready().then(() => {
|
||||
|
||||
// get position
|
||||
this.geolocation.getCurrentPosition().then(pos => {
|
||||
console.log(`lat: ${pos.coords.latitude}, lon: ${pos.coords.longitude}`)
|
||||
});
|
||||
|
||||
|
||||
// watch position
|
||||
const watch = geolocation.watchPosition().subscribe(pos => {
|
||||
console.log(`lat: ${pos.coords.latitude}, lon: ${pos.coords.longitude}`)
|
||||
});
|
||||
|
||||
// to stop watching
|
||||
watch.unsubscribe();
|
||||
.controller('MyCtrl', function($scope, $cordovaCamera) {
|
||||
$scope.takePicture = function() {
|
||||
$cordovaCamera.getPicture(opts).then(function(p) {
|
||||
}, function(err) {
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
```
|
||||
|
||||
#### ES2015+/TypeScript
|
||||
These modules can work in any ES2015+/TypeScript app (including Angular/Ionic apps). To use any plugin, import the class from the appropriate package, and use it's static methods.
|
||||
```js
|
||||
import { Camera } from '@ionic-native/camera';
|
||||
|
||||
document.addEventListener('deviceready', () => {
|
||||
Camera.getPicture()
|
||||
.then((data) => console.log('Took a picture!', data))
|
||||
.catch((e) => console.log('Error occurred while taking a picture', e));
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
#### AngularJS
|
||||
Ionic Native generates an AngularJS module in runtime and prepares a service for each plugin. To use the plugins in your AngularJS app:
|
||||
1. Download the latest bundle from the [Github releases](https://github.com/ionic-team/ionic-native/releases) page.
|
||||
2. Include it in `index.html` before your app's code.
|
||||
3. Inject `ionic.native` module in your app.
|
||||
4. Inject any plugin you would like to use with a `$cordova` prefix.
|
||||
For services that return observables, the Angular 1 digest cycle must be done manually (currently):
|
||||
|
||||
```js
|
||||
angular.module('myApp', ['ionic.native'])
|
||||
.controller('MyPageController', function($cordovaCamera) {
|
||||
$cordovaCamera.getPicture()
|
||||
.then(
|
||||
function(data) {
|
||||
console.log('Took a picture!', data);
|
||||
},
|
||||
function(err) {
|
||||
console.log('Error occurred while taking a picture', err);
|
||||
}
|
||||
);
|
||||
});
|
||||
```
|
||||
```javascript
|
||||
angular.module('myApp', ['ionic', 'ionic.native'])
|
||||
|
||||
#### Vanilla JS
|
||||
To use Ionic Native in any other setup:
|
||||
1. Download the latest bundle from the [Github releases](https://github.com/ionic-team/ionic-native/releases) page.
|
||||
2. Include it in `index.html` before your app's code.
|
||||
3. Access any plugin using the global `IonicNative` variable.
|
||||
|
||||
```js
|
||||
document.addEventListener('deviceready', function() {
|
||||
IonicNative.Camera.getPicture()
|
||||
.then(
|
||||
function(data) {
|
||||
console.log('Took a picture!', data);
|
||||
},
|
||||
function(err) {
|
||||
console.log('Error occurred while taking a picture', err);
|
||||
}
|
||||
);
|
||||
.controller('MyCtrl', function($scope, $cordovaGeolocation) {
|
||||
$scope.takePicture = function() {
|
||||
$cordovaGeolocation.watchPosition(opts).subscribe(function(p) {
|
||||
$scope.$apply(function() {
|
||||
$scope.position = p.coords;
|
||||
});
|
||||
}, function(err) {
|
||||
});
|
||||
};
|
||||
});
|
||||
```
|
||||
|
||||
|
||||
### Mocking and Browser Development (Ionic/Angular apps only)
|
||||
|
||||
Ionic Native makes it possible to mock plugins and develop nearly the entirety of your app in the browser or in `ionic serve`.
|
||||
|
||||
To do this, you need to provide a mock implementation of the plugins you wish to use. Here's an example of mocking the `Camera` plugin to return a stock image while in development:
|
||||
|
||||
First import the `Camera` class in your `src/app/app.module.ts` file:
|
||||
|
||||
```typescript
|
||||
import { Camera } from '@ionic-native/camera/ngx';
|
||||
```
|
||||
|
||||
Then create a new class that extends the `Camera` class with a mock implementation:
|
||||
|
||||
```typescript
|
||||
class CameraMock extends Camera {
|
||||
getPicture(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve('BASE_64_ENCODED_DATA_GOES_HERE');
|
||||
});
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
Finally, override the previous `Camera` class in your `providers` for this module:
|
||||
|
||||
```typescript
|
||||
providers: [{ provide: Camera, useClass: CameraMock }];
|
||||
```
|
||||
|
||||
Here's the full example:
|
||||
|
||||
```typescript
|
||||
import { ErrorHandler, NgModule } from '@angular/core';
|
||||
import { BrowserModule } from '@angular/platform-browser';
|
||||
import { IonicApp, IonicModule, IonicErrorHandler } from 'ionic-angular';
|
||||
import { MyApp } from './app.component';
|
||||
import { HomePage } from '../pages/home/home';
|
||||
|
||||
import { Camera } from '@ionic-native/camera/ngx';
|
||||
|
||||
import { HomePage } from '../pages/home/home';
|
||||
import { MyApp } from './app.component';
|
||||
|
||||
class CameraMock extends Camera {
|
||||
getPicture(options) {
|
||||
return new Promise((resolve, reject) => {
|
||||
resolve('BASE_64_ENCODED_DATA_GOES_HERE');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@NgModule({
|
||||
declarations: [MyApp, HomePage],
|
||||
imports: [BrowserModule, IonicModule.forRoot(MyApp)],
|
||||
bootstrap: [IonicApp],
|
||||
entryComponents: [MyApp, HomePage],
|
||||
providers: [
|
||||
{ provide: ErrorHandler, useClass: IonicErrorHandler },
|
||||
{ provide: Camera, useClass: CameraMock }
|
||||
]
|
||||
})
|
||||
export class AppModule {}
|
||||
```
|
||||
|
||||
### Runtime Diagnostics
|
||||
|
||||
Spent way too long diagnosing an issue only to realize a plugin wasn't firing or installed? Ionic Native lets you know what the issue is and how you can resolve it.
|
||||
|
||||

|
||||

|
||||
|
||||
## Installation
|
||||
|
||||
Run following commmand to install ionic-native in your project.
|
||||
```
|
||||
npm install ionic-native --save
|
||||
```
|
||||
|
||||
|
||||
## Plugin Missing?
|
||||
|
||||
Let us know or submit a PR! Take a look at [the Developer Guide](https://github.com/ionic-team/ionic-native/blob/master/DEVELOPER.md) for more on how to contribute. :heart:
|
||||
Let us know or submit a PR! Take a look at [the Developer Guide](https://github.com/driftyco/ionic-native/blob/master/DEVELOPER.md) for more on how to contribute. :heart:
|
||||
|
||||
|
||||
# Credits
|
||||
|
||||
Ibby Hadeed - [@ihadeed](https://github.com/ihadeed)
|
||||
Ibby Hadeed - [@ihadeed](http://github.com/ihadeed)
|
||||
|
||||
Daniel Sogl - [@sogldaniel](https://twitter.com/sogldaniel)
|
||||
Tim Lancina - [@timlancina](http://twitter.com/timlancina)
|
||||
|
||||
Tim Lancina - [@timlancina](https://twitter.com/timlancina)
|
||||
|
||||
Mike Hartington - [@mhartington](https://twitter.com/mhartington)
|
||||
|
||||
Max Lynch - [@maxlynch](https://twitter.com/maxlynch)
|
||||
Max Lynch - [@maxlynch](http://twitter.com/maxlynch)
|
||||
|
||||
Rob Wormald - [@robwormald](https://twitter.com/robwormald)
|
||||
|
||||
+26
-51
@@ -1,51 +1,26 @@
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
working_directory: ~/ionic-native/
|
||||
docker:
|
||||
- image: node:10
|
||||
steps:
|
||||
- checkout
|
||||
- restore_cache:
|
||||
key: ionic-site-{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: Prepare ionic-site repo
|
||||
command: |
|
||||
if [ "${CIRCLE_BRANCH}" == "master" ]; then
|
||||
./scripts/docs/prepare.sh
|
||||
fi
|
||||
- save_cache:
|
||||
key: ionic-site-{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ~/ionic-site/
|
||||
- restore_cache:
|
||||
key: node_modules_{{ checksum "package.json" }}
|
||||
- run:
|
||||
name: Install node modules
|
||||
command: npm ci
|
||||
- save_cache:
|
||||
key: node_modules_{{ checksum "package.json" }}
|
||||
paths:
|
||||
- ~/ionic-native/node_modules/
|
||||
- run:
|
||||
name: Run tslint
|
||||
command: npm run lint
|
||||
- run: bash ./scripts/git/config.sh
|
||||
- run:
|
||||
name: Build Ionic Native
|
||||
command: npm run build
|
||||
- run:
|
||||
name: Generate README files to ensure docs are valid
|
||||
command: npm run readmes
|
||||
- run:
|
||||
name: Run tests
|
||||
command: npm test
|
||||
- add_ssh_keys
|
||||
- deploy:
|
||||
name: Update docs
|
||||
command: |
|
||||
if [ "${CIRCLE_BRANCH}" == "master" ]; then
|
||||
./scripts/docs/update_docs.sh
|
||||
else
|
||||
echo "We are on ${CIRCLE_BRANCH} branch, not going to update docs."
|
||||
fi
|
||||
machine:
|
||||
node:
|
||||
version: 7.10.0
|
||||
ruby:
|
||||
version: 2.1.2
|
||||
|
||||
general:
|
||||
branches:
|
||||
only:
|
||||
- master # ignore PRs and branches
|
||||
|
||||
dependencies:
|
||||
pre:
|
||||
- ./scripts/docs/prepare.sh
|
||||
cache_directories:
|
||||
- "~/ionic-site" # cache ionic-site
|
||||
|
||||
test:
|
||||
override:
|
||||
- npm run build
|
||||
|
||||
deployment:
|
||||
staging:
|
||||
branch: master
|
||||
commands:
|
||||
- ./scripts/docs/update_docs.sh
|
||||
|
||||
+35
-39
@@ -1,51 +1,47 @@
|
||||
'use strict';
|
||||
var gulp = require('gulp');
|
||||
var minimist = require('minimist');
|
||||
var rename = require("gulp-rename");
|
||||
var tslint = require('gulp-tslint');
|
||||
var decamelize = require('decamelize');
|
||||
var replace = require('gulp-replace');
|
||||
|
||||
const gulp = require('gulp'),
|
||||
minimist = require('minimist'),
|
||||
rename = require('gulp-rename'),
|
||||
tslint = require('gulp-tslint'),
|
||||
replace = require('gulp-replace'),
|
||||
_ = require('lodash');
|
||||
|
||||
const flagConfig = {
|
||||
string: ['port', 'version', 'ngVersion', 'animations'],
|
||||
boolean: ['dry-run'],
|
||||
alias: { p: 'port', v: 'version', a: 'ngVersion' },
|
||||
default: { port: 8000 }
|
||||
},
|
||||
flags = minimist(process.argv.slice(2), flagConfig);
|
||||
var flagConfig = {
|
||||
string: ['port', 'version', 'ngVersion', 'animations'],
|
||||
boolean: ['dry-run'],
|
||||
alias: {'p': 'port', 'v': 'version', 'a': 'ngVersion'},
|
||||
default: { port: 8000 }
|
||||
};
|
||||
var flags = minimist(process.argv.slice(2), flagConfig);
|
||||
|
||||
/* Docs tasks */
|
||||
require('./scripts/docs/gulp-tasks')(gulp, flags);
|
||||
|
||||
gulp.task('lint', () => {
|
||||
return gulp
|
||||
.src('src/**/*.ts')
|
||||
.pipe(
|
||||
tslint({
|
||||
formatter: 'verbose',
|
||||
configuration: 'tslint.json'
|
||||
})
|
||||
)
|
||||
.pipe(tslint.report());
|
||||
gulp.task('lint', function() {
|
||||
gulp.src('src/**/*.ts')
|
||||
.pipe(tslint({
|
||||
formatter: "verbose",
|
||||
configuration: 'tslint.json'
|
||||
}))
|
||||
.pipe(tslint.report())
|
||||
});
|
||||
|
||||
gulp.task('plugin:create', () => {
|
||||
if (flags.n && flags.n !== '') {
|
||||
const src = flags.m ? './scripts/templates/wrap-min.tmpl' : './scripts/templates/wrap.tmpl',
|
||||
pluginName = flags.n,
|
||||
spaced = pluginName.replace(/(?!^)([A-Z])/g, ' $1'),
|
||||
kebabCase = _.kebabCase(pluginName);
|
||||
gulp.task('plugin:create', function(){
|
||||
if(flags.n && flags.n !== ''){
|
||||
|
||||
return gulp
|
||||
.src(src)
|
||||
.pipe(replace('{{ PluginName }}', pluginName))
|
||||
.pipe(replace('{{ Plugin_Name }}', spaced))
|
||||
.pipe(replace('{{ pluginName }}', _.lowerFirst(pluginName)))
|
||||
.pipe(replace('{{ plugin-name }}', kebabCase))
|
||||
const src = flags.m?'./scripts/templates/wrap-min.tmpl':'./scripts/templates/wrap.tmpl',
|
||||
pluginName = flags.n,
|
||||
pluginPackageName = decamelize(pluginName, '-'),
|
||||
pluginNameSpaced = pluginName.replace(/(?!^)([A-Z])/g, ' $1');
|
||||
|
||||
return gulp.src(src)
|
||||
.pipe(replace('PluginName', pluginName))
|
||||
.pipe(replace('Plugin Name', pluginNameSpaced))
|
||||
.pipe(rename('index.ts'))
|
||||
.pipe(gulp.dest('./src/@ionic-native/plugins/' + kebabCase));
|
||||
.pipe(gulp.dest('./src/@ionic-native/plugins/' + pluginPackageName));
|
||||
|
||||
} else {
|
||||
console.log('Usage is: gulp plugin:create -n PluginName');
|
||||
|
||||
console.log("Usage is: gulp plugin:create -n PluginName");
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
Generated
-16562
File diff suppressed because it is too large
Load Diff
+38
-76
@@ -1,87 +1,49 @@
|
||||
{
|
||||
"name": "ionic-native",
|
||||
"version": "5.6.1",
|
||||
"version": "3.1.0-rc.6",
|
||||
"description": "Native plugin wrappers for Cordova and Ionic with TypeScript, ES6+, Promise and Observable support",
|
||||
"homepage": "https://ionicframework.com/",
|
||||
"author": "Ionic Team <hi@ionic.io> (https://ionic.io)",
|
||||
"license": "MIT",
|
||||
"scripts": {
|
||||
"test": "jest",
|
||||
"test:watch": "jest --watch",
|
||||
"build:core": "tsc -p tsconfig.core.json",
|
||||
"build:esm": "ts-node -P scripts/tsconfig.json scripts/tasks/build-esm",
|
||||
"build:es5": "ts-node -P scripts/tsconfig.json scripts/tasks/build-es5",
|
||||
"build:ngx": "ts-node -P scripts/tsconfig.json scripts/tasks/build-ngx",
|
||||
"build": "npm run build:core && npm run build:esm && npm run build:ngx && npm run build:es5",
|
||||
"prebuild": "rimraf -rf dist",
|
||||
"npmpub": "ts-node -P scripts/tsconfig.json scripts/tasks/publish",
|
||||
"lint": "gulp lint",
|
||||
"readmes": "gulp readmes",
|
||||
"docs-json": "ts-node -P scripts/tsconfig.json scripts/docs-json",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0",
|
||||
"postchangelog": "git commit -am \"chore(): update changelog\"",
|
||||
"shipit": "npm run build && npm run readmes && npm run npmpub"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@angular/common": "^7.2.15",
|
||||
"@angular/compiler": "^7.2.15",
|
||||
"@angular/compiler-cli": "^7.2.15",
|
||||
"@angular/core": "^7.2.15",
|
||||
"@types/cordova": "0.0.34",
|
||||
"@types/fs-extra": "^7.0.0",
|
||||
"@types/jest": "^24.0.13",
|
||||
"@types/lodash": "^4.14.132",
|
||||
"@types/node": "^10.14.7",
|
||||
"@types/rimraf": "^2.0.2",
|
||||
"@types/webpack": "^4.4.32",
|
||||
"ajv": "^6.10.0",
|
||||
"async-promise-queue": "^1.0.5",
|
||||
"conventional-changelog-cli": "^2.0.21",
|
||||
"cz-conventional-changelog": "^2.1.0",
|
||||
"dgeni": "^0.4.12",
|
||||
"@angular/compiler": "2.4.8",
|
||||
"@angular/compiler-cli": "2.4.8",
|
||||
"@angular/core": "2.4.8",
|
||||
"canonical-path": "0.0.2",
|
||||
"child-process-promise": "2.2.0",
|
||||
"conventional-changelog-cli": "1.2.0",
|
||||
"cpr": "2.0.2",
|
||||
"cz-conventional-changelog": "1.2.0",
|
||||
"decamelize": "1.2.0",
|
||||
"dgeni": "0.4.7",
|
||||
"dgeni-packages": "0.16.10",
|
||||
"fs-extra": "^8.0.1",
|
||||
"fs-extra": "2.0.0",
|
||||
"fs-extra-promise": "0.4.1",
|
||||
"gulp": "3.9.1",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-replace": "^1.0.0",
|
||||
"gulp-tslint": "^8.1.4",
|
||||
"jest": "^24.8.0",
|
||||
"lodash": "^4.17.11",
|
||||
"minimist": "1.2.0",
|
||||
"natives": "^1.1.6",
|
||||
"rimraf": "^2.6.3",
|
||||
"rxjs": "^6.5.2",
|
||||
"ts-jest": "^24.0.2",
|
||||
"ts-node": "^8.2.0",
|
||||
"tslint": "^5.16.0",
|
||||
"tslint-ionic-rules": "0.0.21",
|
||||
"typedoc": "^0.14.2",
|
||||
"typescript": "3.2.4",
|
||||
"uglifyjs-webpack-plugin": "^2.1.3",
|
||||
"unminified-webpack-plugin": "^2.0.0",
|
||||
"webpack": "^4.32.2",
|
||||
"winston": "^3.2.1",
|
||||
"zone.js": "^0.8.29"
|
||||
"gulp-rename": "1.2.2",
|
||||
"gulp-replace": "0.5.4",
|
||||
"gulp-tslint": "6.1.2",
|
||||
"lodash": "4.17.4",
|
||||
"minimist": "1.1.3",
|
||||
"node-html-encoder": "0.0.2",
|
||||
"q": "1.4.1",
|
||||
"queue": "4.2.1",
|
||||
"rimraf": "2.5.4",
|
||||
"rxjs": "5.0.1",
|
||||
"semver": "5.3.0",
|
||||
"tslint": "3.15.1",
|
||||
"tslint-ionic-rules": "0.0.7",
|
||||
"typescript": "2.0.09",
|
||||
"zone.js": "0.7.2"
|
||||
},
|
||||
"jest": {
|
||||
"transform": {
|
||||
"^.+\\.tsx?$": "ts-jest"
|
||||
},
|
||||
"testRegex": "(/__tests__/.*|(\\.|/)(test|spec))\\.(js?|ts?)$",
|
||||
"moduleFileExtensions": [
|
||||
"ts",
|
||||
"tsx",
|
||||
"js",
|
||||
"jsx",
|
||||
"json"
|
||||
]
|
||||
},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "git+https://github.com/ionic-team/ionic-native.git"
|
||||
},
|
||||
"bugs": {
|
||||
"url": "https://github.com/ionic-team/ionic-native/issues"
|
||||
"scripts": {
|
||||
"start": "npm run test:watch",
|
||||
"lint": "gulp lint",
|
||||
"build": "npm run clean && npm run lint && npm run build:core && npm run build:modules",
|
||||
"build:core": "ngc -p scripts/build/tsconfig-core.json",
|
||||
"build:modules": "node scripts/build/build.js",
|
||||
"clean": "rimraf dist",
|
||||
"shipit": "npm run build && gulp readmes && npm run npmpub",
|
||||
"npmpub": "node scripts/build/publish.js",
|
||||
"changelog": "conventional-changelog -p angular -i CHANGELOG.md -s -r 0"
|
||||
},
|
||||
"config": {
|
||||
"commitizen": {
|
||||
|
||||
@@ -0,0 +1,135 @@
|
||||
// Node module dependencies
|
||||
const fs = require('fs-extra-promise').useFs(require('fs-extra')),
|
||||
queue = require('queue'),
|
||||
path = require('path'),
|
||||
exec = require('child_process').exec;
|
||||
|
||||
// Constants for the build process. Paths and JSON files templates
|
||||
const ROOT = path.resolve(path.join(__dirname, '../../')), // root ionic-native directory
|
||||
PLUGINS_PATH = path.resolve(ROOT, 'src/@ionic-native/plugins'), // path to plugins source files
|
||||
CORE_PACKAGE_JSON = require(path.resolve(__dirname, 'core-package.json')), // core package.json
|
||||
PLUGIN_PACKAGE_JSON = require(path.resolve(__dirname, 'plugin-package.json')), // plugin package.json template
|
||||
PLUGIN_TS_CONFIG = require(path.resolve(__dirname, 'tsconfig-plugin.json')), // plugin tsconfig template
|
||||
BUILD_TMP = path.resolve(ROOT, '.tmp'), // tmp directory path
|
||||
BUILD_DIST_ROOT = path.resolve(ROOT, 'dist/packages-dist/@ionic-native'), // dist directory root path
|
||||
BUILD_PLUGINS_DIST = path.resolve(BUILD_DIST_ROOT, 'plugins'), // plugins dist directory path
|
||||
BUILD_CORE_DIST = path.resolve(BUILD_DIST_ROOT, 'core'); // core dist directory path
|
||||
|
||||
|
||||
// dependency versions
|
||||
const ANGULAR_VERSION = '2.4.8',
|
||||
RXJS_VERSION = '5.0.1',
|
||||
IONIC_NATIVE_VERSION = require(path.resolve(ROOT, 'package.json')).version;
|
||||
|
||||
// package dependencies
|
||||
const CORE_PEER_DEPS = {
|
||||
'rxjs': RXJS_VERSION
|
||||
};
|
||||
|
||||
const PLUGIN_PEER_DEPS = {
|
||||
'@ionic-native/core': IONIC_NATIVE_VERSION,
|
||||
'@angular/core': ANGULAR_VERSION,
|
||||
'rxjs': RXJS_VERSION
|
||||
};
|
||||
|
||||
// set peer dependencies for all plugins
|
||||
PLUGIN_PACKAGE_JSON.peerDependencies = PLUGIN_PEER_DEPS;
|
||||
|
||||
|
||||
// Delete dist directory and any temporary files
|
||||
console.log('Removing old TMP directory');
|
||||
fs.removeSync(BUILD_TMP);
|
||||
fs.removeSync(BUILD_PLUGINS_DIST);
|
||||
|
||||
|
||||
// Create tmp/dist directories
|
||||
console.log('Making new TMP directory');
|
||||
fs.mkdirpSync(BUILD_TMP);
|
||||
|
||||
|
||||
// Prepare and copy the core module's package.json
|
||||
console.log('Preparing core module package.json');
|
||||
CORE_PACKAGE_JSON.version = IONIC_NATIVE_VERSION;
|
||||
CORE_PACKAGE_JSON.peerDependencies = CORE_PEER_DEPS;
|
||||
fs.writeJsonSync(path.resolve(BUILD_CORE_DIST, 'package.json'), CORE_PACKAGE_JSON);
|
||||
|
||||
|
||||
// Fetch a list of the plugins
|
||||
const PLUGINS = fs.readdirSync(PLUGINS_PATH);
|
||||
|
||||
|
||||
// Create a queue to process tasks
|
||||
const QUEUE = queue({
|
||||
concurrency: require('os').cpus().length
|
||||
});
|
||||
|
||||
|
||||
// Function to process a single plugin
|
||||
const addPluginToQueue = pluginName => {
|
||||
|
||||
QUEUE.push((callback) => {
|
||||
|
||||
console.log(`Building plugin: ${pluginName}`);
|
||||
|
||||
const PLUGIN_BUILD_DIR = path.resolve(BUILD_TMP, 'plugins', pluginName),
|
||||
PLUGIN_SRC_PATH = path.resolve(PLUGINS_PATH, pluginName, 'index.ts');
|
||||
|
||||
let tsConfigPath;
|
||||
|
||||
fs.mkdirpAsync(PLUGIN_BUILD_DIR) // create tmp build dir
|
||||
.then(() => fs.mkdirpAsync(path.resolve(BUILD_PLUGINS_DIST, pluginName))) // create dist dir
|
||||
.then(() => {
|
||||
|
||||
// Write tsconfig.json
|
||||
const tsConfig = JSON.parse(JSON.stringify(PLUGIN_TS_CONFIG));
|
||||
tsConfig.files = [PLUGIN_SRC_PATH];
|
||||
// tsConfig.compilerOptions.paths['@ionic-native/core'] = [BUILD_CORE_DIST];
|
||||
|
||||
tsConfigPath = path.resolve(PLUGIN_BUILD_DIR, 'tsconfig.json');
|
||||
|
||||
return fs.writeJsonAsync(tsConfigPath, tsConfig);
|
||||
})
|
||||
.then(() => {
|
||||
// clone package.json
|
||||
const packageJson = JSON.parse(JSON.stringify(PLUGIN_PACKAGE_JSON));
|
||||
|
||||
packageJson.name = `@ionic-native/${pluginName}`;
|
||||
packageJson.version = IONIC_NATIVE_VERSION;
|
||||
|
||||
return fs.writeJsonAsync(path.resolve(BUILD_PLUGINS_DIST, pluginName, 'package.json'), packageJson);
|
||||
})
|
||||
.then(() => {
|
||||
|
||||
// compile the plugin
|
||||
exec(`${ROOT}/node_modules/.bin/ngc -p ${tsConfigPath}`, (err, stdout, stderr) => {
|
||||
|
||||
if (err) {
|
||||
// oops! something went wrong.
|
||||
callback(`\n\nBuilding ${pluginName} failed.`);
|
||||
console.log(err);
|
||||
return;
|
||||
}
|
||||
|
||||
// we're done with this plugin!
|
||||
callback();
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.catch(callback);
|
||||
|
||||
}); // QUEUE.push end
|
||||
|
||||
};
|
||||
|
||||
PLUGINS.forEach(addPluginToQueue);
|
||||
|
||||
QUEUE.start((err) => {
|
||||
|
||||
if (err) {
|
||||
console.log('Error building plugins. ', err);
|
||||
} else {
|
||||
console.log('Done processing plugins!');
|
||||
}
|
||||
|
||||
});
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "@ionic-native/core",
|
||||
"version": "{{VERSION}}",
|
||||
"description": "Ionic Native - Native plugins for ionic apps",
|
||||
"module": "index.js",
|
||||
"typings": "index.d.ts",
|
||||
"author": "ionic",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/driftyco/ionic-native.git"
|
||||
}
|
||||
}
|
||||
@@ -1,126 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import { camelCase, clone } from 'lodash';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
export const ROOT = path.resolve(__dirname, '../../');
|
||||
// tslint:disable-next-line:no-var-requires
|
||||
export const TS_CONFIG = clone(require(path.resolve(ROOT, 'tsconfig.json')));
|
||||
export const COMPILER_OPTIONS = TS_CONFIG.compilerOptions;
|
||||
export const PLUGINS_ROOT = path.join(ROOT, 'src/@ionic-native/plugins/');
|
||||
export const PLUGIN_PATHS = fs.readdirSync(PLUGINS_ROOT).map(d => path.join(PLUGINS_ROOT, d, 'index.ts'));
|
||||
|
||||
export function getDecorator(node: ts.Node, index = 0): ts.Decorator {
|
||||
if (node.decorators && node.decorators[index]) {
|
||||
return node.decorators[index];
|
||||
}
|
||||
}
|
||||
|
||||
export function hasDecorator(decoratorName: string, node: ts.Node): boolean {
|
||||
return node.decorators && node.decorators.length && node.decorators.findIndex(d => getDecoratorName(d) === decoratorName) > -1;
|
||||
}
|
||||
|
||||
export function getDecoratorName(decorator: any) {
|
||||
return decorator.expression.expression.text;
|
||||
}
|
||||
|
||||
export function getRawDecoratorArgs(decorator: any): any[] {
|
||||
if (decorator.expression.arguments.length === 0) return [];
|
||||
return decorator.expression.arguments[0].properties;
|
||||
}
|
||||
|
||||
export function getDecoratorArgs(decorator: any) {
|
||||
const properties: any[] = getRawDecoratorArgs(decorator);
|
||||
const args = {};
|
||||
|
||||
properties.forEach(prop => {
|
||||
let val;
|
||||
|
||||
switch (prop.initializer.kind) {
|
||||
case ts.SyntaxKind.StringLiteral:
|
||||
case ts.SyntaxKind.Identifier:
|
||||
val = prop.initializer.text;
|
||||
break;
|
||||
|
||||
case ts.SyntaxKind.ArrayLiteralExpression:
|
||||
val = prop.initializer.elements.map((e: any) => e.text);
|
||||
break;
|
||||
|
||||
case ts.SyntaxKind.TrueKeyword:
|
||||
val = true;
|
||||
break;
|
||||
|
||||
case ts.SyntaxKind.FalseKeyword:
|
||||
val = false;
|
||||
break;
|
||||
|
||||
case ts.SyntaxKind.NumericLiteral:
|
||||
val = Number(prop.initializer.text);
|
||||
break;
|
||||
|
||||
default:
|
||||
Logger.debug('Unexpected property value type: ' + prop.initializer.kind);
|
||||
throw new Error('Unexpected property value type << helpers.ts >>');
|
||||
}
|
||||
|
||||
args[prop.name.text] = val;
|
||||
});
|
||||
|
||||
return args;
|
||||
}
|
||||
|
||||
/**
|
||||
* FROM STENCIL
|
||||
* Convert a js value into typescript AST
|
||||
* @param val array, object, string, boolean, or number
|
||||
* @returns Typescript Object Literal, Array Literal, String Literal, Boolean Literal, Numeric Literal
|
||||
*/
|
||||
export function convertValueToLiteral(val: any) {
|
||||
if (Array.isArray(val)) {
|
||||
return arrayToArrayLiteral(val);
|
||||
}
|
||||
if (typeof val === 'object') {
|
||||
return objectToObjectLiteral(val);
|
||||
}
|
||||
if (typeof val === 'number') {
|
||||
return ts.createNumericLiteral(String(val));
|
||||
}
|
||||
return ts.createLiteral(val);
|
||||
}
|
||||
|
||||
/**
|
||||
* FROM STENCIL
|
||||
* Convert a js object into typescript AST
|
||||
* @param obj key value object
|
||||
* @returns Typescript Object Literal Expression
|
||||
*/
|
||||
function objectToObjectLiteral(obj: { [key: string]: any }): ts.ObjectLiteralExpression {
|
||||
const newProperties: ts.ObjectLiteralElementLike[] = Object.keys(obj).map((key: string): ts.ObjectLiteralElementLike => {
|
||||
return ts.createPropertyAssignment(ts.createLiteral(key), convertValueToLiteral(obj[key]) as ts.Expression);
|
||||
});
|
||||
|
||||
return ts.createObjectLiteral(newProperties);
|
||||
}
|
||||
|
||||
/**
|
||||
* FROM STENCIL
|
||||
* Convert a js array into typescript AST
|
||||
* @param list array
|
||||
* @returns Typescript Array Literal Expression
|
||||
*/
|
||||
function arrayToArrayLiteral(list: any[]): ts.ArrayLiteralExpression {
|
||||
const newList: any[] = list.map(convertValueToLiteral);
|
||||
return ts.createArrayLiteral(newList);
|
||||
}
|
||||
|
||||
export function getMethodsForDecorator(decoratorName: string) {
|
||||
switch (decoratorName) {
|
||||
case 'CordovaProperty': return ['cordovaPropertyGet', 'cordovaPropertySet'];
|
||||
case 'InstanceProperty': return ['instancePropertyGet', 'instancePropertySet'];
|
||||
case 'CordovaCheck': return ['checkAvailability'];
|
||||
case 'InstanceCheck': return ['instanceAvailability'];
|
||||
}
|
||||
|
||||
return [camelCase(decoratorName)];
|
||||
}
|
||||
@@ -1,105 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import * as ngc from '@angular/compiler-cli';
|
||||
import * as rimraf from 'rimraf';
|
||||
import { generateDeclarations } from './transpile';
|
||||
import { clone } from 'lodash';
|
||||
import { EmitFlags } from '@angular/compiler-cli';
|
||||
import { importsTransformer } from './transformers/imports';
|
||||
import { pluginClassTransformer } from './transformers/plugin-class';
|
||||
import { COMPILER_OPTIONS, PLUGIN_PATHS, ROOT } from './helpers';
|
||||
|
||||
export function getProgram(rootNames: string[] = createSourceFiles()) {
|
||||
const options: ngc.CompilerOptions = clone(COMPILER_OPTIONS);
|
||||
options.basePath = ROOT;
|
||||
options.moduleResolution = ts.ModuleResolutionKind.NodeJs;
|
||||
options.module = ts.ModuleKind.ES2015;
|
||||
options.target = ts.ScriptTarget.ES5;
|
||||
options.lib = ['dom', 'es2017'];
|
||||
options.inlineSourceMap = true;
|
||||
options.inlineSources = true;
|
||||
delete options.baseUrl;
|
||||
|
||||
const host: ngc.CompilerHost = ngc.createCompilerHost({ options });
|
||||
|
||||
return ngc.createProgram({
|
||||
rootNames,
|
||||
options,
|
||||
host
|
||||
});
|
||||
}
|
||||
|
||||
// hacky way to export metadata only for core package
|
||||
export function transpileNgxCore() {
|
||||
getProgram([path.resolve(ROOT, 'src/@ionic-native/core/index.ts')]).emit({
|
||||
emitFlags: EmitFlags.Metadata,
|
||||
emitCallback: ({ program, writeFile, customTransformers, cancellationToken, targetSourceFile }) =>
|
||||
program.emit(targetSourceFile, writeFile, cancellationToken, true, customTransformers)
|
||||
});
|
||||
}
|
||||
|
||||
export function transpileNgx() {
|
||||
getProgram().emit({
|
||||
emitFlags: EmitFlags.Metadata,
|
||||
customTransformers: {
|
||||
beforeTs: [
|
||||
importsTransformer(true),
|
||||
pluginClassTransformer(true)
|
||||
]
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function generateDeclarationFiles() {
|
||||
generateDeclarations(PLUGIN_PATHS.map(p => p.replace('index.ts', 'ngx/index.ts')));
|
||||
}
|
||||
|
||||
// remove reference to @ionic-native/core decorators
|
||||
export function modifyMetadata() {
|
||||
PLUGIN_PATHS.map(p => p.replace(path.join(ROOT, 'src'), path.join(ROOT, 'dist')).replace('index.ts', 'ngx/index.metadata.json'))
|
||||
.forEach(p => {
|
||||
const content = fs.readJSONSync(p);
|
||||
let _prop;
|
||||
for (const prop in content[0].metadata) {
|
||||
_prop = content[0].metadata[prop];
|
||||
removeIonicNativeDecorators(_prop);
|
||||
|
||||
if (_prop.members) {
|
||||
for (const memberProp in _prop.members) {
|
||||
removeIonicNativeDecorators(_prop.members[memberProp][0]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fs.writeJSONSync(p, content);
|
||||
});
|
||||
}
|
||||
|
||||
function removeIonicNativeDecorators(node: any) {
|
||||
if (node.decorators && node.decorators.length) {
|
||||
node.decorators = node.decorators.filter((d, i) => d.expression.module !== '@ionic-native/core');
|
||||
}
|
||||
|
||||
if (node.decorators && !node.decorators.length) delete node.decorators;
|
||||
}
|
||||
|
||||
function createSourceFiles(): string[] {
|
||||
return PLUGIN_PATHS.map((indexPath: string) => {
|
||||
const ngxPath = path.resolve(indexPath.replace('index.ts', ''), 'ngx'),
|
||||
newPath = path.resolve(ngxPath, 'index.ts');
|
||||
|
||||
// delete directory
|
||||
rimraf.sync(ngxPath);
|
||||
fs.mkdirpSync(ngxPath);
|
||||
fs.copyFileSync(indexPath, newPath);
|
||||
|
||||
return newPath;
|
||||
});
|
||||
}
|
||||
|
||||
export function cleanupNgx() {
|
||||
PLUGIN_PATHS.forEach((indexPath: string) =>
|
||||
rimraf.sync(indexPath.replace('index.ts', 'ngx'))
|
||||
);
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
{
|
||||
"name": "@ionic-native/{{PLUGIN}}",
|
||||
"version": "{{VERSION}}",
|
||||
"description": "Ionic Native - Native plugins for ionic apps",
|
||||
"module": "index.js",
|
||||
"typings": "index.d.ts",
|
||||
"author": "ionic",
|
||||
"license": "MIT",
|
||||
"peerDependencies": {},
|
||||
"repository": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/driftyco/ionic-native.git"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
// Node module dependencies
|
||||
const fs = require('fs-extra-promise').useFs(require('fs-extra')),
|
||||
queue = require('queue'),
|
||||
path = require('path'),
|
||||
exec = require('child-process-promise').exec;
|
||||
|
||||
|
||||
const ROOT = path.resolve(path.join(__dirname, '../../')),
|
||||
DIST = path.resolve(ROOT, 'dist', 'packages-dist', '@ionic-native'),
|
||||
PLUGINS_ROOT = path.resolve(DIST, 'plugins'),
|
||||
CORE = path.resolve(DIST, 'core');
|
||||
|
||||
const FLAGS = '--access public'; // add any flags here if you want... (example: --tag alpha)
|
||||
|
||||
console.log('Publishing @ionic-native/core');
|
||||
exec(`npm publish ${CORE} ${FLAGS}`)
|
||||
.then(() => {
|
||||
|
||||
const PLUGINS = fs.readdirSync(PLUGINS_ROOT);
|
||||
|
||||
const QUEUE = queue({
|
||||
concurrency: 10
|
||||
});
|
||||
|
||||
PLUGINS.forEach(pluginName => {
|
||||
|
||||
QUEUE.push(done => {
|
||||
|
||||
console.log(`Publishing plugin ${pluginName}`);
|
||||
const pluginPath = path.resolve(PLUGINS_ROOT, pluginName);
|
||||
|
||||
exec(`npm publish ${pluginPath} ${FLAGS}`)
|
||||
.then(() => done())
|
||||
.catch(done);
|
||||
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
QUEUE.start((err) => {
|
||||
|
||||
if (err) {
|
||||
console.log('Error publishing ionic-native. ', err);
|
||||
} else {
|
||||
console.log('Done publishing ionic-native!');
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
})
|
||||
.catch(e => {
|
||||
|
||||
console.log('Publish failed');
|
||||
console.log(e);
|
||||
|
||||
});
|
||||
@@ -1,2 +0,0 @@
|
||||
// removes the __extends method that is added automatically by typescript
|
||||
module.exports = source => source.replace(/var\s__extends\s=\s\(this\s&&[\sa-z\._\(\)\|{}=:\[\]&,;?]+}\)\(\);/i, '');
|
||||
@@ -1,59 +0,0 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import { hasDecorator, ROOT } from '../helpers';
|
||||
|
||||
export interface InjectableClassEntry {
|
||||
file: string;
|
||||
className: string;
|
||||
dirName: string;
|
||||
}
|
||||
|
||||
const injectableClasses: InjectableClassEntry[] = [];
|
||||
export const EMIT_PATH = path.resolve(ROOT, 'injectable-classes.json');
|
||||
|
||||
/**
|
||||
* This transformer extracts all the injectable classes
|
||||
* so we can use all the names later on when we compile
|
||||
* an es5 bundle.
|
||||
*
|
||||
* Every injectable class will end up in the
|
||||
* window['IonicNative'] object.
|
||||
*/
|
||||
export function extractInjectables() {
|
||||
return (ctx: ts.TransformationContext) => {
|
||||
return tsSourceFile => {
|
||||
if (tsSourceFile.fileName.indexOf('src/@ionic-native/plugins') > -1) {
|
||||
ts.visitEachChild(
|
||||
tsSourceFile,
|
||||
node => {
|
||||
if (node.kind !== ts.SyntaxKind.ClassDeclaration) {
|
||||
return node;
|
||||
}
|
||||
|
||||
const isInjectable: boolean = hasDecorator('Injectable', node);
|
||||
if (isInjectable) {
|
||||
injectableClasses.push({
|
||||
file: tsSourceFile.path,
|
||||
className: (node as ts.ClassDeclaration).name.text,
|
||||
dirName: tsSourceFile.path.split(/[\\\/]+/).reverse()[1]
|
||||
});
|
||||
}
|
||||
},
|
||||
ctx
|
||||
);
|
||||
}
|
||||
|
||||
return tsSourceFile;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
export function emitInjectableClasses() {
|
||||
fs.writeJSONSync(EMIT_PATH, injectableClasses);
|
||||
}
|
||||
|
||||
export function cleanEmittedData() {
|
||||
fs.unlinkSync(EMIT_PATH);
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
import { getMethodsForDecorator } from '../helpers';
|
||||
|
||||
function transformImports(file: ts.SourceFile, ctx: ts.TransformationContext, ngcBuild?: boolean) {
|
||||
// remove angular imports
|
||||
if (!ngcBuild) {
|
||||
file.statements = (file.statements as any).filter((s: any) => !(s.kind === ts.SyntaxKind.ImportDeclaration && s.moduleSpecifier.text === '@angular/core'));
|
||||
}
|
||||
|
||||
// find the @ionic-native/core import statement
|
||||
const importStatement = (file.statements as any).find((s: any) => {
|
||||
return s.kind === ts.SyntaxKind.ImportDeclaration && s.moduleSpecifier.text === '@ionic-native/core';
|
||||
});
|
||||
|
||||
// we're only interested in files containing @ionic-native/core import statement
|
||||
if (!importStatement) return file;
|
||||
|
||||
const decorators: string[] = [];
|
||||
|
||||
const decoratorRegex: RegExp = /@([a-zA-Z]+)\(/g;
|
||||
|
||||
const ignored: string [] = ['Plugin', 'Component', 'Injectable'];
|
||||
|
||||
const keep: string [] = ['getPromise', 'checkAvailability'];
|
||||
|
||||
let m;
|
||||
|
||||
while ((m = decoratorRegex.exec(file.text)) !== null) {
|
||||
if (m.index === decoratorRegex.lastIndex) {
|
||||
decoratorRegex.lastIndex++;
|
||||
}
|
||||
if (m && m[1] && decorators.indexOf(m[1]) === -1 && ignored.indexOf(m[1]) === -1) decorators.push(m[1]);
|
||||
}
|
||||
|
||||
if (decorators.length) {
|
||||
let methods = [];
|
||||
|
||||
decorators.forEach(d => methods = getMethodsForDecorator(d).concat(methods));
|
||||
|
||||
const methodElements = methods.map(m => ts.createIdentifier(m));
|
||||
const methodNames = methodElements.map((el) => el.escapedText);
|
||||
|
||||
importStatement.importClause.namedBindings.elements = [
|
||||
ts.createIdentifier('IonicNativePlugin'),
|
||||
...methodElements,
|
||||
...importStatement.importClause.namedBindings.elements.filter(
|
||||
el => keep.indexOf(el.name.text) !== -1 && methodNames.indexOf(el.name.text) === -1
|
||||
)
|
||||
];
|
||||
|
||||
if (ngcBuild) {
|
||||
importStatement.importClause.namedBindings.elements = importStatement.importClause.namedBindings.elements.map(
|
||||
binding => {
|
||||
if (binding.escapedText) {
|
||||
binding.name = {
|
||||
text: binding.escapedText
|
||||
};
|
||||
}
|
||||
return binding;
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return file;
|
||||
}
|
||||
|
||||
export function importsTransformer(ngcBuild?: boolean) {
|
||||
return (ctx: ts.TransformationContext) => {
|
||||
return tsSourceFile => {
|
||||
return transformImports(tsSourceFile, ctx, ngcBuild);
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,37 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
import { transformMethod } from './methods';
|
||||
import { transformProperty } from './properties';
|
||||
|
||||
export function transformMembers(cls: ts.ClassDeclaration) {
|
||||
const propertyIndices: number[] = [];
|
||||
|
||||
const members = cls.members.map((member: any, index: number) => {
|
||||
// only process decorated members
|
||||
if (!member.decorators || !member.decorators.length) return member;
|
||||
|
||||
switch (member.kind) {
|
||||
case ts.SyntaxKind.MethodDeclaration:
|
||||
return transformMethod(member);
|
||||
case ts.SyntaxKind.PropertyDeclaration:
|
||||
propertyIndices.push(index);
|
||||
return member;
|
||||
case ts.SyntaxKind.Constructor:
|
||||
return ts.createConstructor(undefined, undefined, member.parameters, member.body);
|
||||
default:
|
||||
return member; // in case anything gets here by accident...
|
||||
}
|
||||
});
|
||||
|
||||
propertyIndices.forEach((i: number) => {
|
||||
const [getter, setter] = transformProperty(members, i) as any;
|
||||
members.push(getter, setter);
|
||||
});
|
||||
|
||||
propertyIndices.reverse().forEach(i => members.splice(i, 1));
|
||||
|
||||
return members;
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -1,49 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
import { Logger } from '../../logger';
|
||||
import { convertValueToLiteral, getDecorator, getDecoratorArgs, getDecoratorName, getMethodsForDecorator } from '../helpers';
|
||||
|
||||
export function transformMethod(method: ts.MethodDeclaration) {
|
||||
if (!method) return;
|
||||
|
||||
const decorator = getDecorator(method),
|
||||
decoratorName = getDecoratorName(decorator),
|
||||
decoratorArgs = getDecoratorArgs(decorator);
|
||||
|
||||
try {
|
||||
return ts.createMethod(undefined, undefined, undefined, method.name, undefined, method.typeParameters, method.parameters, method.type, ts.createBlock([
|
||||
ts.createReturn(
|
||||
getMethodBlock(method, decoratorName, decoratorArgs)
|
||||
)
|
||||
]));
|
||||
} catch (e) {
|
||||
Logger.error('Error transforming method: ' + (method.name as any).text);
|
||||
Logger.error(e.message);
|
||||
}
|
||||
}
|
||||
|
||||
function getMethodBlock(method: ts.MethodDeclaration, decoratorName: string, decoratorArgs: any): ts.Expression {
|
||||
const decoratorMethod = getMethodsForDecorator(decoratorName)[0];
|
||||
|
||||
switch (decoratorName) {
|
||||
case 'CordovaCheck':
|
||||
case 'InstanceCheck':
|
||||
// TODO remove function wrapper
|
||||
return ts.createImmediatelyInvokedArrowFunction([ts.createIf(
|
||||
ts.createBinary(
|
||||
ts.createCall(ts.createIdentifier(decoratorMethod), undefined, [ts.createThis()]),
|
||||
ts.SyntaxKind.EqualsEqualsEqualsToken,
|
||||
ts.createTrue()
|
||||
),
|
||||
method.body
|
||||
)]);
|
||||
|
||||
default:
|
||||
return ts.createCall(ts.createIdentifier(decoratorMethod), undefined, [
|
||||
ts.createThis(),
|
||||
ts.createLiteral((method.name as any).text),
|
||||
convertValueToLiteral(decoratorArgs),
|
||||
ts.createIdentifier('arguments')
|
||||
]);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,80 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import { Logger } from '../../logger';
|
||||
import {
|
||||
convertValueToLiteral,
|
||||
getDecorator,
|
||||
getDecoratorArgs,
|
||||
getDecoratorName
|
||||
} from '../helpers';
|
||||
import { transformMembers } from './members';
|
||||
|
||||
function transformClass(cls: any, ngcBuild?: boolean) {
|
||||
Logger.profile('transformClass: ' + cls.name.text);
|
||||
|
||||
const pluginStatics = [];
|
||||
const dec: any = getDecorator(cls);
|
||||
|
||||
if (dec) {
|
||||
const pluginDecoratorArgs = getDecoratorArgs(dec);
|
||||
|
||||
// add plugin decorator args as static properties of the plugin's class
|
||||
for (const prop in pluginDecoratorArgs) {
|
||||
pluginStatics.push(
|
||||
ts.createProperty(
|
||||
undefined,
|
||||
[ts.createToken(ts.SyntaxKind.StaticKeyword)],
|
||||
ts.createIdentifier(prop),
|
||||
undefined,
|
||||
undefined,
|
||||
convertValueToLiteral(pluginDecoratorArgs[prop])
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
cls = ts.createClassDeclaration(
|
||||
ngcBuild && cls.decorators && cls.decorators.length
|
||||
? cls.decorators.filter(d => getDecoratorName(d) === 'Injectable')
|
||||
: undefined, // remove Plugin and Injectable decorators
|
||||
[ts.createToken(ts.SyntaxKind.ExportKeyword)],
|
||||
cls.name,
|
||||
cls.typeParameters,
|
||||
cls.heritageClauses,
|
||||
[...transformMembers(cls), ...pluginStatics]
|
||||
);
|
||||
|
||||
Logger.profile('transformClass: ' + cls.name.text);
|
||||
return cls;
|
||||
}
|
||||
|
||||
function transformClasses(
|
||||
file: ts.SourceFile,
|
||||
ctx: ts.TransformationContext,
|
||||
ngcBuild?: boolean
|
||||
) {
|
||||
Logger.silly('Transforming file: ' + file.fileName);
|
||||
return ts.visitEachChild(
|
||||
file,
|
||||
node => {
|
||||
if (node.kind !== ts.SyntaxKind.ClassDeclaration
|
||||
|| (node.modifiers && node.modifiers.find(v => v.kind === ts.SyntaxKind.DeclareKeyword))) {
|
||||
return node;
|
||||
}
|
||||
return transformClass(node, ngcBuild);
|
||||
},
|
||||
ctx
|
||||
);
|
||||
}
|
||||
|
||||
export function pluginClassTransformer(
|
||||
ngcBuild?: boolean
|
||||
): ts.TransformerFactory<ts.SourceFile> {
|
||||
return (ctx: ts.TransformationContext) => {
|
||||
return tsSourceFile => {
|
||||
if (tsSourceFile.fileName.indexOf('src/@ionic-native/plugins') > -1)
|
||||
return transformClasses(tsSourceFile, ctx, ngcBuild);
|
||||
return tsSourceFile;
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,67 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import { getDecorator, getDecoratorName } from '../helpers';
|
||||
|
||||
export function transformProperty(members: any[], index: number) {
|
||||
const property = members[index] as ts.PropertyDeclaration,
|
||||
decorator = getDecorator(property),
|
||||
decoratorName = getDecoratorName(decorator);
|
||||
|
||||
let type: 'cordova' | 'instance';
|
||||
|
||||
switch (decoratorName) {
|
||||
case 'CordovaProperty':
|
||||
type = 'cordova';
|
||||
break;
|
||||
|
||||
case 'InstanceProperty':
|
||||
type = 'instance';
|
||||
break;
|
||||
|
||||
default:
|
||||
return property;
|
||||
}
|
||||
|
||||
const getter = ts.createGetAccessor(
|
||||
undefined,
|
||||
undefined,
|
||||
property.name,
|
||||
undefined,
|
||||
property.type,
|
||||
ts.createBlock([
|
||||
ts.createReturn(
|
||||
ts.createCall(ts.createIdentifier(type + 'PropertyGet'), undefined, [
|
||||
ts.createThis(),
|
||||
ts.createLiteral((property.name as any).text)
|
||||
])
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
const setter = ts.createSetAccessor(
|
||||
undefined,
|
||||
undefined,
|
||||
property.name,
|
||||
[
|
||||
ts.createParameter(
|
||||
undefined,
|
||||
undefined,
|
||||
undefined,
|
||||
'value',
|
||||
undefined,
|
||||
property.type
|
||||
)
|
||||
],
|
||||
ts.createBlock([
|
||||
ts.createStatement(
|
||||
ts.createCall(ts.createIdentifier(type + 'PropertySet'), undefined, [
|
||||
ts.createThis(),
|
||||
ts.createLiteral((property.name as any).text),
|
||||
ts.createIdentifier('value')
|
||||
])
|
||||
)
|
||||
])
|
||||
);
|
||||
|
||||
return [getter, setter];
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import * as ts from 'typescript';
|
||||
import { pluginClassTransformer } from './transformers/plugin-class';
|
||||
import { importsTransformer } from './transformers/imports';
|
||||
import { clone } from 'lodash';
|
||||
import { emitInjectableClasses, extractInjectables } from './transformers/extract-injectables';
|
||||
import { COMPILER_OPTIONS, PLUGIN_PATHS, TS_CONFIG } from './helpers';
|
||||
|
||||
let host: ts.CompilerHost;
|
||||
|
||||
export function getCompilerHost() {
|
||||
if (!host) host = ts.createCompilerHost(TS_CONFIG);
|
||||
return host;
|
||||
}
|
||||
|
||||
export function getProgram(declaration = false, pluginPaths: string[] = PLUGIN_PATHS) {
|
||||
const compilerOptions: ts.CompilerOptions = clone(COMPILER_OPTIONS);
|
||||
compilerOptions.declaration = declaration;
|
||||
compilerOptions.moduleResolution = ts.ModuleResolutionKind.NodeJs;
|
||||
compilerOptions.target = ts.ScriptTarget.ES5;
|
||||
compilerOptions.module = ts.ModuleKind.ES2015;
|
||||
compilerOptions.inlineSourceMap = true;
|
||||
compilerOptions.inlineSources = true;
|
||||
compilerOptions.lib = [
|
||||
'lib.dom.d.ts',
|
||||
'lib.es5.d.ts',
|
||||
'lib.es2015.d.ts',
|
||||
'lib.es2016.d.ts',
|
||||
'lib.es2017.d.ts'
|
||||
];
|
||||
|
||||
return ts.createProgram(pluginPaths, compilerOptions, getCompilerHost());
|
||||
}
|
||||
|
||||
export function generateDeclarations(sourceFiles?: string[]) {
|
||||
return getProgram(true, sourceFiles).emit(undefined, getCompilerHost().writeFile, undefined, true);
|
||||
}
|
||||
|
||||
export function transpile() {
|
||||
const emitResult = getProgram().emit(undefined, getCompilerHost().writeFile, undefined, false, {
|
||||
before: [
|
||||
extractInjectables(),
|
||||
importsTransformer(),
|
||||
pluginClassTransformer(),
|
||||
]
|
||||
});
|
||||
|
||||
emitInjectableClasses();
|
||||
|
||||
return emitResult;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"stripInternal": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "../../dist/packages-dist/",
|
||||
"rootDir": "../../src/",
|
||||
"target": "es5",
|
||||
"skipLibCheck": true,
|
||||
"lib": ["es2015", "dom"]
|
||||
},
|
||||
"files": [
|
||||
"../../src/@ionic-native/core/index.ts"
|
||||
],
|
||||
"angularCompilerOptions": {
|
||||
"genDir": "../../.tmp/core-aot"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"baseUrl": ".",
|
||||
"declaration": true,
|
||||
"stripInternal": true,
|
||||
"experimentalDecorators": true,
|
||||
"emitDecoratorMetadata": true,
|
||||
"module": "es2015",
|
||||
"moduleResolution": "node",
|
||||
"outDir": "../../../dist/packages-dist/",
|
||||
"paths": {
|
||||
"@ionic-native/core": ["../../../dist/packages-dist/@ionic-native/core"]
|
||||
},
|
||||
"rootDir": "../../../src/",
|
||||
"target": "es5",
|
||||
"skipLibCheck": true,
|
||||
"lib": ["es2015", "dom"]
|
||||
},
|
||||
"files": [
|
||||
"../../../src/@ionic-native/plugins/{{PLUGIN}}/index.ts"
|
||||
]
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
{
|
||||
"sitePath": "../ionic-site",
|
||||
"v2DocsDir": "docs/v2/native",
|
||||
"docsDest": "../ionic-site/content/docs/v2/native",
|
||||
"pluginDir": "dist/packages-dist/@ionic-native/plugins"
|
||||
}
|
||||
@@ -1,99 +0,0 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import { Application } from 'typedoc';
|
||||
import { basename, dirname, resolve } from 'path';
|
||||
import { runInNewContext } from 'vm';
|
||||
|
||||
interface Plugin {
|
||||
packageName: string;
|
||||
displayName: string;
|
||||
description: string;
|
||||
platforms: string[];
|
||||
usage: string;
|
||||
repo: string;
|
||||
cordovaPlugin: {
|
||||
name: string;
|
||||
};
|
||||
}
|
||||
|
||||
const rootDir = resolve(__dirname, '../..');
|
||||
const typedocTmp = resolve(__dirname, 'typedoc.tmp.json');
|
||||
const pluginsDir = resolve(rootDir, 'src/@ionic-native/plugins');
|
||||
const typedoc = new Application({
|
||||
mode: 'modules',
|
||||
tsconfig: resolve(rootDir, 'tsconfig.json'),
|
||||
ignoreCompilerErrors: true
|
||||
});
|
||||
|
||||
run(pluginsDir);
|
||||
|
||||
async function run(pluginsDir: string) {
|
||||
const typedocData = await generateTypedoc(pluginsDir);
|
||||
const modules = typedocData.children.filter(isModule);
|
||||
const plugins = modules.filter(hasPlugin).map(processPlugin);
|
||||
await fs.outputJson(resolve(__dirname, 'plugins.json'), plugins, {
|
||||
spaces: 2
|
||||
});
|
||||
}
|
||||
|
||||
async function generateTypedoc(root: string, outputPath = typedocTmp) {
|
||||
const pluginDirs = await fs.readdir(root);
|
||||
const paths = pluginDirs.map(dir => resolve(root, dir, 'index.ts'));
|
||||
typedoc.generateJson(paths, outputPath);
|
||||
return fs.readJson(outputPath);
|
||||
}
|
||||
|
||||
function processPlugin(pluginModule): Plugin {
|
||||
const pluginClass = pluginModule.children.find(isPlugin);
|
||||
const decorator = getPluginDecorator(pluginClass);
|
||||
const packageName = `@ionic-native/${basename(dirname(pluginModule.originalName))}`;
|
||||
const displayName = getTag(pluginClass, 'name');
|
||||
const usage = getTag(pluginClass, 'usage');
|
||||
const description = getTag(pluginClass, 'description');
|
||||
return {
|
||||
packageName,
|
||||
displayName,
|
||||
description,
|
||||
usage,
|
||||
platforms: decorator.platforms,
|
||||
repo: decorator.repo,
|
||||
cordovaPlugin: {
|
||||
name: decorator.plugin
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Typedoc only gives us the Plugin decorator internals
|
||||
* as a string. So, rather than try to parse that with a RegExp,
|
||||
* we evaluate it using Node's vm module.
|
||||
*/
|
||||
const getPluginDecorator = (child: any) => {
|
||||
if (isPlugin(child)) {
|
||||
const decorator = child.decorators.find(d => d.name === 'Plugin');
|
||||
return runInNewContext(`(${decorator.arguments.config})`);
|
||||
}
|
||||
};
|
||||
|
||||
const getTag = (child: any, tagName: string): string => {
|
||||
if (hasTags(child)) {
|
||||
const tag = child.comment.tags.find(t => t.tag === tagName);
|
||||
if (tag) {
|
||||
return tag.text;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
const isModule = (child: any): boolean =>
|
||||
child.kind === 1;
|
||||
|
||||
const isClass = (child: any): boolean =>
|
||||
child.kind === 128;
|
||||
|
||||
const isPlugin = (child: any): boolean =>
|
||||
isClass(child) && hasTags(child) && Array.isArray(child.decorators) && child.decorators.some(d => d.name === 'Plugin');
|
||||
|
||||
const hasPlugin = (child: any): boolean =>
|
||||
child.children.some(isPlugin);
|
||||
|
||||
const hasTags = (child: any): boolean =>
|
||||
child.comment && Array.isArray(child.comment.tags);
|
||||
@@ -1,3 +0,0 @@
|
||||
# docs-json
|
||||
|
||||
This script reads and generates [typedoc](https://github.com/TypeStrong/typedoc) data for each of the plugins in `src/@ionic-native/plugins`. That data is then formatted and output as `plugins.json` in this directory.
|
||||
@@ -1,6 +0,0 @@
|
||||
{
|
||||
"sitePath": "../ionic-site",
|
||||
"v2DocsDir": "docs/native",
|
||||
"docsDest": "../ionic-site/content/docs/native",
|
||||
"pluginDir": "dist/@ionic-native/plugins"
|
||||
}
|
||||
@@ -0,0 +1,181 @@
|
||||
var Package = require('dgeni').Package;
|
||||
var jsdocPackage = require('dgeni-packages/jsdoc');
|
||||
var nunjucksPackage = require('dgeni-packages/nunjucks');
|
||||
var typescriptPackage = require('dgeni-packages/typescript');
|
||||
var linksPackage = require('dgeni-packages/links');
|
||||
var path = require('path');
|
||||
var semver = require('semver');
|
||||
var fs = require('fs');
|
||||
var _ = require('lodash');
|
||||
var config = require('../config.json');
|
||||
var projectPackage = require('../../package.json');
|
||||
|
||||
// Define the dgeni package for generating the docs
|
||||
module.exports = function(currentVersion) {
|
||||
|
||||
return new Package('ionic-v2-docs', [jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage])
|
||||
|
||||
// .processor(require('./processors/latest-version'))
|
||||
.processor(require('./processors/jekyll'))
|
||||
.processor(require('./processors/remove-private-members'))
|
||||
.processor(require('./processors/hide-private-api'))
|
||||
.processor(require('./processors/collect-inputs-outputs'))
|
||||
|
||||
// for debugging docs
|
||||
// .processor(function test(){
|
||||
// return {
|
||||
//
|
||||
// $runBefore: ['rendering-docs'],
|
||||
// $process: function(docs){
|
||||
// docs.forEach(function(doc){
|
||||
// if (doc.name == "Camera"){
|
||||
//
|
||||
// // console.log(doc.tags);
|
||||
// // doc.tags.forEach(function(tag){
|
||||
// // if(tag.tagName == 'classes'){
|
||||
// //
|
||||
// // }
|
||||
// // });
|
||||
//
|
||||
// // doc.moduleDoc.exports.forEach(function(d,i){
|
||||
// // if(d.name === 'CameraOptions') {
|
||||
// // console.log('Name: ' + d.name);
|
||||
// // console.log('Type: ' + d.docType);
|
||||
// // console.log('First member: ', d.members[0]);
|
||||
// // }
|
||||
// // });
|
||||
//
|
||||
//
|
||||
// // var exports = doc.exportSymbol.parent.exports;
|
||||
// // for(var p in exports) {
|
||||
// // if(p == 'CameraOptions')
|
||||
// // {
|
||||
// // var x = exports[p];
|
||||
// // console.log(x.members.quality);
|
||||
// // }
|
||||
// // }
|
||||
// // doc.members.forEach(function(method){
|
||||
// // if (method.name === "getPicture") {
|
||||
// // console.log(method);
|
||||
// // }
|
||||
// // })
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
|
||||
.config(function(log) {
|
||||
log.level = 'error'; //'silly', 'debug', 'info', 'warn', 'error'
|
||||
})
|
||||
|
||||
.config(function(renderDocsProcessor, computePathsProcessor) {
|
||||
|
||||
versions = [];
|
||||
// new version, add it to the versions list
|
||||
if (currentVersion != 'nightly' && !_.includes(versions, currentVersion)) {
|
||||
versions.unshift(currentVersion);
|
||||
}
|
||||
//First semver valid version is latest
|
||||
var latestVersion = _.find(versions, semver.valid);
|
||||
versions = versions.map(function(version) {
|
||||
// We don't separate by versions so always put the docs in the root
|
||||
var folder = '';
|
||||
return {
|
||||
href: '/' + config.v2DocsDir.replace('content/',''),
|
||||
folder: folder,
|
||||
name: version
|
||||
};
|
||||
});
|
||||
|
||||
var versionData = {
|
||||
list: versions,
|
||||
current: _.find(versions, {name: currentVersion}),
|
||||
latest: _.find(versions, {name: latestVersion}) || _.first(versions)
|
||||
};
|
||||
|
||||
renderDocsProcessor.extraData.version = versionData;
|
||||
computePathsProcessor.pathTemplates = [{
|
||||
docTypes: ['class', 'var', 'function', 'let'],
|
||||
getOutputPath: function(doc) {
|
||||
var docPath = doc.name + '/index.md';
|
||||
var path = 'content/' + config.v2DocsDir + '/' + docPath;
|
||||
|
||||
return path;
|
||||
}
|
||||
}];
|
||||
})
|
||||
|
||||
//configure file reading
|
||||
.config(function(readFilesProcessor, readTypeScriptModules) {
|
||||
|
||||
// Don't run unwanted processors since we are not using the normal file reading processor
|
||||
readFilesProcessor.$enabled = false;
|
||||
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
|
||||
|
||||
readTypeScriptModules.basePath = path.resolve(__dirname, '../..');
|
||||
readTypeScriptModules.sourceFiles = [
|
||||
'./src/@ionic-native/plugins/**/*.ts'
|
||||
];
|
||||
})
|
||||
|
||||
.config(function(parseTagsProcessor) {
|
||||
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions
|
||||
.concat(require('./tag-defs/tag-defs'));
|
||||
})
|
||||
|
||||
// .config(function(parseTagsProcessor) {
|
||||
// // We actually don't want to parse param docs in this package as we are
|
||||
// // getting the data out using TS
|
||||
// parseTagsProcessor.tagDefinitions.forEach(function(tagDef) {
|
||||
// console.log(tagDef);
|
||||
// if (tagDef.name === 'param') {
|
||||
// tagDef.docProperty = 'paramData';
|
||||
// tagDef.transforms = [];
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
|
||||
// Configure links
|
||||
.config(function(getLinkInfo) {
|
||||
getLinkInfo.useFirstAmbiguousLink = false;
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function(writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = '../ionic-site/';
|
||||
})
|
||||
|
||||
// Configure rendering
|
||||
.config(function(templateFinder, templateEngine) {
|
||||
|
||||
// Nunjucks and Angular conflict in their template bindings so change the Nunjucks
|
||||
// Also conflict with Jekyll
|
||||
templateEngine.config.tags = {
|
||||
variableStart: '<$',
|
||||
variableEnd: '$>',
|
||||
blockStart: '<@',
|
||||
blockEnd: '@>',
|
||||
commentStart: '<#',
|
||||
commentEnd: '#>'
|
||||
};
|
||||
|
||||
// add custom filters to nunjucks
|
||||
templateEngine.filters.push(
|
||||
require('./filters/capital'),
|
||||
require('./filters/code'),
|
||||
require('./filters/dump'),
|
||||
require('./filters/dashify')
|
||||
);
|
||||
|
||||
templateFinder.templateFolders.unshift(path.resolve(__dirname, 'templates'));
|
||||
|
||||
// Specify how to match docs to templates.
|
||||
templateFinder.templatePatterns = [
|
||||
'${ doc.template }',
|
||||
'${ doc.docType }.template.html',
|
||||
'common.template.html'
|
||||
];
|
||||
});
|
||||
|
||||
};
|
||||
@@ -0,0 +1,177 @@
|
||||
var Package = require('dgeni').Package;
|
||||
var jsdocPackage = require('dgeni-packages/jsdoc');
|
||||
var nunjucksPackage = require('dgeni-packages/nunjucks');
|
||||
var typescriptPackage = require('dgeni-packages/typescript');
|
||||
var linksPackage = require('dgeni-packages/links');
|
||||
var path = require('path');
|
||||
var semver = require('semver');
|
||||
var fs = require('fs');
|
||||
var _ = require('lodash');
|
||||
var config = require('../config.json');
|
||||
var projectPackage = require('../../package.json');
|
||||
|
||||
// jscs:disable validateIndentation
|
||||
|
||||
// Define the dgeni package for generating the docs
|
||||
module.exports = function(currentVersion) {
|
||||
|
||||
return new Package('ionic-v2-docs', [jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage])
|
||||
|
||||
// .processor(require('./processors/latest-version'))
|
||||
.processor(require('./processors/readmes'))
|
||||
.processor(require('./processors/remove-private-members'))
|
||||
.processor(require('./processors/hide-private-api'))
|
||||
// .processor(require('./processors/collect-inputs-outputs'))
|
||||
|
||||
// for debugging docs
|
||||
// .processor(function test(){
|
||||
// return {
|
||||
//
|
||||
// $runBefore: ['rendering-docs'],
|
||||
// $process: function(docs){
|
||||
// docs.forEach(function(doc){
|
||||
// if (doc.name == "Camera"){
|
||||
//
|
||||
// // console.log(doc.tags);
|
||||
// // doc.tags.forEach(function(tag){
|
||||
// // if(tag.tagName == 'classes'){
|
||||
// //
|
||||
// // }
|
||||
// // });
|
||||
//
|
||||
// // doc.moduleDoc.exports.forEach(function(d,i){
|
||||
// // if(d.name === 'CameraOptions') {
|
||||
// // console.log('Name: ' + d.name);
|
||||
// // console.log('Type: ' + d.docType);
|
||||
// // console.log('First member: ', d.members[0]);
|
||||
// // }
|
||||
// // });
|
||||
//
|
||||
//
|
||||
// // var exports = doc.exportSymbol.parent.exports;
|
||||
// // for(var p in exports) {
|
||||
// // if(p == 'CameraOptions')
|
||||
// // {
|
||||
// // var x = exports[p];
|
||||
// // console.log(x.members.quality);
|
||||
// // }
|
||||
// // }
|
||||
// // doc.members.forEach(function(method){
|
||||
// // if (method.name === "getPicture") {
|
||||
// // console.log(method);
|
||||
// // }
|
||||
// // })
|
||||
// }
|
||||
// })
|
||||
// }
|
||||
// }
|
||||
// })
|
||||
.config(function(log) {
|
||||
log.level = 'error'; //'silly', 'debug', 'info', 'warn', 'error'
|
||||
})
|
||||
|
||||
.config(function(renderDocsProcessor, computePathsProcessor) {
|
||||
|
||||
versions = [];
|
||||
// new version, add it to the versions list
|
||||
if (currentVersion != 'nightly' && !_.includes(versions, currentVersion)) {
|
||||
versions.unshift(currentVersion);
|
||||
}
|
||||
//First semver valid version is latest
|
||||
var latestVersion = _.find(versions, semver.valid);
|
||||
versions = versions.map(function(version) {
|
||||
// We don't separate by versions so always put the docs in the root
|
||||
var folder = '';
|
||||
return {
|
||||
href: '/' + config.v2DocsDir.replace('content/', ''),
|
||||
folder: folder,
|
||||
name: version
|
||||
};
|
||||
});
|
||||
|
||||
var versionData = {
|
||||
list: versions,
|
||||
current: _.find(versions, {name: currentVersion}),
|
||||
latest: _.find(versions, {name: latestVersion}) || _.first(versions)
|
||||
};
|
||||
|
||||
renderDocsProcessor.extraData.version = versionData;
|
||||
computePathsProcessor.pathTemplates = [{
|
||||
docTypes: ['class'],
|
||||
getOutputPath: function(doc) {
|
||||
return doc.originalModule.replace(config.pluginDir + '/', '')
|
||||
.replace('/index', '') + '/README.md';
|
||||
}
|
||||
}];
|
||||
})
|
||||
|
||||
//configure file reading
|
||||
.config(function(readFilesProcessor, readTypeScriptModules) {
|
||||
|
||||
// Don't run unwanted processors since we are not using the normal file reading processor
|
||||
readFilesProcessor.$enabled = false;
|
||||
readFilesProcessor.basePath = path.resolve(__dirname, '../..');
|
||||
|
||||
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../..'));
|
||||
readTypeScriptModules.sourceFiles = ['./src/@ionic-native/plugins/**/*.ts'];
|
||||
})
|
||||
|
||||
.config(function(parseTagsProcessor) {
|
||||
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions
|
||||
.concat(require('./tag-defs/tag-defs'));
|
||||
})
|
||||
|
||||
// .config(function(parseTagsProcessor) {
|
||||
// // We actually don't want to parse param docs in this package as we are
|
||||
// // getting the data out using TS
|
||||
// parseTagsProcessor.tagDefinitions.forEach(function(tagDef) {
|
||||
// console.log(tagDef);
|
||||
// if (tagDef.name === 'param') {
|
||||
// tagDef.docProperty = 'paramData';
|
||||
// tagDef.transforms = [];
|
||||
// }
|
||||
// });
|
||||
// })
|
||||
|
||||
// Configure links
|
||||
.config(function(getLinkInfo) {
|
||||
getLinkInfo.useFirstAmbiguousLink = false;
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function(writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = './dist/packages-dist/';
|
||||
})
|
||||
|
||||
// Configure rendering
|
||||
.config(function(templateFinder, templateEngine) {
|
||||
|
||||
// Nunjucks and Angular conflict in their template bindings so change the Nunjucks
|
||||
// Also conflict with Jekyll
|
||||
templateEngine.config.tags = {
|
||||
variableStart: '<$',
|
||||
variableEnd: '$>',
|
||||
blockStart: '<@',
|
||||
blockEnd: '@>',
|
||||
commentStart: '<#',
|
||||
commentEnd: '#>'
|
||||
};
|
||||
|
||||
// add custom filters to nunjucks
|
||||
templateEngine.filters.push(
|
||||
require('./filters/capital'),
|
||||
require('./filters/code'),
|
||||
require('./filters/dump')
|
||||
);
|
||||
|
||||
templateFinder.templateFolders.unshift(path.resolve(__dirname, 'templates'));
|
||||
|
||||
// Specify how to match docs to templates.
|
||||
templateFinder.templatePatterns = [
|
||||
'${ doc.template }',
|
||||
'${ doc.docType }.template.md',
|
||||
'readme.template.md'
|
||||
];
|
||||
});
|
||||
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function(getLinkInfo) {
|
||||
getLinkInfo.useFirstAmbiguousLink = false;
|
||||
};
|
||||
@@ -1,3 +0,0 @@
|
||||
module.exports = function(log) {
|
||||
log.level = 'error'; //'silly', 'debug', 'info', 'warn', 'error'
|
||||
};
|
||||
@@ -1,4 +0,0 @@
|
||||
module.exports = function(parseTagsProcessor) {
|
||||
parseTagsProcessor.tagDefinitions = parseTagsProcessor.tagDefinitions
|
||||
.concat(require('../tag-defs/tag-defs'));
|
||||
};
|
||||
@@ -1,12 +0,0 @@
|
||||
module.exports = function(templateEngine) {
|
||||
// Nunjucks and Angular conflict in their template bindings so change the Nunjucks
|
||||
// Also conflict with Jekyll
|
||||
templateEngine.config.tags = {
|
||||
variableStart: '<$',
|
||||
variableEnd: '$>',
|
||||
blockStart: '<@',
|
||||
blockEnd: '@>',
|
||||
commentStart: '<#',
|
||||
commentEnd: '#>'
|
||||
};
|
||||
};
|
||||
@@ -1,9 +0,0 @@
|
||||
module.exports = function(templateEngine) {
|
||||
// add custom filters to nunjucks
|
||||
templateEngine.filters.push(
|
||||
require('../filters/capital'),
|
||||
require('../filters/code'),
|
||||
require('../filters/dump'),
|
||||
require('../filters/dashify')
|
||||
);
|
||||
};
|
||||
@@ -1,79 +0,0 @@
|
||||
"use strict";
|
||||
const Package = require('dgeni').Package,
|
||||
jsdocPackage = require('dgeni-packages/jsdoc'),
|
||||
nunjucksPackage = require('dgeni-packages/nunjucks'),
|
||||
typescriptPackage = require('dgeni-packages/typescript'),
|
||||
linksPackage = require('dgeni-packages/links'),
|
||||
path = require('path'),
|
||||
config = require('../config.json');
|
||||
|
||||
module.exports = currentVersion => {
|
||||
|
||||
return new Package('ionic-native-docs', [jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage])
|
||||
|
||||
.processor(require('./processors/remove-private-members'))
|
||||
.processor(require('./processors/hide-private-api'))
|
||||
.processor(require('./processors/parse-optional'))
|
||||
.processor(require('./processors/mark-properties'))
|
||||
.processor(require('./processors/npm-id'))
|
||||
.processor(require('./processors/jekyll'))
|
||||
|
||||
.config(require('./configs/log'))
|
||||
.config(require('./configs/template-filters'))
|
||||
.config(require('./configs/template-tags'))
|
||||
.config(require('./configs/tag-defs'))
|
||||
.config(require('./configs/links'))
|
||||
|
||||
.config(function(renderDocsProcessor, computePathsProcessor) {
|
||||
|
||||
currentVersion = {
|
||||
href: '/' + config.v2DocsDir.replace('content/', ''),
|
||||
folder: '',
|
||||
name: currentVersion
|
||||
};
|
||||
|
||||
renderDocsProcessor.extraData.version = {
|
||||
list: [currentVersion],
|
||||
current: currentVersion,
|
||||
latest: currentVersion
|
||||
};
|
||||
|
||||
computePathsProcessor.pathTemplates = [{
|
||||
docTypes: ['class'],
|
||||
getOutputPath: doc => 'content/' + config.v2DocsDir + '/' + doc.name + '/index.md'
|
||||
}];
|
||||
|
||||
})
|
||||
|
||||
//configure file reading
|
||||
.config(function(readFilesProcessor, readTypeScriptModules) {
|
||||
|
||||
// Don't run unwanted processors since we are not using the normal file reading processor
|
||||
readFilesProcessor.$enabled = false;
|
||||
readFilesProcessor.basePath = path.resolve(__dirname, '../../..');
|
||||
|
||||
readTypeScriptModules.basePath = path.resolve(__dirname, '../../..');
|
||||
readTypeScriptModules.sourceFiles = [
|
||||
'./src/@ionic-native/plugins/**/*.ts'
|
||||
];
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function(writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = '../ionic-site/';
|
||||
})
|
||||
|
||||
// Configure rendering
|
||||
.config(function(templateFinder) {
|
||||
|
||||
templateFinder.templateFolders.unshift(path.resolve(__dirname, 'templates'));
|
||||
|
||||
// Specify how to match docs to templates.
|
||||
templateFinder.templatePatterns = [
|
||||
'${ doc.template }',
|
||||
'${ doc.docType }.template.html',
|
||||
'common.template.html'
|
||||
];
|
||||
});
|
||||
|
||||
};
|
||||
@@ -1,75 +0,0 @@
|
||||
"use strict";
|
||||
const Package = require('dgeni').Package,
|
||||
jsdocPackage = require('dgeni-packages/jsdoc'),
|
||||
nunjucksPackage = require('dgeni-packages/nunjucks'),
|
||||
typescriptPackage = require('dgeni-packages/typescript'),
|
||||
linksPackage = require('dgeni-packages/links'),
|
||||
path = require('path'),
|
||||
config = require('../config.json');
|
||||
|
||||
module.exports = currentVersion => {
|
||||
|
||||
return new Package('ionic-native-readmes', [jsdocPackage, nunjucksPackage, typescriptPackage, linksPackage])
|
||||
|
||||
.processor(require('./processors/readmes'))
|
||||
.processor(require('./processors/remove-private-members'))
|
||||
.processor(require('./processors/hide-private-api'))
|
||||
.processor(require('./processors/npm-id'))
|
||||
|
||||
.config(require('./configs/log'))
|
||||
.config(require('./configs/template-filters'))
|
||||
.config(require('./configs/template-tags'))
|
||||
.config(require('./configs/tag-defs'))
|
||||
.config(require('./configs/links'))
|
||||
|
||||
|
||||
.config(function(renderDocsProcessor, computePathsProcessor) {
|
||||
|
||||
currentVersion = {
|
||||
href: '/' + config.v2DocsDir.replace('content/', ''),
|
||||
folder: '',
|
||||
name: currentVersion
|
||||
};
|
||||
|
||||
renderDocsProcessor.extraData.version = {
|
||||
list: [currentVersion],
|
||||
current: currentVersion,
|
||||
latest: currentVersion
|
||||
};
|
||||
|
||||
computePathsProcessor.pathTemplates = [{
|
||||
docTypes: ['class'],
|
||||
getOutputPath: doc => doc.originalModule.replace(config.pluginDir + '/', '')
|
||||
.replace(/\/index$/, '/README.md')
|
||||
}];
|
||||
|
||||
})
|
||||
|
||||
//configure file reading
|
||||
.config(function(readFilesProcessor, readTypeScriptModules) {
|
||||
// Don't run unwanted processors since we are not using the normal file reading processor
|
||||
readFilesProcessor.$enabled = false;
|
||||
readFilesProcessor.basePath = path.resolve(__dirname, '../../..');
|
||||
|
||||
readTypeScriptModules.basePath = path.resolve(path.resolve(__dirname, '../../..'));
|
||||
readTypeScriptModules.sourceFiles = ['./src/@ionic-native/plugins/**/*.ts'];
|
||||
})
|
||||
|
||||
// Configure file writing
|
||||
.config(function(writeFilesProcessor) {
|
||||
writeFilesProcessor.outputFolder = './dist/@ionic-native/';
|
||||
})
|
||||
|
||||
// Configure rendering
|
||||
.config(function(templateFinder) {
|
||||
templateFinder.templateFolders.unshift(path.resolve(__dirname, 'templates'));
|
||||
|
||||
// Specify how to match docs to templates.
|
||||
templateFinder.templatePatterns = [
|
||||
'${ doc.template }',
|
||||
'${ doc.docType }.template.md',
|
||||
'readme.template.md'
|
||||
];
|
||||
});
|
||||
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = {
|
||||
name: 'capital',
|
||||
process: str => str? str.charAt(0).toUpperCase() + str.substring(1) : ''
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = {
|
||||
name: 'dashify',
|
||||
process: str => str? str.replace(/\s/g, '-') : ''
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = {
|
||||
name: 'dump',
|
||||
process: obj => console.log(obj)
|
||||
};
|
||||
@@ -1,43 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function test(){
|
||||
return {
|
||||
name: 'debug',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs){
|
||||
docs.forEach(function(doc){
|
||||
if (doc.name == "Camera"){
|
||||
|
||||
console.log(doc.tags);
|
||||
doc.tags.forEach(function(tag){
|
||||
if(tag.tagName == 'classes'){
|
||||
|
||||
}
|
||||
});
|
||||
|
||||
doc.moduleDoc.exports.forEach(function(d,i){
|
||||
if(d.name === 'CameraOptions') {
|
||||
console.log('Name: ' + d.name);
|
||||
console.log('Type: ' + d.docType);
|
||||
console.log('First member: ', d.members[0]);
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var exports = doc.exportSymbol.parent.exports;
|
||||
for(var p in exports) {
|
||||
if(p == 'CameraOptions')
|
||||
{
|
||||
var x = exports[p];
|
||||
console.log(x.members.quality);
|
||||
}
|
||||
}
|
||||
doc.members.forEach(function(method){
|
||||
if (method.name === "getPicture") {
|
||||
console.log(method);
|
||||
}
|
||||
})
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,9 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function removePrivateApi() {
|
||||
return {
|
||||
name: 'remove-private-api',
|
||||
description: 'Prevent the private apis from being rendered',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => docs.filter(doc => !doc.private && (!doc.tags || !doc.tags.tagsByName.get('hidden')))
|
||||
};
|
||||
};
|
||||
@@ -1,66 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function jekyll(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'jekyll',
|
||||
description: 'Create jekyll includes',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => {
|
||||
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter(doc => (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page');
|
||||
|
||||
docs.push({
|
||||
docType: 'class',
|
||||
URL: 'https://github.com/ionic-team/ionic-native-google-maps/blob/master/documents/README.md',
|
||||
name: 'Google Maps',
|
||||
});
|
||||
|
||||
docs.sort((a, b) => {
|
||||
const textA = a.name ? a.name.toUpperCase() : '',
|
||||
textB = b.name ? b.name.toUpperCase() : '';
|
||||
|
||||
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
|
||||
});
|
||||
|
||||
docs.forEach(doc => {
|
||||
if (!doc.outputPath) {
|
||||
return;
|
||||
}
|
||||
|
||||
doc.outputPath = doc.outputPath.toLowerCase().replace(/\s/g, '-');
|
||||
doc.URL = doc.outputPath.replace('docs//', 'docs/')
|
||||
.replace('/index.md', '')
|
||||
.replace('content/', '');
|
||||
// add trailing slash to plugin pages
|
||||
if(!doc.URL.endsWith("/") && !doc.URL.endsWith(".html")) {
|
||||
doc.URL = doc.URL + '/';
|
||||
}
|
||||
|
||||
doc.URL = '/' + doc.URL;
|
||||
});
|
||||
|
||||
const betaDocs = [];
|
||||
|
||||
docs = docs.filter(doc => {
|
||||
if (doc.beta === true) {
|
||||
betaDocs.push(doc);
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
docs = docs.concat(betaDocs);
|
||||
|
||||
// add side menu
|
||||
docs.push({
|
||||
docType: 'nativeMenu',
|
||||
id: 'native_menu',
|
||||
template: 'native_menu.template.html',
|
||||
outputPath: 'content/_includes/fluid/native_menu.html'
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,15 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function markProperties() {
|
||||
return {
|
||||
name: 'mark-properties',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => docs.map(doc => {
|
||||
for (let i in doc.members) {
|
||||
if (doc.members.hasOwnProperty(i) && typeof doc.members[i].parameters === 'undefined') {
|
||||
doc.members[i].isProperty = true;
|
||||
}
|
||||
}
|
||||
return doc;
|
||||
})
|
||||
}
|
||||
};
|
||||
@@ -1,20 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function npmId(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'npm-id',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => {
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter(function(doc) {
|
||||
return (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page';
|
||||
});
|
||||
|
||||
docs.forEach(doc => {
|
||||
doc.npmId = doc.id.match(/plugins\/(.*)\/index/)[1];
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,22 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function parseOptional() {
|
||||
return {
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => {
|
||||
docs.forEach(doc => {
|
||||
if (doc.members && doc.members.length) {
|
||||
for (let i in doc.members) {
|
||||
if (doc.members[i].params && doc.members[i].params.length) {
|
||||
for (let ii in doc.members[i].params) {
|
||||
if (doc.members[i].params[ii].optional) {
|
||||
doc.members[i].params[ii].description += '<strong class="tag">Optional</strong>';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
return docs;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -1,19 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function readmes(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'readmes',
|
||||
description: 'Create jekyll includes',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => {
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter(doc => (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page');
|
||||
|
||||
docs.forEach(doc => {
|
||||
doc.outputPath = doc.outputPath.replace('src/@ionic-native/', '');
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,24 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = function removePrivateMembers() {
|
||||
return {
|
||||
name: 'remove-private-members',
|
||||
description: 'Remove member docs with @private tags',
|
||||
$runAfter: ['tags-parsed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: docs => {
|
||||
docs.forEach(doc => {
|
||||
|
||||
if (doc.members) {
|
||||
doc.members = doc.members.filter(member => !member.tags.tagsByName.get('hidden'));
|
||||
}
|
||||
|
||||
if (doc.statics) {
|
||||
doc.statics = doc.statics.filter(staticMethod => !staticMethod.tags.tagsByName.get('hidden'));
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -1,11 +0,0 @@
|
||||
"use strict";
|
||||
module.exports = [
|
||||
{'name': 'advanced'},
|
||||
{'name': 'demo'},
|
||||
{'name': 'beta', transforms: (doc, tag, value) => typeof value !== 'undefined'}, // make the value true or undefined instead of '' or undefined
|
||||
{'name': 'usage'},
|
||||
{'name': 'hidden'}, // hide from docs
|
||||
{'name': 'classes'}, // related classes
|
||||
{'name': 'interfaces'}, // related interfaces
|
||||
{'name': 'paid', transforms: (doc, tag, value) => typeof value !== 'undefined'} // paid plugin, set value to true
|
||||
];
|
||||
@@ -1,10 +0,0 @@
|
||||
<li class="capitalize {% if page.id == 'overview' %}active{% endif %}">
|
||||
<a href="/docs/native/">Overview</a>
|
||||
</li>
|
||||
<li class="capitalize {% if page.id == 'mocking' %}active{% endif %}">
|
||||
<a href="/docs/native/browser.html">Browser Usage</a>
|
||||
</li>
|
||||
<@- for doc in docs @><@ if doc.URL and doc.private != true @>
|
||||
<li class="capitalize {% if page.id == '<$ doc.name|lower|dashify $>' %}active{% endif %}">
|
||||
<a href="<$ doc.URL $>"><$ doc.name $><@ if doc.paid == true @> <span class="paid">Paid</span><@ endif @><@ if doc.beta == true @> <span class="beta">β</span><@ endif @></a>
|
||||
</li><@ endif @><@ endfor @>
|
||||
@@ -1,38 +0,0 @@
|
||||
<a style="float:right;font-size:12px;" href="http://github.com/ionic-team/ionic-native/edit/master/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/') $>#L<$ doc.location.start.line $>">
|
||||
Improve this doc
|
||||
</a>
|
||||
|
||||
# <$ doc.name $>
|
||||
|
||||
<@- if doc.beta == true @>
|
||||
<p style="color:orange">
|
||||
This plugin is still in beta stage and may not work as expected. Please
|
||||
submit any issues to the <a target="_blank"
|
||||
href="<$ prop.repo $>/issues">plugin repo</a>.
|
||||
</p>
|
||||
<@ endif -@>
|
||||
|
||||
|
||||
<@ for prop in doc.decorators[0].argumentInfo @>
|
||||
|
||||
```
|
||||
$ <@ if prop.install @><$ prop.install $><@ else @>ionic cordova plugin add <$ prop.plugin $><@ endif @>
|
||||
$ npm install @ionic-native/<$ doc.npmId $>
|
||||
```
|
||||
|
||||
## [Usage Documentation](https://ionicframework.com/docs/native/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/')|replace('index.ts','')|replace('src/@ionic-native/plugins/','') $>)
|
||||
|
||||
Plugin Repo: [<$ prop.repo $>](<$ prop.repo $>)
|
||||
|
||||
<$ doc.description $>
|
||||
|
||||
<@- if prop.platforms @>
|
||||
|
||||
## Supported platforms
|
||||
<@ for platform in prop.platforms -@>
|
||||
- <$ platform $>
|
||||
<@ endfor @>
|
||||
|
||||
<@ endif -@>
|
||||
|
||||
<@ endfor @>
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
name: 'capital',
|
||||
process: function(str) {
|
||||
str || (str = '');
|
||||
return str.charAt(0).toUpperCase() + str.substring(1);
|
||||
}
|
||||
};
|
||||
@@ -1,5 +1,4 @@
|
||||
"use strict";
|
||||
const encoder = new require('node-html-encoder').Encoder();
|
||||
var encoder = new require('node-html-encoder').Encoder();
|
||||
|
||||
function code(str, inline, lang) {
|
||||
// Encode any HTML entities in the code string
|
||||
@@ -11,14 +10,16 @@ function code(str, inline, lang) {
|
||||
str = '<code' + lang + '>' + str + '</code>';
|
||||
|
||||
// If not inline then wrap the code element in a pre element
|
||||
if (!inline) {
|
||||
if ( !inline ) {
|
||||
str = '<pre>' + str + '</pre>';
|
||||
}
|
||||
|
||||
return str;
|
||||
}
|
||||
};
|
||||
|
||||
module.exports = {
|
||||
name: 'code',
|
||||
process: (str, lang) => code(str, true, lang)
|
||||
process: function(str, lang) {
|
||||
return code(str, true, lang);
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,7 @@
|
||||
module.exports = {
|
||||
name: 'dashify',
|
||||
process: function(str) {
|
||||
str || (str = '');
|
||||
return str.replace(/\s/g, '-');
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,6 @@
|
||||
module.exports = {
|
||||
name: 'dump',
|
||||
process: function(obj) {
|
||||
console.log(obj);
|
||||
}
|
||||
};
|
||||
+19
-30
@@ -1,42 +1,31 @@
|
||||
'use strict';
|
||||
const config = require('./config.json'),
|
||||
projectPackage = require('../../package.json'),
|
||||
path = require('path'),
|
||||
fs = require('fs-extra'),
|
||||
Dgeni = require('dgeni');
|
||||
|
||||
module.exports = gulp => {
|
||||
gulp.task('docs', [], () => {
|
||||
var config = require('../config.json');
|
||||
var projectPackage = require('../../package.json');
|
||||
module.exports = function(gulp) {
|
||||
gulp.task('docs', [], function() {
|
||||
var Dgeni = require('dgeni');
|
||||
var semver = require('semver');
|
||||
try {
|
||||
const ionicPackage = require('./dgeni/dgeni-config')(
|
||||
projectPackage.version
|
||||
),
|
||||
dgeni = new Dgeni([ionicPackage]);
|
||||
|
||||
return dgeni
|
||||
.generate()
|
||||
.then(docs => console.log(docs.length + ' docs generated'));
|
||||
var ionicPackage = require('./dgeni-config')(projectPackage.version);
|
||||
var dgeni = new Dgeni([ionicPackage]);
|
||||
return dgeni.generate().then(function(docs) {
|
||||
console.log(docs.length + ' docs generated');
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
});
|
||||
|
||||
gulp.task('readmes', [], function() {
|
||||
fs.copySync(
|
||||
path.resolve(__dirname, '..', '..', 'README.md'),
|
||||
path.resolve(__dirname, '..', '..', config.pluginDir, 'core', 'README.md')
|
||||
);
|
||||
|
||||
var Dgeni = require('dgeni');
|
||||
var semver = require('semver');
|
||||
try {
|
||||
const ionicPackage = require('./dgeni/dgeni-readmes-config')(
|
||||
projectPackage.version
|
||||
),
|
||||
dgeni = new Dgeni([ionicPackage]);
|
||||
return dgeni
|
||||
.generate()
|
||||
.then(docs => console.log(docs.length + ' README files generated'));
|
||||
var ionicPackage = require('./dgeni-readmes-config')(projectPackage.version);
|
||||
var dgeni = new Dgeni([ionicPackage]);
|
||||
return dgeni.generate().then(function(docs) {
|
||||
console.log(docs.length + ' README files generated');
|
||||
});
|
||||
} catch (err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
});
|
||||
};
|
||||
}
|
||||
|
||||
@@ -30,8 +30,8 @@ function run {
|
||||
git pull origin master
|
||||
fi
|
||||
|
||||
git rm -rf content/docs/native/*/ || true
|
||||
git rm -rf content/docs/v2/native/*/ || true
|
||||
|
||||
}
|
||||
|
||||
source $(dirname $0)/utils.inc.sh
|
||||
source $(dirname $0)/../utils.inc.sh
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
module.exports = function collectInputsOutputs() {
|
||||
return {
|
||||
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
docs.forEach(function(doc) {
|
||||
|
||||
if (doc.statics && doc.statics.length) {
|
||||
for (var i in doc.statics) {
|
||||
// identify properties to differentiate from methods
|
||||
if (typeof doc.statics[i].parameters == 'undefined') {
|
||||
doc.statics[i].isProperty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (doc.members && doc.members.length) {
|
||||
var members = [];
|
||||
var inputs = [];
|
||||
var outputs = [];
|
||||
|
||||
memberLoop:
|
||||
for (var i in doc.members) {
|
||||
|
||||
// identify properties to differentiate from methods
|
||||
if (typeof doc.members[i].parameters == 'undefined') {
|
||||
doc.members[i].isProperty = true;
|
||||
}
|
||||
|
||||
if (doc.members[i].decorators && doc.members[i].decorators.length) {
|
||||
|
||||
decoratorLoop:
|
||||
for (var ii in doc.members[i].decorators) {
|
||||
|
||||
if (doc.members[i].decorators[ii].name == 'Input') {
|
||||
inputs.push(parseMember(doc.members[i]));
|
||||
continue memberLoop;
|
||||
}
|
||||
if (doc.members[i].decorators[ii].name == 'Output') {
|
||||
outputs.push(parseMember(doc.members[i]));
|
||||
continue memberLoop;
|
||||
}
|
||||
}
|
||||
// not an input or output, must be a plain member
|
||||
members.push(doc.members[i]);
|
||||
} else {
|
||||
members.push(doc.members[i]);
|
||||
};
|
||||
}
|
||||
|
||||
// update doc with pruned members list and add inputs and outputs
|
||||
doc.members = members;
|
||||
doc.inputs = inputs;
|
||||
doc.outputs = outputs;
|
||||
}
|
||||
|
||||
function parseMember(member) {
|
||||
member.type = member.content.substring(
|
||||
member.content.indexOf('{') + 1,
|
||||
member.content.indexOf('}')
|
||||
);
|
||||
member.description = member.content.substring(
|
||||
member.content.indexOf('}') + 1,
|
||||
member.content.length
|
||||
);
|
||||
return member;
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,18 @@
|
||||
module.exports = function removePrivateApi() {
|
||||
return {
|
||||
name: 'remove-private-api',
|
||||
description: 'Prevent the private apis from being rendered',
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
var publicDocs = [];
|
||||
docs.forEach(function(doc){
|
||||
if (!doc.private && (!doc.tags || !doc.tags.tagsByName.get('hidden'))){
|
||||
publicDocs.push(doc);
|
||||
return doc
|
||||
}
|
||||
});
|
||||
docs = publicDocs;
|
||||
return docs;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,39 @@
|
||||
module.exports = function jekyll(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'jekyll',
|
||||
description: 'Create jekyll includes',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
var currentVersion = renderDocsProcessor.extraData.version.current.name;
|
||||
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter(function(doc) {
|
||||
return (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page';
|
||||
});
|
||||
docs.sort(function(a, b) {
|
||||
textA = a.name ? a.name.toUpperCase() : '';
|
||||
textB = b.name ? b.name.toUpperCase() : '';
|
||||
return (textA < textB) ? -1 : (textA > textB) ? 1 : 0;
|
||||
});
|
||||
docs.forEach(function(doc, i) {
|
||||
doc.outputPath = doc.outputPath.toLowerCase().replace(/\s/g, '-');
|
||||
docs[i].URL = doc.outputPath.replace('docs/v2//', 'docs/v2/')
|
||||
.replace('/index.md', '')
|
||||
.replace('content/', '');
|
||||
|
||||
docs[i].demo = !!docs[i].demo;
|
||||
});
|
||||
|
||||
docs.push({
|
||||
docType: 'native_menu-menu',
|
||||
id: 'native_menu-menu',
|
||||
template: 'native_menu.template.html',
|
||||
outputPath: 'content/_includes/v2_fluid/native_menu.html'
|
||||
});
|
||||
|
||||
// returning docs will replace docs object in the next process
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,33 @@
|
||||
var copy = require('cpr').cpr;
|
||||
var mkdirp = require('mkdirp');
|
||||
var path = require('canonical-path');
|
||||
var q = require('q');
|
||||
var fs = require('fs');
|
||||
|
||||
module.exports = function latestVersion(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'latest-version',
|
||||
$runAfter: ['files-written'],
|
||||
description: 'Copy the latest version (that was compiled to docs/) into docs/versionName',
|
||||
$process: function(docs) {
|
||||
var versionData = renderDocsProcessor.extraData.version;
|
||||
|
||||
var docsBase = 'dist/ionic-site/content/docs/v2/';
|
||||
var versionDir = path.resolve(docsBase, versionData.latest.name);
|
||||
var latestDir = path.resolve(docsBase, 'api');
|
||||
|
||||
var deferred = q.defer();
|
||||
|
||||
mkdirp(versionDir, function() {
|
||||
copy(latestDir, path.join(versionDir, 'api'), {
|
||||
deleteFirst: true,
|
||||
overwrite: true
|
||||
}, function(err, files) {
|
||||
deferred.resolve(docs);
|
||||
});
|
||||
});
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,25 @@
|
||||
module.exports = function jekyll(renderDocsProcessor) {
|
||||
return {
|
||||
name: 'readmes',
|
||||
description: 'Create jekyll includes',
|
||||
$runAfter: ['paths-computed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
var currentVersion = renderDocsProcessor.extraData.version.current.name;
|
||||
|
||||
// pretty up and sort the docs object for menu generation
|
||||
docs = docs.filter(function(doc) {
|
||||
return (!!doc.name && !!doc.outputPath) || doc.docType === 'index-page';
|
||||
});
|
||||
|
||||
docs.forEach(function(doc, i) {
|
||||
doc.npmId = doc.outputPath.replace('/README.md', '')
|
||||
.replace('src/@ionic-native/plugins/','');
|
||||
doc.outputPath = doc.outputPath.replace('src/', '');
|
||||
});
|
||||
|
||||
// returning docs will replace docs object in the next process
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,27 @@
|
||||
module.exports = function removePrivateMembers() {
|
||||
return {
|
||||
name: 'remove-private-members',
|
||||
description: 'Remove member docs with @private tags',
|
||||
$runAfter: ['tags-parsed'],
|
||||
$runBefore: ['rendering-docs'],
|
||||
$process: function(docs) {
|
||||
docs.forEach(function(doc) {
|
||||
|
||||
if (doc.members) {
|
||||
doc.members = doc.members.filter(function(member) {
|
||||
return !member.tags.tagsByName.get('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
if (doc.statics) {
|
||||
doc.statics = doc.statics.filter(function(staticMethod) {
|
||||
return !staticMethod.tags.tagsByName.get('hidden');
|
||||
});
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return docs;
|
||||
}
|
||||
};
|
||||
};
|
||||
@@ -0,0 +1,12 @@
|
||||
module.exports = [
|
||||
{'name': 'advanced'},
|
||||
{'name': 'demo'},
|
||||
{'name': 'beta', transforms: function(doc, tag, value) {
|
||||
// make the value true or undefined instead of '' or undefined
|
||||
return typeof value !== 'undefined';
|
||||
}},
|
||||
{'name': 'usage'},
|
||||
{'name': 'hidden'}, // hide from docs
|
||||
{'name': 'classes'}, // related classes
|
||||
{'name': 'interfaces'} // related interfaces
|
||||
];
|
||||
Vendored
+170
-98
@@ -1,5 +1,5 @@
|
||||
---
|
||||
layout: "fluid/docs_base"
|
||||
layout: "v2_fluid/docs_base"
|
||||
version: "<$ version.current.name $>"
|
||||
versionHref: "<$ version.current.href.replace('content/','') $>"
|
||||
path: "<$ doc.path $>"
|
||||
@@ -11,7 +11,7 @@ doc: "<$ doc.name $>"
|
||||
docType: "<$ doc.docType $>"
|
||||
---
|
||||
|
||||
<@- macro interfaceTable(interface) -@>
|
||||
<@ macro interfaceTable(interface) @>
|
||||
<@ for export in doc.moduleDoc.exports -@>
|
||||
<@ if export.name == interface @>
|
||||
<table class="table param-table" style="margin:0;">
|
||||
@@ -27,27 +27,36 @@ docType: "<$ doc.docType $>"
|
||||
<tr>
|
||||
<td>
|
||||
<$ param.name $>
|
||||
<@ if param.optional @><div><em>(optional)</em></div><@ endif @>
|
||||
</td>
|
||||
<td>
|
||||
<code><$ param.returnType | escape $></code>
|
||||
</td>
|
||||
<td>
|
||||
<$ param.description | marked $>
|
||||
<@ if param.optional @><em>(optional)</em><@ endif @>
|
||||
</td>
|
||||
</tr>
|
||||
<@ endfor @>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
<@ endif @>
|
||||
<@- endfor @>
|
||||
<@ endmacro @>
|
||||
|
||||
<@ macro paramList(paramData) -@>
|
||||
<@- if paramData -@><span class="params">(
|
||||
<@- for param in paramData -@>
|
||||
<span class="param"><$ param | escape $><@ if not loop.last @>, <@ endif @></span>
|
||||
<@- endfor @>)</span>
|
||||
<@- endif @>
|
||||
<@- endmacro -@>
|
||||
|
||||
<@- macro githubViewLink(doc) -@>
|
||||
<a href="https://github.com/ionic-team/ionic-native/tree/master/<$ doc.fileInfo.relativePath $>#L<$ doc.location.start.line+1 $>-L<$ doc.location.end.line+1 $>"><$ doc.fileInfo.relativePath $> (line <$ doc.location.start.line+1 $>)</a>
|
||||
<@ macro githubViewLink(doc) -@>
|
||||
<a href="https://github.com/driftyco/ionic-native/tree/master/<$ doc.fileInfo.relativePath $>#L<$ doc.location.start.line+1 $>-L<$ doc.location.end.line+1 $>"><$ doc.fileInfo.relativePath $> (line <$ doc.location.start.line+1 $>)</a>
|
||||
<@- endmacro -@>
|
||||
|
||||
<@- macro paramTable(params, isDirective) -@>
|
||||
<@ macro paramTable(params, isDirective) -@>
|
||||
<table class="table param-table" style="margin:0;">
|
||||
<thead>
|
||||
<tr>
|
||||
@@ -57,108 +66,156 @@ docType: "<$ doc.docType $>"
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<@- for param in params @>
|
||||
<@ for param in params @>
|
||||
<tr>
|
||||
<td>
|
||||
<$ param.name $>
|
||||
<@- if param.alias @>| <$ param.alias $><@ endif -@>
|
||||
<@ if param.alias @>| <$ param.alias $><@ endif @>
|
||||
<@ if param.type.optional @><div><em>(optional)</em></div><@ endif @>
|
||||
</td>
|
||||
<td>
|
||||
<$ typeList(param.typeList) $>
|
||||
</td>
|
||||
<td>
|
||||
<$ param.description | marked $>
|
||||
<@- if param.defaultValue @><p><em>(default: <$ param.defaultValue $>)</em></p><@ endif -@>
|
||||
<@ if param.default @><p><em>(default: <$ param.default $>)</em></p><@ endif @>
|
||||
</td>
|
||||
</tr>
|
||||
<@ endfor -@>
|
||||
<@ endfor @>
|
||||
</tbody>
|
||||
</table>
|
||||
<@- endmacro -@>
|
||||
|
||||
|
||||
<@- macro functionSyntax(fn) @>
|
||||
<@- set sep = joiner(', ') -@>
|
||||
<code><$ fn.name $><@- if not fn.isProperty @>(<@ endif -@><@- for param in fn.params @><$ sep() $>
|
||||
<@- if param.type.optional @>[<@- endif -@>
|
||||
<@- if param.type.optional @>[<@ endif -@>
|
||||
<$ param.name $>
|
||||
<@- if param.type.optional -@>]<@- endif -@>
|
||||
<@- endfor -@><@- if not fn.isProperty @>)<@- endif -@></code>
|
||||
<@- endmacro -@>
|
||||
<@- if param.type.optional @>]<@ endif -@>
|
||||
<@ endfor @><@- if not fn.isProperty @>)<@ endif -@></code>
|
||||
<@ if fn.alias @><small>(alias: <$ fn.alias $>)</small><@ endif @>
|
||||
<@ endmacro -@>
|
||||
|
||||
<@- macro typeList(types) -@>
|
||||
<@ macro typeList(types) -@>
|
||||
<@ set separator = joiner("|") @>
|
||||
<@- for type in types @><$ separator() $><$ type | code $><@ endfor -@>
|
||||
<@ for type in types @><$ separator() $><$ type | code $><@ endfor @>
|
||||
<@- endmacro -@>
|
||||
|
||||
<@- macro typeInfo(fn) -@>
|
||||
<$ typeList(fn.typeList) $> <$ fn.description $>
|
||||
<@- endmacro -@>
|
||||
|
||||
<@- macro documentPlatforms(method) -@>
|
||||
|
||||
|
||||
<@ macro documentClass(doc) @>
|
||||
<@- if doc.statics.length -@>
|
||||
<h2>Static Members</h2>
|
||||
<@ for method in doc.statics -@>
|
||||
<@ if not method.internal @>
|
||||
<div id="<$ method.name $>"></div>
|
||||
<h3><$ functionSyntax(method) $></h3>
|
||||
<@- if method.decorators @>
|
||||
<@ for prop in method.decorators[0].argumentInfo @>
|
||||
<@ if prop.platforms @>
|
||||
<p>
|
||||
<strong>Platforms:</strong>
|
||||
<@- for platform in prop.platforms -@>
|
||||
<strong class="tag"><$ platform $></strong>
|
||||
<@- endfor -@>
|
||||
<b>Platforms:</b>
|
||||
<@- for platform in prop.platforms @>
|
||||
<code><$ platform $></code>
|
||||
<@ endfor -@>
|
||||
</p>
|
||||
<@ endif @>
|
||||
<@ endfor @>
|
||||
<@- endif @>
|
||||
<@- endmacro -@>
|
||||
|
||||
<@ macro documentMethod(method) -@>
|
||||
<h3><a class="anchor" name="<$ method.name $>" href="#<$ method.name $>"></a><$ functionSyntax(method) $></h3>
|
||||
<$ documentPlatforms(method) $>
|
||||
<$ method.description $>
|
||||
|
||||
<@ if method.params @>
|
||||
<$ paramTable(method.params) $>
|
||||
<@ endif @>
|
||||
|
||||
<@ if method.this -@>
|
||||
<h4> Method's `this`
|
||||
<$ method.this $>
|
||||
</h4>
|
||||
<@- endif @>
|
||||
|
||||
<@ if method.returns @>
|
||||
<div class="return-value" markdown="1">
|
||||
<i class="icon ion-arrow-return-left"></i>
|
||||
<b>Returns:</b> <$ typeInfo(method.returns) $>
|
||||
</div>
|
||||
<@ endif @>
|
||||
<@ endif @>
|
||||
<@ endfor -@>
|
||||
<@ endif @>
|
||||
|
||||
<!-- methods on the class -->
|
||||
<@- if doc.members and doc.members.length @>
|
||||
|
||||
<h2>Instance Members</h2>
|
||||
<@ for method in doc.members -@>
|
||||
<div id="<$ method.name $>"></div>
|
||||
<h3>
|
||||
<$ functionSyntax(method) $>
|
||||
</h3>
|
||||
<$ method.description $>
|
||||
<@ if method.params -@>
|
||||
<$ paramTable(method.params) $>
|
||||
<@- endif @>
|
||||
|
||||
<@ if method.this -@>
|
||||
<h4> Method's `this`
|
||||
<$ method.this $>
|
||||
</h4>
|
||||
<@- endif @>
|
||||
<@ if method.returns -@>
|
||||
<div class="return-value" markdown="1">
|
||||
<i class="icon ion-arrow-return-left"></i>
|
||||
<b>Returns:</b> <$ typeInfo(method.returns) $>
|
||||
</div>
|
||||
<@- endif @>
|
||||
<@- endmacro -@>
|
||||
|
||||
<@- macro documentClass(doc) @>
|
||||
<@- if doc.statics.length -@>
|
||||
<h2><a class="anchor" name="static-members" href="#static-members"></a>Static Members</h2>
|
||||
<@ for method in doc.statics -@>
|
||||
<$ documentMethod(method) $>
|
||||
<@ endfor -@>
|
||||
<@ endif @>
|
||||
|
||||
<# --- methods in class --- #>
|
||||
<@- if doc.members and doc.members.length @>
|
||||
|
||||
<h2><a class="anchor" name="instance-members" href="#instance-members"></a>Instance Members</h2>
|
||||
<@ for method in doc.members -@>
|
||||
<$ documentMethod(method) $>
|
||||
<@- endfor @>
|
||||
<@- endif -@>
|
||||
<@ endmacro @>
|
||||
<@ block body @>
|
||||
<@ block content @>
|
||||
<@ block header @>
|
||||
<h1 class="api-title">
|
||||
<@ if doc.docType == "directive" @>
|
||||
<$ doc.name | dashCase $>
|
||||
<@ else @>
|
||||
<$ doc.name $>
|
||||
<@ endif @>
|
||||
|
||||
<h1 class="api-title"><$ doc.name $>
|
||||
<@ if doc.parent @>
|
||||
<br />
|
||||
<small>
|
||||
Child of <$ doc.parent $>
|
||||
</small>
|
||||
<@ endif @>
|
||||
|
||||
<@ if doc.delegate @>
|
||||
<br/>
|
||||
<small>
|
||||
Delegate: <$ doc.delegate $>
|
||||
</small>
|
||||
<@ endif @>
|
||||
<@- if doc.beta == true -@>
|
||||
<span class="beta" title="beta">β</span>
|
||||
<@- endif -@>
|
||||
<@- if doc.paid == true -@>
|
||||
<span class="paid" title="paid">Paid</span>
|
||||
<@- endif -@>
|
||||
</h1>
|
||||
|
||||
<a class="improve-v2-docs" href="http://github.com/ionic-team/ionic-native/edit/master/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/') $>#L<$ doc.location.start.line $>">
|
||||
<a class="improve-v2-docs" href="http://github.com/driftyco/ionic-native/edit/master/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/') $>#L<$ doc.location.start.line $>">
|
||||
Improve this doc
|
||||
</a>
|
||||
|
||||
<# --- Decorators --- #>
|
||||
<@ endblock @>
|
||||
|
||||
<!-- decorators -->
|
||||
<@- if doc.decorators @>
|
||||
|
||||
<@ for prop in doc.decorators[0].argumentInfo @>
|
||||
|
||||
<@ if doc.beta == true @>
|
||||
<p class="beta-notice">
|
||||
This plugin is still in beta stage and may not work as expected. Please
|
||||
@@ -166,58 +223,59 @@ docType: "<$ doc.docType $>"
|
||||
href="<$ prop.repo $>/issues">plugin repo</a>.
|
||||
</p>
|
||||
<@ endif @>
|
||||
<@ if doc.paid == true @>
|
||||
<p class="paid-notice">
|
||||
This plugin might require a paid license, or might take a share of your app's earnings.
|
||||
Check the <a target="_blank" rel="nofollow" href="<$ prop.repo $>">plugin's repo</a> for more information.
|
||||
</p>
|
||||
<@ endif @>
|
||||
|
||||
<# --- Plugin description --- #>
|
||||
<$ doc.description | marked $>
|
||||
|
||||
<pre><code>
|
||||
$ <@ if prop.install @><$ prop.install $><@ else @>ionic plugin add <$ prop.plugin $><@ endif -@>
|
||||
$ npm install --save @ionic-native/<$ prop.pluginRef $>
|
||||
</code></pre>
|
||||
<p>Repo:
|
||||
<a href="<$ prop.repo $>">
|
||||
<$ prop.repo $>
|
||||
</a>
|
||||
</p>
|
||||
|
||||
<# --- Install commands --- #>
|
||||
<h2><a class="anchor" name="installation" href="#installation"></a>Installation</h2>
|
||||
<ol class="installation">
|
||||
<li>Install the Cordova and Ionic Native plugins:<br>
|
||||
<pre><code class="nohighlight">$ <@ if prop.install @><$ prop.install | replace('<', '<').replace('>', '>') $><@ else @>ionic cordova plugin add <$ prop.plugin $><@ endif @>
|
||||
$ npm install @ionic-native/<$ doc.npmId $>
|
||||
</code></pre>
|
||||
</li>
|
||||
<li><a href="https://ionicframework.com/docs/native/#Add_Plugins_to_Your_App_Module">Add this plugin to your app's module</a></li>
|
||||
</ol>
|
||||
<!-- description -->
|
||||
<@ block description @>
|
||||
<$ doc.description | marked $>
|
||||
<@ endblock @>
|
||||
|
||||
|
||||
<@- if doc.directiveInfo @>
|
||||
<h2><$ doc.directiveInfo.type $></h2>
|
||||
<h3><$ doc.directiveInfo.properties[0].name $>: <code><$ doc.directiveInfo.properties[0].values $></code></h3>
|
||||
<@ endif -@>
|
||||
|
||||
<# --- Plugin supported platforms --- #>
|
||||
<@ if prop.platforms @>
|
||||
<h2><a class="anchor" name="platforms" href="#platforms"></a>Supported platforms</h2>
|
||||
<!-- @platforms tag -->
|
||||
<h2>Supported platforms</h2>
|
||||
<@ block platforms @>
|
||||
<ul>
|
||||
<@ for platform in prop.platforms -@>
|
||||
<li><$ platform $></li>
|
||||
<@- endfor @>
|
||||
</ul>
|
||||
<@ endblock @>
|
||||
<!-- @platforms tag end -->
|
||||
<@ endif @>
|
||||
<@ endfor @>
|
||||
<@ endif -@> <# --- end of: if doc.decorators --- #>
|
||||
<@ endif -@><!-- if doc.decorators -->
|
||||
|
||||
<# --- Plugin usage --- #>
|
||||
<!-- @usage tag -->
|
||||
<@ if doc.usage @>
|
||||
<h2><a class="anchor" name="usage" href="#usage"></a>Usage</h2>
|
||||
<h2>Usage</h2>
|
||||
<@ block usage @>
|
||||
<$ doc.usage | marked $>
|
||||
<@ endblock @>
|
||||
<@ endif @>
|
||||
|
||||
<# --- Plugin attributes --- #>
|
||||
<@- if doc.properties -@>
|
||||
<h2><a class="anchor" name="attributes" href="#attributes"></a>Attributes:</h2>
|
||||
<!-- @property tags -->
|
||||
<@ if doc.properties @>
|
||||
<h2>Attributes:</h2>
|
||||
<table class="table" style="margin:0;">
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Attribute</th>
|
||||
|
||||
<@ set hasTypes = false @>
|
||||
<@ for prop in doc.properties @>
|
||||
<@ if prop.type @>
|
||||
@@ -227,11 +285,12 @@ $ npm install @ionic-native/<$ doc.npmId $>
|
||||
<@ if hasTypes @>
|
||||
<th>Type</th>
|
||||
<@ endif @>
|
||||
|
||||
<th>Description</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<@- for prop in doc.properties -@>
|
||||
<@ for prop in doc.properties -@>
|
||||
<tr>
|
||||
<td>
|
||||
<$ prop.name $>
|
||||
@@ -241,44 +300,48 @@ $ npm install @ionic-native/<$ doc.npmId $>
|
||||
<$ prop.type.name $>
|
||||
</td>
|
||||
<@ endif @>
|
||||
|
||||
<td>
|
||||
<$ prop.description $>
|
||||
</td>
|
||||
</tr>
|
||||
<@ endfor -@>
|
||||
<@- endfor @>
|
||||
</tbody>
|
||||
</table>
|
||||
<@- endif -@>
|
||||
<@ endif @>
|
||||
|
||||
<# --- Plugin class documentation --- #>
|
||||
<$ documentClass(doc) $>
|
||||
|
||||
<# --- Advanced usage --- #>
|
||||
<@ block advanced @>
|
||||
<@- if doc.advanced -@>
|
||||
<h2><a class="anchor" name="advanced" href="#advanced"></a>Advanced</h2>
|
||||
<$ doc.advanced | marked $>
|
||||
<@- endif -@>
|
||||
<@ endblock @>
|
||||
|
||||
<# --- Other classes --- #>
|
||||
<@- for tag in doc.tags.tags -@>
|
||||
<@- if tag.tagName == 'classes' -@>
|
||||
<@- set classes = tag.description.split('\n') -@>
|
||||
<@- for item in classes -@>
|
||||
<@- if item.length > 1 -@>
|
||||
<@- for export in doc.moduleDoc.exports -@>
|
||||
<@- if export.name == item -@>
|
||||
<!-- other classes -->
|
||||
<@ for tag in doc.tags.tags -@>
|
||||
<@ if tag.tagName == 'classes' -@>
|
||||
<!--<h2><a class="anchor" name="related-classes" href="#related-classes"></a>Related Classes</h2>-->
|
||||
<@ set classes = tag.description.split('\n') @>
|
||||
<@ for item in classes -@>
|
||||
<@ if item.length > 1 @>
|
||||
<@ for export in doc.moduleDoc.exports -@>
|
||||
<@ if export.name == item @>
|
||||
<h2><a class="anchor" name="<$ item $>" href="#<$ item $>"></a><$ item $></h2>
|
||||
<$ documentClass(export) $>
|
||||
<@- endif -@>
|
||||
<@- endfor -@>
|
||||
<@- endif -@>
|
||||
<@- endfor -@>
|
||||
<@- endif -@>
|
||||
<@- endfor -@>
|
||||
<@ endif @>
|
||||
<@- endfor @>
|
||||
<@ endif @>
|
||||
<@- endfor @>
|
||||
<@- endif @>
|
||||
<@- endfor @>
|
||||
<!-- end other classes -->
|
||||
|
||||
<# --- Other interfaces --- #>
|
||||
<!-- interfaces -->
|
||||
<@ for tag in doc.tags.tags -@>
|
||||
<@ if tag.tagName == 'interfaces' @>
|
||||
<!--<h2><a class="anchor" name="interfaces" href="#interfaces"></a>Interfaces</h2>-->
|
||||
<@ set interfaces = tag.description.split('\n') @>
|
||||
<@ for item in interfaces -@>
|
||||
<@ if item.length > 1 @>
|
||||
@@ -288,12 +351,21 @@ $ npm install @ionic-native/<$ doc.npmId $>
|
||||
<@- endfor @>
|
||||
<@ endif @>
|
||||
<@- endfor @>
|
||||
<!-- end interfaces -->
|
||||
|
||||
|
||||
<# --- Related links --- #>
|
||||
<!-- related link -->
|
||||
<@- if doc.see @>
|
||||
<h2><a class="anchor" name="related" href="#related"></a>Related</h2>
|
||||
|
||||
<h2>Related</h2>
|
||||
<@ for s in doc.see @>
|
||||
<$ s | safe $>
|
||||
<@- endfor -@>
|
||||
|
||||
<@- endif -@>
|
||||
|
||||
|
||||
<!-- end content block -->
|
||||
<@ endblock @>
|
||||
|
||||
<!-- end body block -->
|
||||
<@ endblock @>
|
||||
@@ -0,0 +1,9 @@
|
||||
<@ for doc in docs @><@ if doc.URL and doc.private != true and doc.beta != true @>
|
||||
<li class="capitalize {% if page.id == '<$ doc.name|lower|dashify $>' %}active{% endif %}">
|
||||
<a href="/<$ doc.URL $>"><$ doc.name $></a>
|
||||
</li><@ endif @><@ endfor @>
|
||||
|
||||
<@ for doc in docs @><@ if doc.URL and doc.private != true and doc.beta == true @>
|
||||
<li class="capitalize {% if page.id == '<$ doc.name|lower|dashify $>' %}active{% endif %}">
|
||||
<a href="/<$ doc.URL $>"><$ doc.name $> <span class="beta">β</span></a>
|
||||
</li><@ endif @><@ endfor @>
|
||||
+38
@@ -0,0 +1,38 @@
|
||||
<a style="float:right;font-size:12px;" href="http://github.com/driftyco/ionic-native/edit/master/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/') $>#L<$ doc.location.start.line $>">
|
||||
Improve this doc
|
||||
</a>
|
||||
|
||||
# <$ doc.name $>
|
||||
|
||||
<@- if doc.beta == true @>
|
||||
<p style="color:orange">
|
||||
This plugin is still in beta stage and may not work as expected. Please
|
||||
submit any issues to the <a target="_blank"
|
||||
href="<$ prop.repo $>/issues">plugin repo</a>.
|
||||
</p>
|
||||
<@ endif -@>
|
||||
|
||||
|
||||
<@ for prop in doc.decorators[0].argumentInfo @>
|
||||
|
||||
```
|
||||
$ <@ if prop.install @><$ prop.install $><@ else @>ionic plugin add <$ prop.plugin $><@ endif @>
|
||||
$ npm install --save @ionic-native/<$ doc.npmId $>
|
||||
```
|
||||
|
||||
## [Usage Documentation](https://ionicframework.com/docs/v2/native/<$ doc.fileInfo.relativePath|replace('/home/ubuntu/ionic-native/', '')|replace('//','/')|replace('index.ts','')|replace('src/@ionic-native/plugins/','') $>)
|
||||
|
||||
Plugin Repo: [<$ prop.repo $>](<$ prop.repo $>)
|
||||
|
||||
<$ doc.description $>
|
||||
|
||||
<@- if prop.platforms @>
|
||||
|
||||
## Supported platforms
|
||||
<@ for platform in prop.platforms -@>
|
||||
- <$ platform $>
|
||||
<@ endfor @>
|
||||
|
||||
<@ endif -@>
|
||||
|
||||
<@ endfor @>
|
||||
@@ -23,19 +23,17 @@ function run {
|
||||
# CD in to the site dir to commit updated docs
|
||||
cd $SITE_DIR
|
||||
|
||||
# Add all files to git
|
||||
git add .
|
||||
|
||||
# if no changes, don't commit
|
||||
CHANGED=$(git diff-index --name-only HEAD 2>/dev/null | wc -l)
|
||||
if [ $CHANGED -eq 0 ];
|
||||
CHANGED=$(git diff-index --name-only HEAD --)
|
||||
if [ -z "$CHANGED" ];
|
||||
then
|
||||
echo "-- No changes detected for the following commit, docs not updated."
|
||||
echo "https://github.com/ionic-team/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
|
||||
echo "https://github.com/driftyco/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
|
||||
else
|
||||
git config --global user.email "hi@ionicframework.com"
|
||||
git config --global user.name "Ionitron"
|
||||
git commit -am "Automated build of native docs ionic-team/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
|
||||
git add -A
|
||||
git commit -am "Automated build of native docs driftyco/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
|
||||
# in case a different commit was pushed to ionic-site during doc/demo gen,
|
||||
# try to rebase around it before pushing
|
||||
git fetch
|
||||
@@ -47,4 +45,4 @@ function run {
|
||||
fi
|
||||
}
|
||||
|
||||
source $(dirname $0)/utils.inc.sh
|
||||
source $(dirname $0)/../utils.inc.sh
|
||||
|
||||
@@ -18,12 +18,12 @@ function run {
|
||||
if [ -z "$CHANGED" ];
|
||||
then
|
||||
echo "-- No changes detected for the following commit, docs not updated."
|
||||
echo "https://github.com/ionic-team/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
|
||||
echo "https://github.com/driftyco/$CIRCLE_PROJECT_REPONAME/commit/$CIRCLE_SHA1"
|
||||
else
|
||||
git config --global user.email "hi@ionicframework.com"
|
||||
git config --global user.name "Ionitron"
|
||||
git add -A
|
||||
git commit -am "Automated build of native readmes for ionic-team/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
|
||||
git commit -am "Automated build of native readmes for driftyco/$CIRCLE_PROJECT_REPONAME@$CIRCLE_SHA1"
|
||||
# in case a different commit was pushed to ionic-site during doc/demo gen,
|
||||
# try to rebase around it before pushing
|
||||
git fetch
|
||||
@@ -31,7 +31,7 @@ function run {
|
||||
|
||||
# git push origin master || :
|
||||
|
||||
echo "-- Updated docs for $VERSION_NAME successfully!"
|
||||
echo "-- Updated docs for $VERSION_NAME succesfully!"
|
||||
fi
|
||||
}
|
||||
|
||||
|
||||
@@ -21,7 +21,7 @@ function run {
|
||||
git config --global user.email "hi@ionicframework.com"
|
||||
git config --global user.name "Ionitron"
|
||||
|
||||
git clone git@github.com:ionic-team/$REPOSITORY.git $DIRECTORY $ARGS
|
||||
git clone git@github.com:driftyco/$REPOSITORY.git $DIRECTORY $ARGS
|
||||
cd $DIRECTORY
|
||||
git fetch origin --tags
|
||||
cd ../
|
||||
|
||||
@@ -1,2 +0,0 @@
|
||||
git config --global user.email "hi@ionicframework.com"
|
||||
git config --global user.name "Ionitron"
|
||||
@@ -1,11 +0,0 @@
|
||||
import { createLogger, format, transports } from 'winston';
|
||||
|
||||
const { combine, colorize, simple } = format;
|
||||
|
||||
const LOG_LEVEL = 'verbose';
|
||||
|
||||
export const Logger = createLogger({
|
||||
level: LOG_LEVEL,
|
||||
format: combine(colorize(), simple()),
|
||||
transports: [new transports.Console({ level: LOG_LEVEL })]
|
||||
});
|
||||
@@ -1,97 +0,0 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
import * as uglifyJsPlugin from 'uglifyjs-webpack-plugin';
|
||||
import * as unminifiedPlugin from 'unminified-webpack-plugin';
|
||||
import * as webpack from 'webpack';
|
||||
|
||||
import { ROOT } from '../build/helpers';
|
||||
import {
|
||||
cleanEmittedData,
|
||||
EMIT_PATH,
|
||||
InjectableClassEntry
|
||||
} from '../build/transformers/extract-injectables';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
const DIST = path.resolve(ROOT, 'dist');
|
||||
const INDEX_PATH = path.resolve(DIST, 'index.js');
|
||||
const INJECTABLE_CLASSES = fs
|
||||
.readJSONSync(EMIT_PATH)
|
||||
.map((item: InjectableClassEntry) => {
|
||||
item.file =
|
||||
'./' +
|
||||
item.file
|
||||
.split(/[\/\\]+/)
|
||||
.slice(-4, -1)
|
||||
.join('/');
|
||||
return item;
|
||||
});
|
||||
|
||||
const webpackConfig: webpack.Configuration = {
|
||||
mode: 'production',
|
||||
entry: INDEX_PATH,
|
||||
devtool: 'source-map',
|
||||
target: 'web',
|
||||
output: {
|
||||
path: DIST,
|
||||
filename: 'ionic-native.min.js'
|
||||
},
|
||||
resolve: {
|
||||
modules: ['node_modules'],
|
||||
extensions: ['.js'],
|
||||
alias: {
|
||||
'@ionic-native/core': path.resolve(DIST, '@ionic-native/core/index.js')
|
||||
}
|
||||
},
|
||||
module: {
|
||||
rules: [
|
||||
{
|
||||
test: /\.js$/,
|
||||
use: path.resolve(ROOT, 'scripts/build/remove-tslib-helpers.js')
|
||||
}
|
||||
]
|
||||
},
|
||||
plugins: [
|
||||
new webpack.ProvidePlugin({
|
||||
__extends: ['tslib', '__extends']
|
||||
}),
|
||||
new webpack.optimize.OccurrenceOrderPlugin(true),
|
||||
new webpack.DefinePlugin({
|
||||
'process.env.NODE_ENV': JSON.stringify('production')
|
||||
}),
|
||||
new uglifyJsPlugin({
|
||||
sourceMap: true
|
||||
}),
|
||||
new unminifiedPlugin()
|
||||
]
|
||||
};
|
||||
|
||||
function getPluginImport(entry: InjectableClassEntry) {
|
||||
return `import { ${entry.className} } from '${entry.file}';`;
|
||||
}
|
||||
|
||||
function createIndexFile() {
|
||||
let fileContent = '';
|
||||
fileContent += INJECTABLE_CLASSES.map(getPluginImport).join('\n');
|
||||
fileContent += `\nwindow.IonicNative = {\n`;
|
||||
fileContent += INJECTABLE_CLASSES.map(e => e.className).join(',\n');
|
||||
fileContent += '\n};\n';
|
||||
fileContent += `require('./@ionic-native/core/bootstrap').checkReady();\n`;
|
||||
fileContent += `require('./@ionic-native/core/ng1').initAngular1(window.IonicNative);`;
|
||||
|
||||
fs.writeFileSync(INDEX_PATH, fileContent, { encoding: 'utf-8' });
|
||||
}
|
||||
|
||||
function compile() {
|
||||
Logger.profile('build-es5');
|
||||
webpack(webpackConfig, (err, stats) => {
|
||||
Logger.profile('build-es5');
|
||||
if (err) Logger.error('Error occurred while compiling with Webpack', err);
|
||||
else {
|
||||
Logger.info('Compiled ES5 file with Webpack successfully.');
|
||||
}
|
||||
cleanEmittedData();
|
||||
});
|
||||
}
|
||||
|
||||
createIndexFile();
|
||||
compile();
|
||||
@@ -1,46 +0,0 @@
|
||||
import * as fs from 'fs-extra';
|
||||
import * as path from 'path';
|
||||
|
||||
import { PLUGIN_PATHS, ROOT } from '../build/helpers';
|
||||
import { EMIT_PATH } from '../build/transformers/extract-injectables';
|
||||
import { generateDeclarations, transpile } from '../build/transpile';
|
||||
|
||||
generateDeclarations();
|
||||
transpile();
|
||||
|
||||
const outDirs = PLUGIN_PATHS.map(p =>
|
||||
p.replace(path.join(ROOT, 'src'), path.join(ROOT, 'dist')).replace(/[\\/]index.ts/, '')
|
||||
);
|
||||
const injectableClasses = fs.readJSONSync(EMIT_PATH);
|
||||
|
||||
outDirs.forEach(dir => {
|
||||
const classes = injectableClasses.filter(
|
||||
entry => entry.dirName === dir.split(/[\\/]+/).pop()
|
||||
);
|
||||
|
||||
let jsFile: string = fs.readFileSync(path.join(dir, 'index.js'), 'utf-8'),
|
||||
dtsFile: string = fs.readFileSync(path.join(dir, 'index.d.ts'), 'utf-8');
|
||||
|
||||
classes.forEach(entry => {
|
||||
dtsFile = dtsFile.replace(
|
||||
`class ${entry.className} `,
|
||||
'class ' + entry.className + 'Original '
|
||||
);
|
||||
dtsFile += `\nexport declare const ${entry.className}: ${
|
||||
entry.className
|
||||
}Original;`;
|
||||
jsFile = jsFile.replace(
|
||||
new RegExp(`([\\s\\(])${entry.className}([\\s\\.;\\(,])`, 'g'),
|
||||
'$1' + entry.className + 'Original$2'
|
||||
);
|
||||
jsFile = jsFile.replace(
|
||||
`export { ${entry.className}Original }`,
|
||||
`var ${entry.className} = new ${entry.className}Original();\nexport { ${
|
||||
entry.className
|
||||
} }`
|
||||
);
|
||||
});
|
||||
|
||||
fs.writeFileSync(path.join(dir, 'index.js'), jsFile, 'utf-8');
|
||||
fs.writeFileSync(path.join(dir, 'index.d.ts'), dtsFile, 'utf-8');
|
||||
});
|
||||
@@ -1,13 +0,0 @@
|
||||
import {
|
||||
cleanupNgx,
|
||||
generateDeclarationFiles,
|
||||
modifyMetadata,
|
||||
transpileNgx,
|
||||
transpileNgxCore
|
||||
} from '../build/ngx';
|
||||
|
||||
transpileNgxCore();
|
||||
transpileNgx();
|
||||
generateDeclarationFiles();
|
||||
modifyMetadata();
|
||||
cleanupNgx();
|
||||
@@ -1,109 +0,0 @@
|
||||
import * as Queue from 'async-promise-queue';
|
||||
import { exec } from 'child_process';
|
||||
import * as fs from 'fs-extra';
|
||||
import { merge } from 'lodash';
|
||||
import { cpus } from 'os';
|
||||
import * as path from 'path';
|
||||
|
||||
import { PLUGIN_PATHS, ROOT } from '../build/helpers';
|
||||
import { Logger } from '../logger';
|
||||
|
||||
// tslint:disable-next-line:no-var-requires
|
||||
const MAIN_PACKAGE_JSON = require('../../package.json');
|
||||
const VERSION = MAIN_PACKAGE_JSON.version;
|
||||
const FLAGS = '--access public';
|
||||
|
||||
const PACKAGE_JSON_BASE = {
|
||||
description: 'Ionic Native - Native plugins for ionic apps',
|
||||
module: 'index.js',
|
||||
typings: 'index.d.ts',
|
||||
author: 'ionic',
|
||||
license: 'MIT',
|
||||
repository: {
|
||||
type: 'git',
|
||||
url: 'https://github.com/ionic-team/ionic-native.git'
|
||||
}
|
||||
};
|
||||
|
||||
const DIST = path.resolve(ROOT, 'dist/@ionic-native');
|
||||
|
||||
const PACKAGES = [];
|
||||
|
||||
const MIN_CORE_VERSION = '^5.1.0';
|
||||
const RXJS_VERSION = '^6.3.0';
|
||||
|
||||
const PLUGIN_PEER_DEPENDENCIES = {
|
||||
'@ionic-native/core': MIN_CORE_VERSION,
|
||||
rxjs: RXJS_VERSION
|
||||
};
|
||||
|
||||
function getPackageJsonContent(name: string, peerDependencies = {}, dependencies = {}) {
|
||||
return merge(PACKAGE_JSON_BASE, {
|
||||
name: '@ionic-native/' + name,
|
||||
dependencies,
|
||||
peerDependencies,
|
||||
version: VERSION
|
||||
});
|
||||
}
|
||||
|
||||
function writePackageJson(data: any, dir: string) {
|
||||
const filePath = path.resolve(dir, 'package.json');
|
||||
fs.writeJSONSync(filePath, data);
|
||||
PACKAGES.push(dir);
|
||||
}
|
||||
|
||||
function prepare() {
|
||||
// write @ionic-native/core package.json
|
||||
writePackageJson(
|
||||
getPackageJsonContent('core', { rxjs: RXJS_VERSION }, { '@types/cordova': 'latest' }),
|
||||
path.resolve(DIST, 'core')
|
||||
);
|
||||
|
||||
// write plugin package.json files
|
||||
PLUGIN_PATHS.forEach((pluginPath: string) => {
|
||||
const pluginName = pluginPath.split(/[\/\\]+/).slice(-2)[0];
|
||||
const packageJsonContents = getPackageJsonContent(pluginName, PLUGIN_PEER_DEPENDENCIES);
|
||||
const dir = path.resolve(DIST, 'plugins', pluginName);
|
||||
|
||||
writePackageJson(packageJsonContents, dir);
|
||||
});
|
||||
}
|
||||
|
||||
async function publish(ignoreErrors = false) {
|
||||
Logger.profile('Publishing');
|
||||
// upload 1 package per CPU thread at a time
|
||||
const worker = Queue.async.asyncify(
|
||||
(pkg: any) =>
|
||||
new Promise<any>((resolve, reject) => {
|
||||
exec(`npm publish ${pkg} ${FLAGS}`, (err, stdout) => {
|
||||
if (stdout) {
|
||||
Logger.verbose(stdout.trim());
|
||||
resolve(stdout);
|
||||
}
|
||||
if (err) {
|
||||
if (!ignoreErrors) {
|
||||
if (
|
||||
err.message.includes('You cannot publish over the previously published version')
|
||||
) {
|
||||
Logger.verbose('Ignoring duplicate version error.');
|
||||
return resolve();
|
||||
}
|
||||
reject(err);
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
);
|
||||
|
||||
try {
|
||||
await Queue(worker, PACKAGES, cpus().length);
|
||||
Logger.info('Done publishing!');
|
||||
} catch (e) {
|
||||
Logger.error('Error publishing!');
|
||||
Logger.error(e);
|
||||
}
|
||||
Logger.profile('Publishing');
|
||||
}
|
||||
|
||||
prepare();
|
||||
publish();
|
||||
@@ -1,60 +1,24 @@
|
||||
/**
|
||||
* This is a template for new plugin wrappers
|
||||
*
|
||||
* TODO:
|
||||
* - Add/Change information below
|
||||
* - Document usage (importing, executing main functionality)
|
||||
* - Remove any imports that you are not using
|
||||
* - Remove all the comments included in this template, EXCEPT the @Plugin wrapper docs and any other docs you added
|
||||
* - Remove this note
|
||||
*
|
||||
*/
|
||||
import { Plugin } from '@ionic-native/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Plugin, Cordova, CordovaProperty, CordovaInstance, InstanceProperty, IonicNativePlugin } from '@ionic-native/core';
|
||||
import { Observable } from 'rxjs';
|
||||
|
||||
/**
|
||||
* @name {{ Plugin_Name }}
|
||||
* @name Plugin Name
|
||||
* @description
|
||||
* This plugin does something
|
||||
*
|
||||
* @usage
|
||||
* ```typescript
|
||||
* import { {{ PluginName }} } from '@ionic-native/{{ plugin-name }}';
|
||||
* ```
|
||||
* import { PluginName } from 'ionic-native';
|
||||
*
|
||||
*
|
||||
* constructor(private {{ pluginName }}: {{ PluginName }}) { }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
*
|
||||
* this.{{ pluginName }}.functionName('Hello', 123)
|
||||
* .then((res: any) => console.log(res))
|
||||
* .catch((error: any) => console.error(error));
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
@Plugin({
|
||||
pluginName: '{{ PluginName }}',
|
||||
plugin: '', // npm package name, example: cordova-plugin-camera
|
||||
pluginRef: '', // the variable reference to call the plugin, example: navigator.geolocation
|
||||
repo: '', // the github repository URL for the plugin
|
||||
install: '', // OPTIONAL install command, in case the plugin requires variables
|
||||
installVariables: [], // OPTIONAL the plugin requires variables
|
||||
platforms: [] // Array of platforms supported, example: ['Android', 'iOS']
|
||||
pluginName: 'PluginName',
|
||||
plugin: '',
|
||||
pluginRef: '',
|
||||
repo: ''
|
||||
})
|
||||
@Injectable()
|
||||
export class {{ PluginName }} extends IonicNativePlugin {
|
||||
|
||||
/**
|
||||
* This function does something
|
||||
* @param arg1 {string} Some param to configure something
|
||||
* @param arg2 {number} Another param to configure something
|
||||
* @return {Promise<any>} Returns a promise that resolves when something happens
|
||||
*/
|
||||
@Cordova()
|
||||
functionName(arg1: string, arg2: number): Promise<any> {
|
||||
return; // We add return; here to avoid any IDE / Compiler errors
|
||||
}
|
||||
export class PluginName {
|
||||
|
||||
}
|
||||
|
||||
+12
-19
@@ -5,46 +5,39 @@
|
||||
* - Add/Change information below
|
||||
* - Document usage (importing, executing main functionality)
|
||||
* - Remove any imports that you are not using
|
||||
* - Add this file to /src/index.ts (follow style of other plugins)
|
||||
* - Remove all the comments included in this template, EXCEPT the @Plugin wrapper docs and any other docs you added
|
||||
* - Remove this note
|
||||
*
|
||||
*/
|
||||
import { Plugin, Cordova, CordovaProperty, CordovaInstance, InstanceProperty } from '@ionic-native/core';
|
||||
import { Injectable } from '@angular/core';
|
||||
import { Plugin, Cordova, CordovaProperty, CordovaInstance, InstanceProperty, IonicNativePlugin } from '@ionic-native/core';
|
||||
import { Observable } from 'rxjs';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
/**
|
||||
* @name {{ Plugin_Name }}
|
||||
* @name Plugin Name
|
||||
* @description
|
||||
* This plugin does something
|
||||
*
|
||||
* @usage
|
||||
* ```typescript
|
||||
* import { {{ PluginName }} } from '@ionic-native/{{ plugin-name }}';
|
||||
* ```
|
||||
* import { PluginName } from 'ionic-native';
|
||||
*
|
||||
*
|
||||
* constructor(private {{ pluginName }}: {{ PluginName }}) { }
|
||||
*
|
||||
* ...
|
||||
*
|
||||
*
|
||||
* this.{{ pluginName }}.functionName('Hello', 123)
|
||||
* .then((res: any) => console.log(res))
|
||||
* .catch((error: any) => console.error(error));
|
||||
* PluginName.functionName('Hello', 123)
|
||||
* .then((something: any) => doSomething(something))
|
||||
* .catch((error: any) => console.log(error));
|
||||
*
|
||||
* ```
|
||||
*/
|
||||
@Plugin({
|
||||
pluginName: '{{ PluginName }}',
|
||||
pluginName: 'PluginName',
|
||||
plugin: '', // npm package name, example: cordova-plugin-camera
|
||||
pluginRef: '', // the variable reference to call the plugin, example: navigator.geolocation
|
||||
repo: '', // the github repository URL for the plugin
|
||||
install: '', // OPTIONAL install command, in case the plugin requires variables
|
||||
installVariables: [], // OPTIONAL the plugin requires variables
|
||||
platforms: [] // Array of platforms supported, example: ['Android', 'iOS']
|
||||
install: '' // OPTIONAL install command, in case the plugin requires variables
|
||||
})
|
||||
@Injectable()
|
||||
export class {{ PluginName }} extends IonicNativePlugin {
|
||||
export class PluginName {
|
||||
|
||||
/**
|
||||
* This function does something
|
||||
|
||||
@@ -1,12 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"module": "commonjs",
|
||||
"target": "es5",
|
||||
"moduleResolution": "node",
|
||||
"noImplicitAny": false,
|
||||
"lib": ["es6"]
|
||||
},
|
||||
"exclude": [
|
||||
"node_modules"
|
||||
]
|
||||
}
|
||||
Regular → Executable
+3
@@ -1,4 +1,5 @@
|
||||
# bash utils from angularjs
|
||||
|
||||
# This file provides:
|
||||
# - a default control flow
|
||||
# * initializes the environment
|
||||
@@ -35,6 +36,7 @@
|
||||
# Special arguments that are always available:
|
||||
# - "--action=.*": This parameter will be used to dispatch to a function with that name when the
|
||||
# script is started
|
||||
|
||||
# - "--verbose=true": This will set the `-x` flag in bash so that all calls will be logged
|
||||
#
|
||||
# Utility functions:
|
||||
@@ -44,6 +46,7 @@
|
||||
# - getVar
|
||||
# - serVar
|
||||
# - isFunction
|
||||
|
||||
# always stop on errors
|
||||
set -e
|
||||
|
||||
@@ -1,26 +1,23 @@
|
||||
declare var window;
|
||||
|
||||
export function checkReady() {
|
||||
if (typeof process === 'undefined') {
|
||||
const win: any = typeof window !== 'undefined' ? window : {};
|
||||
const DEVICE_READY_TIMEOUT = 5000;
|
||||
const DEVICE_READY_TIMEOUT = 5000;
|
||||
|
||||
// To help developers using cordova, we listen for the device ready event and
|
||||
// log an error if it didn't fire in a reasonable amount of time. Generally,
|
||||
// when this happens, developers should remove and reinstall plugins, since
|
||||
// an inconsistent plugin is often the culprit.
|
||||
const before = Date.now();
|
||||
// To help developers using cordova, we listen for the device ready event and
|
||||
// log an error if it didn't fire in a reasonable amount of time. Generally,
|
||||
// when this happens, developers should remove and reinstall plugins, since
|
||||
// an inconsistent plugin is often the culprit.
|
||||
const before = Date.now();
|
||||
|
||||
let didFireReady = false;
|
||||
win.document.addEventListener('deviceready', () => {
|
||||
console.log(`Ionic Native: deviceready event fired after ${Date.now() - before} ms`);
|
||||
didFireReady = true;
|
||||
});
|
||||
let didFireReady = false;
|
||||
document.addEventListener('deviceready', () => {
|
||||
console.log(`Ionic Native: deviceready event fired after ${(Date.now() - before)} ms`);
|
||||
didFireReady = true;
|
||||
});
|
||||
|
||||
setTimeout(() => {
|
||||
if (!didFireReady && win.cordova) {
|
||||
console.warn(
|
||||
`Ionic Native: deviceready did not fire within ${DEVICE_READY_TIMEOUT}ms. This can happen when plugins are in an inconsistent state. Try removing plugins from plugins/ and reinstalling them.`
|
||||
);
|
||||
}
|
||||
}, DEVICE_READY_TIMEOUT);
|
||||
}
|
||||
setTimeout(() => {
|
||||
if (!didFireReady && window.cordova) {
|
||||
console.warn(`Ionic Native: deviceready did not fire within ${DEVICE_READY_TIMEOUT}ms. This can happen when plugins are in an inconsistent state. Try removing plugins from plugins/ and reinstalling them.`);
|
||||
}
|
||||
}, DEVICE_READY_TIMEOUT);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,344 @@
|
||||
import { instanceAvailability, checkAvailability, wrap, wrapInstance, overrideFunction } from './plugin';
|
||||
import { getPlugin, getPromise } from './util';
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
|
||||
export interface PluginConfig {
|
||||
/**
|
||||
* Plugin name, this should match the class name
|
||||
*/
|
||||
pluginName: string;
|
||||
/**
|
||||
* Plugin NPM package name
|
||||
*/
|
||||
plugin: string;
|
||||
/**
|
||||
* Plugin object reference
|
||||
*/
|
||||
pluginRef?: string;
|
||||
/**
|
||||
* Github repository URL
|
||||
*/
|
||||
repo?: string;
|
||||
/**
|
||||
* Custom install command
|
||||
*/
|
||||
install?: string;
|
||||
/**
|
||||
* Available installation variables
|
||||
*/
|
||||
installVariables?: string[];
|
||||
/**
|
||||
* Supported platforms
|
||||
*/
|
||||
platforms?: string[];
|
||||
}
|
||||
|
||||
export interface CordovaOptions {
|
||||
/**
|
||||
* Set to true if the wrapped method is a sync function
|
||||
*/
|
||||
sync?: boolean;
|
||||
/**
|
||||
* Callback order. Set to reverse if the success/error callbacks are the first 2 arguments that the wrapped method takes.
|
||||
*/
|
||||
callbackOrder?: 'reverse';
|
||||
/**
|
||||
* Callback style
|
||||
*/
|
||||
callbackStyle?: 'node' | 'object';
|
||||
/**
|
||||
* Set a custom index for the success callback function. This doesn't work if callbackOrder or callbackStyle are set.
|
||||
*/
|
||||
successIndex?: number;
|
||||
/**
|
||||
* Set a custom index for the error callback function. This doesn't work if callbackOrder or callbackStyle are set.
|
||||
*/
|
||||
errorIndex?: number;
|
||||
/**
|
||||
* Success function property name. This must be set if callbackStyle is set to object.
|
||||
*/
|
||||
successName?: string;
|
||||
/**
|
||||
* Error function property name. This must be set if callbackStyle is set to object.
|
||||
*/
|
||||
errorName?: string;
|
||||
/**
|
||||
* Set to true to return an observable
|
||||
*/
|
||||
observable?: boolean;
|
||||
/**
|
||||
* If observable is set to true, this can be set to a different function name that will cancel the observable.
|
||||
*/
|
||||
clearFunction?: string;
|
||||
/**
|
||||
* This can be used if clearFunction is set. Set this to true to call the clearFunction with the same arguments used in the initial function.
|
||||
*/
|
||||
clearWithArgs?: boolean;
|
||||
/**
|
||||
* Creates an observable that wraps a global event. Replaces document.addEventListener
|
||||
*/
|
||||
eventObservable?: boolean;
|
||||
/**
|
||||
* Event name, this must be set if eventObservable is set to true
|
||||
*/
|
||||
event?: string;
|
||||
/**
|
||||
* Element to attach the event listener to, this is optional, defaults to `window`
|
||||
*/
|
||||
element?: any;
|
||||
/**
|
||||
* Set to true if the wrapped method returns a promise
|
||||
*/
|
||||
otherPromise?: boolean;
|
||||
/**
|
||||
* Supported platforms
|
||||
*/
|
||||
platforms?: string[];
|
||||
}
|
||||
|
||||
export interface CordovaCheckOptions {
|
||||
sync?: boolean;
|
||||
observable?: boolean;
|
||||
}
|
||||
|
||||
export interface CordovaFiniteObservableOptions extends CordovaOptions {
|
||||
/**
|
||||
* Function that gets a result returned from plugin's success callback, and decides whether it is last value and observable should complete.
|
||||
*/
|
||||
resultFinalPredicate?: (result: any) => boolean;
|
||||
/**
|
||||
* Function that gets called after resultFinalPredicate, and removes service data that indicates end of stream from the result.
|
||||
*/
|
||||
resultTransform?: (result: any) => any;
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function InstanceCheck(opts: CordovaCheckOptions = {}) {
|
||||
return (pluginObj: Object, methodName: string, descriptor: TypedPropertyDescriptor<any>): TypedPropertyDescriptor<any> => {
|
||||
return {
|
||||
value: function(...args: any[]): any {
|
||||
if (instanceAvailability(this)) {
|
||||
return descriptor.value.apply(this, args);
|
||||
} else {
|
||||
|
||||
if (opts.sync) {
|
||||
return;
|
||||
} else if (opts.observable) {
|
||||
return new Observable<any>(() => {});
|
||||
}
|
||||
|
||||
return getPromise(() => {});
|
||||
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes function only if plugin is available
|
||||
* @private
|
||||
*/
|
||||
export function CordovaCheck(opts: CordovaCheckOptions = {}) {
|
||||
return (pluginObj: Object, methodName: string, descriptor: TypedPropertyDescriptor<any>): TypedPropertyDescriptor<any> => {
|
||||
return {
|
||||
value: function(...args: any[]): any {
|
||||
if (checkAvailability(pluginObj) === true) {
|
||||
return descriptor.value.apply(this, args);
|
||||
} else {
|
||||
if (opts.sync) {
|
||||
return;
|
||||
} else if (opts.observable) {
|
||||
return new Observable<any>(() => {});
|
||||
}
|
||||
return getPromise(() => {});
|
||||
}
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Class decorator specifying Plugin metadata. Required for all plugins.
|
||||
*
|
||||
* @usage
|
||||
* ```typescript
|
||||
* @Plugin({
|
||||
* pluginName: 'MyPlugin',
|
||||
* plugin: 'cordova-plugin-myplugin',
|
||||
* pluginRef: 'window.myplugin'
|
||||
* })
|
||||
* export class MyPlugin {
|
||||
*
|
||||
* // Plugin wrappers, properties, and functions go here ...
|
||||
*
|
||||
* }
|
||||
* ```
|
||||
*/
|
||||
export function Plugin(config: PluginConfig) {
|
||||
return function(cls) {
|
||||
|
||||
// Add these fields to the class
|
||||
for (let k in config) {
|
||||
cls[k] = config[k];
|
||||
}
|
||||
|
||||
cls['installed'] = function(printWarning?: boolean) {
|
||||
return !!getPlugin(config.pluginRef);
|
||||
};
|
||||
|
||||
cls['getPlugin'] = function() {
|
||||
return getPlugin(config.pluginRef);
|
||||
};
|
||||
|
||||
cls['checkInstall'] = function() {
|
||||
return checkAvailability(cls) === true;
|
||||
};
|
||||
|
||||
cls['getPluginName'] = function() {
|
||||
return config.pluginName;
|
||||
};
|
||||
cls['getPluginRef'] = function() {
|
||||
return config.pluginRef;
|
||||
};
|
||||
cls['getPluginInstallName'] = function() {
|
||||
return config.plugin;
|
||||
};
|
||||
cls['getPluginRepo'] = function() {
|
||||
return config.repo;
|
||||
};
|
||||
cls['getSupportedPlatforms'] = function() {
|
||||
return config.platforms;
|
||||
};
|
||||
|
||||
return cls;
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Wrap a stub function in a call to a Cordova plugin, checking if both Cordova
|
||||
* and the required plugin are installed.
|
||||
*/
|
||||
export function Cordova(opts: CordovaOptions = {}) {
|
||||
return (target: Object, methodName: string, descriptor: TypedPropertyDescriptor<any>) => {
|
||||
return {
|
||||
value: function(...args: any[]) {
|
||||
return wrap(this, methodName, opts).apply(this, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Wrap an instance method
|
||||
*/
|
||||
export function CordovaInstance(opts: any = {}) {
|
||||
return (target: Object, methodName: string) => {
|
||||
return {
|
||||
value: function(...args: any[]) {
|
||||
return wrapInstance(this, methodName, opts).apply(this, args);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
*
|
||||
* Before calling the original method, ensure Cordova and the plugin are installed.
|
||||
*/
|
||||
export function CordovaProperty(target: any, key: string) {
|
||||
Object.defineProperty(target, key, {
|
||||
get: () => {
|
||||
if (checkAvailability(target, key) === true) {
|
||||
return getPlugin(target.constructor.getPluginRef())[key];
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
},
|
||||
set: (value) => {
|
||||
if (checkAvailability(target, key) === true) {
|
||||
getPlugin(target.constructor.getPluginRef())[key] = value;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param target
|
||||
* @param key
|
||||
* @constructor
|
||||
*/
|
||||
export function InstanceProperty(target: any, key: string) {
|
||||
Object.defineProperty(target, key, {
|
||||
get: function(){
|
||||
return this._objectInstance[key];
|
||||
},
|
||||
set: function(value){
|
||||
this._objectInstance[key] = value;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Wrap a stub function in a call to a Cordova plugin, checking if both Cordova
|
||||
* and the required plugin are installed.
|
||||
*/
|
||||
export function CordovaFunctionOverride(opts: any = {}) {
|
||||
return (target: Object, methodName: string, descriptor: TypedPropertyDescriptor<any>) => {
|
||||
return {
|
||||
value: function(...args: any[]) {
|
||||
return overrideFunction(this, methodName, opts);
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*
|
||||
* Wraps method that returns an observable that can be completed. Provided opts.resultFinalPredicate dictates when the observable completes.
|
||||
*
|
||||
*/
|
||||
export function CordovaFiniteObservable(opts: CordovaFiniteObservableOptions = {}) {
|
||||
if (opts.observable === false) {
|
||||
throw new Error('CordovaFiniteObservable decorator can only be used on methods that returns observable. Please provide correct option.');
|
||||
}
|
||||
opts.observable = true;
|
||||
return (target: Object, methodName: string, descriptor: TypedPropertyDescriptor<any>) => {
|
||||
return {
|
||||
value: function(...args: any[]) {
|
||||
let wrappedObservable: Observable<any> = wrap(this, methodName, opts).apply(this, args);
|
||||
return new Observable<any>((observer) => {
|
||||
let wrappedSubscription = wrappedObservable.subscribe({
|
||||
next: (x) => {
|
||||
observer.next(opts.resultTransform ? opts.resultTransform(x) : x);
|
||||
if (opts.resultFinalPredicate && opts.resultFinalPredicate(x)) {
|
||||
observer.complete();
|
||||
}
|
||||
},
|
||||
error: (err) => { observer.error(err); },
|
||||
complete: () => { observer.complete(); }
|
||||
});
|
||||
return () => {
|
||||
wrappedSubscription.unsubscribe();
|
||||
};
|
||||
});
|
||||
}
|
||||
};
|
||||
};
|
||||
}
|
||||
@@ -1,100 +0,0 @@
|
||||
import { callCordovaPlugin, wrapPromise } from './common';
|
||||
|
||||
declare const window: any;
|
||||
|
||||
class MockPlugin {
|
||||
static getPluginRef(): string {
|
||||
return 'mockPlugin';
|
||||
}
|
||||
|
||||
static getPluginName(): string {
|
||||
return 'MockPlugin';
|
||||
}
|
||||
|
||||
static getPluginInstallName(): string {
|
||||
return '';
|
||||
}
|
||||
|
||||
create(): MockInstancePluginObject {
|
||||
return new MockInstancePluginObject();
|
||||
}
|
||||
}
|
||||
|
||||
class MockInstancePluginObject {
|
||||
_pluginInstance: MockCordovaPlugin;
|
||||
|
||||
constructor() {
|
||||
this._pluginInstance = new MockCordovaPlugin();
|
||||
}
|
||||
}
|
||||
|
||||
class MockCordovaPlugin {
|
||||
static ping = jest.fn((arg: string) => 'pong');
|
||||
static pingAsync = jest.fn((arg: string, success: Function, error: Function) => success('pong'));
|
||||
ping = jest.fn((arg: string) => 'pong');
|
||||
pingAsync = jest.fn((arg: string, success: Function, error: Function) => success('pong'));
|
||||
}
|
||||
|
||||
describe('Common decorator functions', () => {
|
||||
let plugin: MockPlugin, instancePluginObject: MockInstancePluginObject;
|
||||
|
||||
beforeAll(() => {
|
||||
window.mockPlugin = MockCordovaPlugin;
|
||||
plugin = new MockPlugin();
|
||||
instancePluginObject = plugin.create();
|
||||
});
|
||||
|
||||
describe('callCordovaPlugin', () => {
|
||||
test('should return value from cordova plugin', () => {
|
||||
expect(callCordovaPlugin(plugin, 'ping', ['pingpong'])).toBe('pong');
|
||||
});
|
||||
|
||||
test('original method should have been called', () => {
|
||||
expect(MockCordovaPlugin.ping.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
test('original method should have received args', () => {
|
||||
expect(MockCordovaPlugin.ping.mock.calls[0][0]).toBe('pingpong');
|
||||
});
|
||||
});
|
||||
|
||||
describe('wrapPromise', () => {
|
||||
test('should return a promise that resolves with a value', async () => {
|
||||
expect(await wrapPromise(plugin, 'pingAsync', ['pingpong'])).toBe('pong');
|
||||
});
|
||||
|
||||
test('original method should have been called', () => {
|
||||
expect(MockCordovaPlugin.pingAsync.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
test('original method should have received args', () => {
|
||||
expect(MockCordovaPlugin.pingAsync.mock.calls[0][0]).toBe('pingpong');
|
||||
expect(typeof MockCordovaPlugin.pingAsync.mock.calls[0][1]).toBe('function');
|
||||
expect(typeof MockCordovaPlugin.pingAsync.mock.calls[0][2]).toBe('function');
|
||||
});
|
||||
});
|
||||
|
||||
describe('wrapObservable', () => {
|
||||
test('should return an observable that emits a value', async () => {});
|
||||
|
||||
test('original method should have been called', () => {});
|
||||
|
||||
test('original method should have received args', () => {});
|
||||
});
|
||||
|
||||
describe('wrapEventObservable', () => {
|
||||
test('should return an observable that wraps an event listener', async () => {});
|
||||
});
|
||||
|
||||
describe('callInstance', () => {
|
||||
test('should call an instance method', async () => {});
|
||||
|
||||
test('original method should have been called', () => {
|
||||
// expect(instancePluginObject._pluginInstance.ping.mock.calls.length).toBe(1);
|
||||
});
|
||||
|
||||
test('original method should have received args', () => {
|
||||
// expect(instancePluginObject._pluginInstance.ping.mock.calls[0][0]).toBe('pingpong');
|
||||
});
|
||||
});
|
||||
});
|
||||
@@ -1,502 +0,0 @@
|
||||
import { fromEvent, Observable } from 'rxjs';
|
||||
|
||||
import { CordovaOptions } from './interfaces';
|
||||
|
||||
declare const window: any;
|
||||
|
||||
export const ERR_CORDOVA_NOT_AVAILABLE = { error: 'cordova_not_available' };
|
||||
export const ERR_PLUGIN_NOT_INSTALLED = { error: 'plugin_not_installed' };
|
||||
|
||||
export function getPromise<T>(callback: (resolve: Function, reject?: Function) => any): Promise<T> {
|
||||
const tryNativePromise = () => {
|
||||
if (Promise) {
|
||||
return new Promise<T>((resolve, reject) => {
|
||||
callback(resolve, reject);
|
||||
});
|
||||
} else {
|
||||
console.error(
|
||||
'No Promise support or polyfill found. To enable Ionic Native support, please add the es6-promise polyfill before this script, or run with a library like Angular or on a recent browser.'
|
||||
);
|
||||
}
|
||||
};
|
||||
|
||||
if (typeof window !== 'undefined' && window.angular) {
|
||||
const doc = window.document;
|
||||
const injector = window.angular
|
||||
.element(doc.querySelector('[ng-app]') || doc.body)
|
||||
.injector();
|
||||
if (injector) {
|
||||
const $q = injector.get('$q');
|
||||
return $q((resolve: Function, reject: Function) => {
|
||||
callback(resolve, reject);
|
||||
});
|
||||
}
|
||||
console.warn(
|
||||
`Angular 1 was detected but $q couldn't be retrieved. This is usually when the app is not bootstrapped on the html or body tag. Falling back to native promises which won't trigger an automatic digest when promises resolve.`
|
||||
);
|
||||
}
|
||||
|
||||
return tryNativePromise();
|
||||
}
|
||||
|
||||
export function wrapPromise(
|
||||
pluginObj: any,
|
||||
methodName: string,
|
||||
args: any[],
|
||||
opts: CordovaOptions = {}
|
||||
) {
|
||||
let pluginResult: any, rej: Function;
|
||||
const p = getPromise((resolve: Function, reject: Function) => {
|
||||
if (opts.destruct) {
|
||||
pluginResult = callCordovaPlugin(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
(...args: any[]) => resolve(args),
|
||||
(...args: any[]) => reject(args)
|
||||
);
|
||||
} else {
|
||||
pluginResult = callCordovaPlugin(pluginObj, methodName, args, opts, resolve, reject);
|
||||
}
|
||||
rej = reject;
|
||||
});
|
||||
// Angular throws an error on unhandled rejection, but in this case we have already printed
|
||||
// a warning that Cordova is undefined or the plugin is uninstalled, so there is no reason
|
||||
// to error
|
||||
if (pluginResult && pluginResult.error) {
|
||||
p.catch(() => {});
|
||||
typeof rej === 'function' && rej(pluginResult.error);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
function wrapOtherPromise(pluginObj: any, methodName: string, args: any[], opts: any = {}) {
|
||||
return getPromise((resolve: Function, reject: Function) => {
|
||||
const pluginResult = callCordovaPlugin(pluginObj, methodName, args, opts);
|
||||
if (pluginResult) {
|
||||
if (pluginResult.error) {
|
||||
reject(pluginResult.error);
|
||||
} else if (pluginResult.then) {
|
||||
pluginResult.then(resolve).catch(reject);
|
||||
}
|
||||
} else {
|
||||
reject({ error: 'unexpected_error' });
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function wrapObservable(pluginObj: any, methodName: string, args: any[], opts: any = {}) {
|
||||
return new Observable(observer => {
|
||||
let pluginResult;
|
||||
|
||||
if (opts.destruct) {
|
||||
pluginResult = callCordovaPlugin(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
(...args: any[]) => observer.next(args),
|
||||
(...args: any[]) => observer.error(args)
|
||||
);
|
||||
} else {
|
||||
pluginResult = callCordovaPlugin(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
observer.next.bind(observer),
|
||||
observer.error.bind(observer)
|
||||
);
|
||||
}
|
||||
|
||||
if (pluginResult && pluginResult.error) {
|
||||
observer.error(pluginResult.error);
|
||||
observer.complete();
|
||||
}
|
||||
return () => {
|
||||
try {
|
||||
if (opts.clearFunction) {
|
||||
if (opts.clearWithArgs) {
|
||||
return callCordovaPlugin(
|
||||
pluginObj,
|
||||
opts.clearFunction,
|
||||
args,
|
||||
opts,
|
||||
observer.next.bind(observer),
|
||||
observer.error.bind(observer)
|
||||
);
|
||||
}
|
||||
return callCordovaPlugin(pluginObj, opts.clearFunction, []);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
'Unable to clear the previous observable watch for',
|
||||
pluginObj.constructor.getPluginName(),
|
||||
methodName
|
||||
);
|
||||
console.warn(e);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the event with an observable
|
||||
* @private
|
||||
* @param event event name
|
||||
* @param element The element to attach the event listener to
|
||||
* @returns {Observable}
|
||||
*/
|
||||
function wrapEventObservable(event: string, element: any): Observable<any> {
|
||||
element = (typeof window !== 'undefined' && element) ? get(window, element) : element || typeof window !== 'undefined' || {};
|
||||
return fromEvent(element, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if plugin/cordova is available
|
||||
* @return {boolean | { error: string } }
|
||||
* @private
|
||||
*/
|
||||
export function checkAvailability(
|
||||
pluginRef: string,
|
||||
methodName?: string,
|
||||
pluginName?: string
|
||||
): boolean | { error: string };
|
||||
export function checkAvailability(
|
||||
pluginObj: any,
|
||||
methodName?: string,
|
||||
pluginName?: string
|
||||
): boolean | { error: string };
|
||||
export function checkAvailability(
|
||||
plugin: any,
|
||||
methodName?: string,
|
||||
pluginName?: string
|
||||
): boolean | { error: string } {
|
||||
let pluginRef, pluginInstance, pluginPackage;
|
||||
|
||||
if (typeof plugin === 'string') {
|
||||
pluginRef = plugin;
|
||||
} else {
|
||||
pluginRef = plugin.constructor.getPluginRef();
|
||||
pluginName = plugin.constructor.getPluginName();
|
||||
pluginPackage = plugin.constructor.getPluginInstallName();
|
||||
}
|
||||
|
||||
pluginInstance = getPlugin(pluginRef);
|
||||
|
||||
if (!pluginInstance || (!!methodName && typeof pluginInstance[methodName] === 'undefined')) {
|
||||
if (typeof window === 'undefined' || !window.cordova) {
|
||||
cordovaWarn(pluginName, methodName);
|
||||
return ERR_CORDOVA_NOT_AVAILABLE;
|
||||
}
|
||||
|
||||
pluginWarn(pluginName, pluginPackage, methodName);
|
||||
return ERR_PLUGIN_NOT_INSTALLED;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if _objectInstance exists and has the method/property
|
||||
* @private
|
||||
*/
|
||||
export function instanceAvailability(pluginObj: any, methodName?: string): boolean {
|
||||
return (
|
||||
pluginObj._objectInstance &&
|
||||
(!methodName || typeof pluginObj._objectInstance[methodName] !== 'undefined')
|
||||
);
|
||||
}
|
||||
|
||||
export function setIndex(args: any[], opts: any = {}, resolve?: Function, reject?: Function): any {
|
||||
// ignore resolve and reject in case sync
|
||||
if (opts.sync) {
|
||||
return args;
|
||||
}
|
||||
|
||||
// If the plugin method expects myMethod(success, err, options)
|
||||
if (opts.callbackOrder === 'reverse') {
|
||||
// Get those arguments in the order [resolve, reject, ...restOfArgs]
|
||||
args.unshift(reject);
|
||||
args.unshift(resolve);
|
||||
} else if (opts.callbackStyle === 'node') {
|
||||
args.push((err: any, result: any) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else if (opts.callbackStyle === 'object' && opts.successName && opts.errorName) {
|
||||
const obj: any = {};
|
||||
obj[opts.successName] = resolve;
|
||||
obj[opts.errorName] = reject;
|
||||
args.push(obj);
|
||||
} else if (typeof opts.successIndex !== 'undefined' || typeof opts.errorIndex !== 'undefined') {
|
||||
const setSuccessIndex = () => {
|
||||
// If we've specified a success/error index
|
||||
if (opts.successIndex > args.length) {
|
||||
args[opts.successIndex] = resolve;
|
||||
} else {
|
||||
args.splice(opts.successIndex, 0, resolve);
|
||||
}
|
||||
};
|
||||
|
||||
const setErrorIndex = () => {
|
||||
// We don't want that the reject cb gets spliced into the position of an optional argument that has not been
|
||||
// defined and thus causing non expected behavior.
|
||||
if (opts.errorIndex > args.length) {
|
||||
args[opts.errorIndex] = reject; // insert the reject fn at the correct specific index
|
||||
} else {
|
||||
args.splice(opts.errorIndex, 0, reject); // otherwise just splice it into the array
|
||||
}
|
||||
};
|
||||
|
||||
if (opts.successIndex > opts.errorIndex) {
|
||||
setErrorIndex();
|
||||
setSuccessIndex();
|
||||
} else {
|
||||
setSuccessIndex();
|
||||
setErrorIndex();
|
||||
}
|
||||
} else {
|
||||
// Otherwise, let's tack them on to the end of the argument list
|
||||
// which is 90% of cases
|
||||
args.push(resolve);
|
||||
args.push(reject);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
export function callCordovaPlugin(
|
||||
pluginObj: any,
|
||||
methodName: string,
|
||||
args: any[],
|
||||
opts: any = {},
|
||||
resolve?: Function,
|
||||
reject?: Function
|
||||
) {
|
||||
// Try to figure out where the success/error callbacks need to be bound
|
||||
// to our promise resolve/reject handlers.
|
||||
args = setIndex(args, opts, resolve, reject);
|
||||
|
||||
const availabilityCheck = checkAvailability(pluginObj, methodName);
|
||||
|
||||
if (availabilityCheck === true) {
|
||||
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
|
||||
return pluginInstance[methodName].apply(pluginInstance, args);
|
||||
} else {
|
||||
return availabilityCheck;
|
||||
}
|
||||
}
|
||||
|
||||
export function callInstance(
|
||||
pluginObj: any,
|
||||
methodName: string,
|
||||
args: any[],
|
||||
opts: any = {},
|
||||
resolve?: Function,
|
||||
reject?: Function
|
||||
) {
|
||||
args = setIndex(args, opts, resolve, reject);
|
||||
|
||||
if (instanceAvailability(pluginObj, methodName)) {
|
||||
return pluginObj._objectInstance[methodName].apply(pluginObj._objectInstance, args);
|
||||
}
|
||||
}
|
||||
|
||||
export function getPlugin(pluginRef: string): any {
|
||||
if (typeof window !== 'undefined') {
|
||||
return get(window, pluginRef);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function get(element: Element | Window, path: string) {
|
||||
const paths: string[] = path.split('.');
|
||||
let obj: any = element;
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
if (!obj) {
|
||||
return null;
|
||||
}
|
||||
obj = obj[paths[i]];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
export function pluginWarn(pluginName: string, plugin?: string, method?: string): void {
|
||||
if (method) {
|
||||
console.warn(
|
||||
'Native: tried calling ' +
|
||||
pluginName +
|
||||
'.' +
|
||||
method +
|
||||
', but the ' +
|
||||
pluginName +
|
||||
' plugin is not installed.'
|
||||
);
|
||||
} else {
|
||||
console.warn(`Native: tried accessing the ${pluginName} plugin but it's not installed.`);
|
||||
}
|
||||
if (plugin) {
|
||||
console.warn(`Install the ${pluginName} plugin: 'ionic cordova plugin add ${plugin}'`);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param pluginName
|
||||
* @param method
|
||||
*/
|
||||
export function cordovaWarn(pluginName: string, method?: string): void {
|
||||
if (typeof process === 'undefined') {
|
||||
if (method) {
|
||||
console.warn(
|
||||
'Native: tried calling ' +
|
||||
pluginName +
|
||||
'.' +
|
||||
method +
|
||||
', but Cordova is not available. Make sure to include cordova.js or run in a device/simulator'
|
||||
);
|
||||
} else {
|
||||
console.warn(
|
||||
'Native: tried accessing the ' +
|
||||
pluginName +
|
||||
' plugin but Cordova is not available. Make sure to include cordova.js or run in a device/simulator'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Fixes a bug in TypeScript 2.9.2 where the ...args is being converted into args: {} and
|
||||
// causing compilation issues
|
||||
export type WrapFn = (...args: any[]) => any;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export const wrap = (pluginObj: any, methodName: string, opts: CordovaOptions = {}): WrapFn => {
|
||||
return (...args: any[]) => {
|
||||
if (opts.sync) {
|
||||
// Sync doesn't wrap the plugin with a promise or observable, it returns the result as-is
|
||||
return callCordovaPlugin(pluginObj, methodName, args, opts);
|
||||
} else if (opts.observable) {
|
||||
return wrapObservable(pluginObj, methodName, args, opts);
|
||||
} else if (opts.eventObservable && opts.event) {
|
||||
return wrapEventObservable(opts.event, opts.element);
|
||||
} else if (opts.otherPromise) {
|
||||
return wrapOtherPromise(pluginObj, methodName, args, opts);
|
||||
} else {
|
||||
return wrapPromise(pluginObj, methodName, args, opts);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function wrapInstance(pluginObj: any, methodName: string, opts: any = {}): Function {
|
||||
return (...args: any[]) => {
|
||||
if (opts.sync) {
|
||||
return callInstance(pluginObj, methodName, args, opts);
|
||||
} else if (opts.observable) {
|
||||
return new Observable(observer => {
|
||||
let pluginResult;
|
||||
|
||||
if (opts.destruct) {
|
||||
pluginResult = callInstance(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
(...args: any[]) => observer.next(args),
|
||||
(...args: any[]) => observer.error(args)
|
||||
);
|
||||
} else {
|
||||
pluginResult = callInstance(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
observer.next.bind(observer),
|
||||
observer.error.bind(observer)
|
||||
);
|
||||
}
|
||||
|
||||
if (pluginResult && pluginResult.error) {
|
||||
observer.error(pluginResult.error);
|
||||
}
|
||||
|
||||
return () => {
|
||||
try {
|
||||
if (opts.clearWithArgs) {
|
||||
return callInstance(
|
||||
pluginObj,
|
||||
opts.clearFunction,
|
||||
args,
|
||||
opts,
|
||||
observer.next.bind(observer),
|
||||
observer.error.bind(observer)
|
||||
);
|
||||
}
|
||||
return callInstance(pluginObj, opts.clearFunction, []);
|
||||
} catch (e) {
|
||||
console.warn(
|
||||
'Unable to clear the previous observable watch for',
|
||||
pluginObj.constructor.getPluginName(),
|
||||
methodName
|
||||
);
|
||||
console.warn(e);
|
||||
}
|
||||
};
|
||||
});
|
||||
} else if (opts.otherPromise) {
|
||||
return getPromise((resolve: Function, reject: Function) => {
|
||||
let result;
|
||||
if (opts.destruct) {
|
||||
result = callInstance(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
(...args: any[]) => resolve(args),
|
||||
(...args: any[]) => reject(args)
|
||||
);
|
||||
} else {
|
||||
result = callInstance(pluginObj, methodName, args, opts, resolve, reject);
|
||||
}
|
||||
if (result && result.then) {
|
||||
result.then(resolve, reject);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
let pluginResult: any, rej: Function;
|
||||
const p = getPromise((resolve: Function, reject: Function) => {
|
||||
if (opts.destruct) {
|
||||
pluginResult = callInstance(
|
||||
pluginObj,
|
||||
methodName,
|
||||
args,
|
||||
opts,
|
||||
(...args: any[]) => resolve(args),
|
||||
(...args: any[]) => reject(args)
|
||||
);
|
||||
} else {
|
||||
pluginResult = callInstance(pluginObj, methodName, args, opts, resolve, reject);
|
||||
}
|
||||
rej = reject;
|
||||
});
|
||||
// Angular throws an error on unhandled rejection, but in this case we have already printed
|
||||
// a warning that Cordova is undefined or the plugin is uninstalled, so there is no reason
|
||||
// to error
|
||||
if (pluginResult && pluginResult.error) {
|
||||
p.catch(() => {});
|
||||
typeof rej === 'function' && rej(pluginResult.error);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
import { Observable, Observer } from 'rxjs';
|
||||
|
||||
import { checkAvailability, getPlugin } from './common';
|
||||
|
||||
function overrideFunction(pluginObj: any, methodName: string): Observable<any> {
|
||||
return new Observable((observer: Observer<any>) => {
|
||||
const availabilityCheck = checkAvailability(pluginObj, methodName);
|
||||
|
||||
if (availabilityCheck === true) {
|
||||
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
|
||||
pluginInstance[methodName] = observer.next.bind(observer);
|
||||
return () => (pluginInstance[methodName] = () => {});
|
||||
} else {
|
||||
observer.error(availabilityCheck);
|
||||
observer.complete();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
export function cordovaFunctionOverride(
|
||||
pluginObj: any,
|
||||
methodName: string,
|
||||
args: IArguments | any[] = []
|
||||
) {
|
||||
return overrideFunction(pluginObj, methodName);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
import { wrapInstance } from './common';
|
||||
import { CordovaOptions } from './interfaces';
|
||||
|
||||
export function cordovaInstance(
|
||||
pluginObj: any,
|
||||
methodName: string,
|
||||
config: CordovaOptions,
|
||||
args: IArguments | any[]
|
||||
) {
|
||||
args = Array.from(args);
|
||||
return wrapInstance(pluginObj, methodName, config).apply(this, args);
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
import { checkAvailability, getPlugin } from './common';
|
||||
|
||||
export function cordovaPropertyGet(pluginObj: any, key: string) {
|
||||
if (checkAvailability(pluginObj, key) === true) {
|
||||
return getPlugin(pluginObj.constructor.getPluginRef())[key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function cordovaPropertySet(pluginObj: any, key: string, value: any) {
|
||||
if (checkAvailability(pluginObj, key) === true) {
|
||||
getPlugin(pluginObj.constructor.getPluginRef())[key] = value;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +0,0 @@
|
||||
import { wrap } from './common';
|
||||
import { CordovaOptions } from './interfaces';
|
||||
|
||||
export function cordova(
|
||||
pluginObj: any,
|
||||
methodName: string,
|
||||
config: CordovaOptions,
|
||||
args: IArguments | any[]
|
||||
) {
|
||||
return wrap(pluginObj, methodName, config).apply(this, args);
|
||||
}
|
||||
@@ -1,12 +0,0 @@
|
||||
export function instancePropertyGet(pluginObj: any, key: string) {
|
||||
if (pluginObj._objectInstance && pluginObj._objectInstance[key]) {
|
||||
return pluginObj._objectInstance[key];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
export function instancePropertySet(pluginObj: any, key: string, value: any) {
|
||||
if (pluginObj._objectInstance) {
|
||||
pluginObj._objectInstance[key] = value;
|
||||
}
|
||||
}
|
||||
@@ -1,107 +0,0 @@
|
||||
export interface PluginConfig {
|
||||
/**
|
||||
* Plugin name, this should match the class name
|
||||
*/
|
||||
pluginName: string;
|
||||
/**
|
||||
* Plugin NPM package name
|
||||
*/
|
||||
plugin: string;
|
||||
/**
|
||||
* Plugin object reference
|
||||
*/
|
||||
pluginRef?: string;
|
||||
/**
|
||||
* Github repository URL
|
||||
*/
|
||||
repo?: string;
|
||||
/**
|
||||
* Custom install command
|
||||
*/
|
||||
install?: string;
|
||||
/**
|
||||
* Available installation variables
|
||||
*/
|
||||
installVariables?: string[];
|
||||
/**
|
||||
* Supported platforms
|
||||
*/
|
||||
platforms?: string[];
|
||||
|
||||
[key: string]: any;
|
||||
}
|
||||
|
||||
export interface CordovaOptions {
|
||||
destruct?: boolean;
|
||||
/**
|
||||
* Set to true if the wrapped method is a sync function
|
||||
*/
|
||||
sync?: boolean;
|
||||
/**
|
||||
* Callback order. Set to reverse if the success/error callbacks are the first 2 arguments that the wrapped method
|
||||
* takes.
|
||||
*/
|
||||
callbackOrder?: 'reverse';
|
||||
/**
|
||||
* Callback style
|
||||
*/
|
||||
callbackStyle?: 'node' | 'object';
|
||||
/**
|
||||
* Set a custom index for the success callback function. This doesn't work if callbackOrder or callbackStyle are set.
|
||||
*/
|
||||
successIndex?: number;
|
||||
/**
|
||||
* Set a custom index for the error callback function. This doesn't work if callbackOrder or callbackStyle are set.
|
||||
*/
|
||||
errorIndex?: number;
|
||||
/**
|
||||
* Success function property name. This must be set if callbackStyle is set to object.
|
||||
*/
|
||||
successName?: string;
|
||||
/**
|
||||
* Error function property name. This must be set if callbackStyle is set to object.
|
||||
*/
|
||||
errorName?: string;
|
||||
/**
|
||||
* Set to true to return an observable
|
||||
*/
|
||||
observable?: boolean;
|
||||
/**
|
||||
* If observable is set to true, this can be set to a different function name that will cancel the observable.
|
||||
*/
|
||||
clearFunction?: string;
|
||||
/**
|
||||
* This can be used if clearFunction is set. Set this to true to call the clearFunction with the same arguments used
|
||||
* in the initial function.
|
||||
*/
|
||||
clearWithArgs?: boolean;
|
||||
/**
|
||||
* Creates an observable that wraps a global event. Replaces document.addEventListener
|
||||
*/
|
||||
eventObservable?: boolean;
|
||||
/**
|
||||
* Event name, this must be set if eventObservable is set to true
|
||||
*/
|
||||
event?: string;
|
||||
/**
|
||||
* Element to attach the event listener to, this is optional, defaults to `window`
|
||||
*/
|
||||
element?: any;
|
||||
/**
|
||||
* Set to true if the wrapped method returns a promise
|
||||
*/
|
||||
otherPromise?: boolean;
|
||||
/**
|
||||
* Supported platforms
|
||||
*/
|
||||
platforms?: string[];
|
||||
}
|
||||
|
||||
export declare const Plugin: (config: PluginConfig) => ClassDecorator;
|
||||
export declare const Cordova: (config?: CordovaOptions) => MethodDecorator;
|
||||
export declare const CordovaProperty: () => PropertyDecorator;
|
||||
export declare const CordovaInstance: (config?: CordovaOptions) => MethodDecorator;
|
||||
export declare const InstanceProperty: () => PropertyDecorator;
|
||||
export declare const CordovaCheck: (config?: CordovaOptions) => MethodDecorator;
|
||||
export declare const InstanceCheck: (config?: CordovaOptions) => MethodDecorator;
|
||||
export declare const CordovaFunctionOverride: () => MethodDecorator;
|
||||
@@ -1,14 +1,3 @@
|
||||
import { checkReady } from './bootstrap';
|
||||
|
||||
export { IonicNativePlugin } from './ionic-native-plugin';
|
||||
|
||||
// Decorators
|
||||
export { checkAvailability, instanceAvailability, wrap, getPromise } from './decorators/common';
|
||||
export * from './decorators/cordova';
|
||||
export * from './decorators/cordova-function-override';
|
||||
export * from './decorators/cordova-instance';
|
||||
export * from './decorators/cordova-property';
|
||||
export * from './decorators/instance-property';
|
||||
export * from './decorators/interfaces';
|
||||
|
||||
checkReady();
|
||||
export * from './plugin';
|
||||
export * from './decorators';
|
||||
export * from './util';
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
import { checkAvailability } from './decorators/common';
|
||||
import { get } from './util';
|
||||
|
||||
export class IonicNativePlugin {
|
||||
static pluginName: string;
|
||||
|
||||
static pluginRef: string;
|
||||
|
||||
static plugin: string;
|
||||
|
||||
static repo: string;
|
||||
|
||||
static platforms: string[];
|
||||
|
||||
static install: string;
|
||||
|
||||
/**
|
||||
* Returns a boolean that indicates whether the plugin is installed
|
||||
* @return {boolean}
|
||||
*/
|
||||
static installed(): boolean {
|
||||
return checkAvailability(this.pluginRef) === true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the original plugin object
|
||||
*/
|
||||
static getPlugin(): any {
|
||||
if (typeof window !== 'undefined') {
|
||||
return get(window, this.pluginRef);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin's name
|
||||
*/
|
||||
static getPluginName(): string {
|
||||
return this.pluginName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin's reference
|
||||
*/
|
||||
static getPluginRef(): string {
|
||||
return this.pluginRef;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin's install name
|
||||
*/
|
||||
static getPluginInstallName(): string {
|
||||
return this.plugin;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the plugin's supported platforms
|
||||
*/
|
||||
static getSupportedPlatforms(): string[] {
|
||||
return this.platforms || [];
|
||||
}
|
||||
}
|
||||
@@ -1,27 +0,0 @@
|
||||
declare const window: any;
|
||||
|
||||
/**
|
||||
* Initialize the ionic.native Angular module if we're running in ng1.
|
||||
* This iterates through the list of registered plugins and dynamically
|
||||
* creates Angular 1 services of the form $cordovaSERVICE, ex: $cordovaStatusBar.
|
||||
*/
|
||||
export function initAngular1(plugins: any) {
|
||||
if (typeof window !== 'undefined' && window.angular) {
|
||||
const ngModule = window.angular.module('ionic.native', []);
|
||||
|
||||
for (const name in plugins) {
|
||||
const serviceName = '$cordova' + name;
|
||||
const cls = plugins[name];
|
||||
|
||||
((serviceName, cls, name) => {
|
||||
ngModule.service(serviceName, [
|
||||
() => {
|
||||
const funcs = window.angular.copy(cls);
|
||||
funcs.__proto__['name'] = name;
|
||||
return funcs;
|
||||
}
|
||||
]);
|
||||
})(serviceName, cls, name);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,309 @@
|
||||
import { get, getPlugin, getPromise, cordovaWarn, pluginWarn } from './util';
|
||||
import { checkReady } from './bootstrap';
|
||||
import { CordovaOptions } from './decorators';
|
||||
|
||||
import { Observable } from 'rxjs/Observable';
|
||||
import 'rxjs/add/observable/fromEvent';
|
||||
|
||||
checkReady();
|
||||
|
||||
declare var window;
|
||||
declare var Promise;
|
||||
|
||||
|
||||
/**
|
||||
* Checks if plugin/cordova is available
|
||||
* @return {boolean | { error: string } }
|
||||
* @private
|
||||
*/
|
||||
export function checkAvailability(pluginRef: string, methodName?: string, pluginName?: string);
|
||||
export function checkAvailability(pluginObj: any, methodName?: string, pluginName?: string);
|
||||
export function checkAvailability(plugin: any, methodName?: string, pluginName?: string): boolean | { error: string } {
|
||||
|
||||
let pluginRef, pluginInstance, pluginPackage;
|
||||
|
||||
if (typeof plugin === 'string') {
|
||||
pluginRef = plugin;
|
||||
} else {
|
||||
pluginRef = plugin.constructor.getPluginRef();
|
||||
pluginName = plugin.constructor.getPluginName();
|
||||
pluginPackage = plugin.constructor.getPluginInstallName();
|
||||
}
|
||||
|
||||
pluginInstance = getPlugin(pluginRef);
|
||||
|
||||
if (!pluginInstance || (!!methodName && pluginInstance[methodName] === 'undefined')) {
|
||||
if (!window.cordova) {
|
||||
cordovaWarn(pluginName, methodName);
|
||||
return {
|
||||
error: 'cordova_not_available'
|
||||
};
|
||||
}
|
||||
|
||||
pluginWarn(pluginName, pluginPackage, methodName);
|
||||
return {
|
||||
error: 'plugin_not_installed'
|
||||
};
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if _objectInstance exists and has the method/property
|
||||
* @private
|
||||
*/
|
||||
export function instanceAvailability(pluginObj: any, methodName?: string): boolean {
|
||||
return pluginObj._objectInstance && (!methodName || pluginObj._objectInstance[methodName] !== 'undefined');
|
||||
}
|
||||
|
||||
function setIndex(args: any[], opts: any = {}, resolve?: Function, reject?: Function): any {
|
||||
// ignore resolve and reject in case sync
|
||||
if (opts.sync) {
|
||||
return args;
|
||||
}
|
||||
|
||||
// If the plugin method expects myMethod(success, err, options)
|
||||
if (opts.callbackOrder === 'reverse') {
|
||||
// Get those arguments in the order [resolve, reject, ...restOfArgs]
|
||||
args.unshift(reject);
|
||||
args.unshift(resolve);
|
||||
} else if (opts.callbackStyle === 'node') {
|
||||
args.push((err, result) => {
|
||||
if (err) {
|
||||
reject(err);
|
||||
} else {
|
||||
resolve(result);
|
||||
}
|
||||
});
|
||||
} else if (opts.callbackStyle === 'object' && opts.successName && opts.errorName) {
|
||||
let obj: any = {};
|
||||
obj[opts.successName] = resolve;
|
||||
obj[opts.errorName] = reject;
|
||||
args.push(obj);
|
||||
} else if (typeof opts.successIndex !== 'undefined' || typeof opts.errorIndex !== 'undefined') {
|
||||
const setSuccessIndex = () => {
|
||||
// If we've specified a success/error index
|
||||
if (opts.successIndex > args.length) {
|
||||
args[opts.successIndex] = resolve;
|
||||
} else {
|
||||
args.splice(opts.successIndex, 0, resolve);
|
||||
}
|
||||
};
|
||||
|
||||
const setErrorIndex = () => {
|
||||
// We don't want that the reject cb gets spliced into the position of an optional argument that has not been defined and thus causing non expected behaviour.
|
||||
if (opts.errorIndex > args.length) {
|
||||
args[opts.errorIndex] = reject; // insert the reject fn at the correct specific index
|
||||
} else {
|
||||
args.splice(opts.errorIndex, 0, reject); // otherwise just splice it into the array
|
||||
}
|
||||
};
|
||||
|
||||
if (opts.successIndex > opts.errorIndex) {
|
||||
setErrorIndex();
|
||||
setSuccessIndex();
|
||||
} else {
|
||||
setSuccessIndex();
|
||||
setErrorIndex();
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
// Otherwise, let's tack them on to the end of the argument list
|
||||
// which is 90% of cases
|
||||
args.push(resolve);
|
||||
args.push(reject);
|
||||
}
|
||||
return args;
|
||||
}
|
||||
|
||||
function callCordovaPlugin(pluginObj: any, methodName: string, args: any[], opts: any = {}, resolve?: Function, reject?: Function) {
|
||||
// Try to figure out where the success/error callbacks need to be bound
|
||||
// to our promise resolve/reject handlers.
|
||||
args = setIndex(args, opts, resolve, reject);
|
||||
|
||||
const availabilityCheck = checkAvailability(pluginObj, methodName);
|
||||
|
||||
if (availabilityCheck === true) {
|
||||
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
|
||||
return pluginInstance[methodName].apply(pluginInstance, args);
|
||||
} else {
|
||||
return availabilityCheck;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function wrapPromise(pluginObj: any, methodName: string, args: any[], opts: any = {}) {
|
||||
let pluginResult, rej;
|
||||
const p = getPromise((resolve, reject) => {
|
||||
pluginResult = callCordovaPlugin(pluginObj, methodName, args, opts, resolve, reject);
|
||||
rej = reject;
|
||||
});
|
||||
// Angular throws an error on unhandled rejection, but in this case we have already printed
|
||||
// a warning that Cordova is undefined or the plugin is uninstalled, so there is no reason
|
||||
// to error
|
||||
if (pluginResult && pluginResult.error) {
|
||||
p.catch(() => { });
|
||||
rej(pluginResult.error);
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
function wrapOtherPromise(pluginObj: any, methodName: string, args: any[], opts: any= {}) {
|
||||
return getPromise((resolve, reject) => {
|
||||
let pluginResult = callCordovaPlugin(pluginObj, methodName, args, opts);
|
||||
if (pluginResult && pluginResult.error) {
|
||||
reject(pluginResult.error);
|
||||
}
|
||||
pluginResult.then(resolve).catch(reject);
|
||||
});
|
||||
}
|
||||
|
||||
function wrapObservable(pluginObj: any, methodName: string, args: any[], opts: any = {}) {
|
||||
return new Observable(observer => {
|
||||
let pluginResult = callCordovaPlugin(pluginObj, methodName, args, opts, observer.next.bind(observer), observer.error.bind(observer));
|
||||
if (pluginResult && pluginResult.error) {
|
||||
observer.error(pluginResult.error);
|
||||
observer.complete();
|
||||
}
|
||||
return () => {
|
||||
try {
|
||||
if (opts.clearFunction) {
|
||||
if (opts.clearWithArgs) {
|
||||
return callCordovaPlugin(pluginObj, opts.clearFunction, args, opts, observer.next.bind(observer), observer.error.bind(observer));
|
||||
}
|
||||
return get(window, pluginObj.constructor.getPluginRef())[opts.clearFunction].call(pluginObj, pluginResult);
|
||||
}
|
||||
} catch (e) {
|
||||
console.warn('Unable to clear the previous observable watch for', pluginObj.constructor.getPluginName(), methodName);
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
});
|
||||
}
|
||||
|
||||
function callInstance(pluginObj: any, methodName: string, args: any[], opts: any = {}, resolve?: Function, reject?: Function) {
|
||||
|
||||
args = setIndex(args, opts, resolve, reject);
|
||||
|
||||
if (instanceAvailability(pluginObj, methodName)) {
|
||||
return pluginObj._objectInstance[methodName].apply(pluginObj._objectInstance, args);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap the event with an observable
|
||||
* @private
|
||||
* @param event even name
|
||||
* @param element The element to attach the event listener to
|
||||
* @returns {Observable}
|
||||
*/
|
||||
export function wrapEventObservable(event: string, element: any = window): Observable<any> {
|
||||
return Observable.fromEvent(element, event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Certain plugins expect the user to override methods in the plugin. For example,
|
||||
* window.cordova.plugins.backgroundMode.onactivate = function() { ... }.
|
||||
*
|
||||
* Unfortunately, this is brittle and would be better wrapped as an Observable. overrideFunction
|
||||
* does just this.
|
||||
* @private
|
||||
*/
|
||||
export function overrideFunction(pluginObj: any, methodName: string, args: any[], opts: any = {}): Observable<any> {
|
||||
return new Observable(observer => {
|
||||
|
||||
const availabilityCheck = checkAvailability(pluginObj, methodName);
|
||||
|
||||
if (availabilityCheck === true) {
|
||||
const pluginInstance = getPlugin(pluginObj.constructor.getPluginRef());
|
||||
pluginInstance[methodName] = observer.next.bind(observer);
|
||||
return () => pluginInstance[methodName] = () => {};
|
||||
} else {
|
||||
observer.error(availabilityCheck);
|
||||
observer.complete();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export const wrap = function(pluginObj: any, methodName: string, opts: CordovaOptions = {}) {
|
||||
return (...args) => {
|
||||
if (opts.sync) {
|
||||
// Sync doesn't wrap the plugin with a promise or observable, it returns the result as-is
|
||||
return callCordovaPlugin(pluginObj, methodName, args, opts);
|
||||
} else if (opts.observable) {
|
||||
return wrapObservable(pluginObj, methodName, args, opts);
|
||||
} else if (opts.eventObservable && opts.event) {
|
||||
return wrapEventObservable(opts.event, opts.element);
|
||||
} else if (opts.otherPromise) {
|
||||
return wrapOtherPromise(pluginObj, methodName, args, opts);
|
||||
} else {
|
||||
return wrapPromise(pluginObj, methodName, args, opts);
|
||||
}
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function wrapInstance(pluginObj: any, methodName: string, opts: any = {}) {
|
||||
return (...args) => {
|
||||
if (opts.sync) {
|
||||
|
||||
return callInstance(pluginObj, methodName, args, opts);
|
||||
|
||||
} else if (opts.observable) {
|
||||
|
||||
return new Observable(observer => {
|
||||
let pluginResult = callInstance(pluginObj, methodName, args, opts, observer.next.bind(observer), observer.error.bind(observer));
|
||||
|
||||
if (pluginResult && pluginResult.error) {
|
||||
observer.error(pluginResult.error);
|
||||
observer.complete();
|
||||
}
|
||||
|
||||
return () => {
|
||||
try {
|
||||
if (opts.clearWithArgs) {
|
||||
return pluginObj._objectInstance[opts.clearFunction].apply(pluginObj._objectInstance, args);
|
||||
}
|
||||
return pluginObj._objectInstance[opts.clearFunction].call(pluginObj, pluginResult);
|
||||
} catch (e) {
|
||||
console.warn('Unable to clear the previous observable watch for', pluginObj.constructor.getPluginName(), methodName);
|
||||
console.error(e);
|
||||
}
|
||||
};
|
||||
});
|
||||
|
||||
} else if (opts.otherPromise) {
|
||||
|
||||
return getPromise((resolve, reject) => {
|
||||
let result = callInstance(pluginObj, methodName, args, opts, resolve, reject);
|
||||
if (result && !result.error) {
|
||||
result.then(resolve, reject);
|
||||
}
|
||||
});
|
||||
|
||||
} else {
|
||||
|
||||
let pluginResult, rej;
|
||||
const p = getPromise((resolve, reject) => {
|
||||
pluginResult = callInstance(pluginObj, methodName, args, opts, resolve, reject);
|
||||
rej = reject;
|
||||
});
|
||||
if (pluginResult && pluginResult.error) {
|
||||
p.catch(() => { });
|
||||
rej(pluginResult.error);
|
||||
}
|
||||
return p;
|
||||
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,35 +1,68 @@
|
||||
declare const window: any;
|
||||
declare var window: any;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function get(element: Element | Window, path: string) {
|
||||
const paths: string[] = path.split('.');
|
||||
let obj: any = element;
|
||||
for (let i = 0; i < paths.length; i++) {
|
||||
if (!obj) {
|
||||
return null;
|
||||
}
|
||||
obj = obj[paths[i]];
|
||||
export function get(obj, path) {
|
||||
path = path.split('.');
|
||||
for (let i = 0; i < path.length; i++) {
|
||||
if (!obj) { return null; }
|
||||
obj = obj[path[i]];
|
||||
}
|
||||
return obj;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export function getPromise(callback: Function = () => {}): Promise<any> {
|
||||
export function getPromise(cb) {
|
||||
|
||||
const tryNativePromise = () => {
|
||||
if (typeof Promise === 'function' || (typeof window !== 'undefined' && window.Promise)) {
|
||||
return new Promise<any>((resolve, reject) => {
|
||||
callback(resolve, reject);
|
||||
if (window.Promise) {
|
||||
return new Promise((resolve, reject) => {
|
||||
cb(resolve, reject);
|
||||
});
|
||||
} else {
|
||||
console.error(
|
||||
'No Promise support or polyfill found. To enable Ionic Native support, please add the es6-promise polyfill before this script, or run with a library like Angular or on a recent browser.'
|
||||
);
|
||||
console.error('No Promise support or polyfill found. To enable Ionic Native support, please add the es6-promise polyfill before this script, or run with a library like Angular 2 or on a recent browser.');
|
||||
}
|
||||
};
|
||||
|
||||
return tryNativePromise();
|
||||
}
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param pluginRef
|
||||
* @returns {null|*}
|
||||
*/
|
||||
export function getPlugin(pluginRef: string): any {
|
||||
return get(window, pluginRef);
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
export const pluginWarn = function(pluginName: string, plugin?: string, method?: string) {
|
||||
if (method) {
|
||||
console.warn('Native: tried calling ' + pluginName + '.' + method + ', but the ' + pluginName + ' plugin is not installed.');
|
||||
} else {
|
||||
console.warn('Native: tried accessing the ' + pluginName + ' plugin but it\'s not installed.');
|
||||
}
|
||||
if (plugin) {
|
||||
console.warn('Install the ' + pluginName + ' plugin: \'ionic plugin add ' + plugin + '\'');
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @param pluginName
|
||||
* @param method
|
||||
*/
|
||||
export const cordovaWarn = function(pluginName: string, method?: string) {
|
||||
if (method) {
|
||||
console.warn('Native: tried calling ' + pluginName + '.' + method + ', but Cordova is not available. Make sure to include cordova.js or run in a device/simulator');
|
||||
} else {
|
||||
console.warn('Native: tried accessing the ' + pluginName + ' plugin but Cordova is not available. Make sure to include cordova.js or run in a device/simulator');
|
||||
}
|
||||
};
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user