commit
53a91a77c6
|
@ -12,5 +12,9 @@ module.exports = {
|
|||
copyConfig: {
|
||||
src: ['{{ROOT}}/src/config.json'],
|
||||
dest: '{{WWW}}/'
|
||||
}
|
||||
},
|
||||
copyMathJax: {
|
||||
src: ['{{ROOT}}/node_modules/mathjax/**/*'],
|
||||
dest: '{{WWW}}/lib/mathjax'
|
||||
},
|
||||
};
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
{
|
||||
"name": "moodlemobile",
|
||||
"version": "3.7.1",
|
||||
"version": "3.8.0",
|
||||
"lockfileVersion": 1,
|
||||
"requires": true,
|
||||
"dependencies": {
|
||||
|
@ -503,8 +503,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -525,14 +524,12 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -547,20 +544,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -677,8 +671,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -690,7 +683,6 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -705,7 +697,6 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -713,14 +704,12 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -739,7 +728,6 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -820,8 +808,7 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -833,7 +820,6 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -919,8 +905,7 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -956,7 +941,6 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -976,7 +960,6 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -1020,14 +1003,12 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -5243,8 +5224,7 @@
|
|||
},
|
||||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -5262,13 +5242,11 @@
|
|||
},
|
||||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -5281,18 +5259,15 @@
|
|||
},
|
||||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -5395,8 +5370,7 @@
|
|||
},
|
||||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -5406,7 +5380,6 @@
|
|||
"is-fullwidth-code-point": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -5419,20 +5392,17 @@
|
|||
"minimatch": {
|
||||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
},
|
||||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -5449,7 +5419,6 @@
|
|||
"mkdirp": {
|
||||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -5528,8 +5497,7 @@
|
|||
},
|
||||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -5539,7 +5507,6 @@
|
|||
"once": {
|
||||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -5615,8 +5582,7 @@
|
|||
},
|
||||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -5646,7 +5612,6 @@
|
|||
"string-width": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -5664,7 +5629,6 @@
|
|||
"strip-ansi": {
|
||||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -5703,13 +5667,11 @@
|
|||
},
|
||||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"optional": true
|
||||
"bundled": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -6136,8 +6098,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -6158,14 +6119,12 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -6180,20 +6139,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -6310,8 +6266,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -6323,7 +6278,6 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -6338,7 +6292,6 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -6346,14 +6299,12 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -6372,7 +6323,6 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -6453,8 +6403,7 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -6466,7 +6415,6 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -6552,8 +6500,7 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -6589,7 +6536,6 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -6609,7 +6555,6 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -6653,14 +6598,12 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -8863,6 +8806,11 @@
|
|||
"resolved": "https://registry.npmjs.org/math-random/-/math-random-1.0.4.tgz",
|
||||
"integrity": "sha512-rUxjysqif/BZQH2yhd5Aaq7vXMSx9NdEsQcyA07uEzIvxgI7zIr33gGsh+RU0/XjmQpCW7RsVof1vlkvQVCK5A=="
|
||||
},
|
||||
"mathjax": {
|
||||
"version": "2.7.2",
|
||||
"resolved": "https://registry.npmjs.org/mathjax/-/mathjax-2.7.2.tgz",
|
||||
"integrity": "sha512-Z9te7r3lsjZibugO1uKsdyqICKXVNr7M1Ll2GtjJu9cUKvOvwDqEp0YIjBD4H58NNuPg5DP5/AQ2Tu8K52Mqng=="
|
||||
},
|
||||
"md5-file": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/md5-file/-/md5-file-4.0.0.tgz",
|
||||
|
@ -12921,8 +12869,7 @@
|
|||
"ansi-regex": {
|
||||
"version": "2.1.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"aproba": {
|
||||
"version": "1.2.0",
|
||||
|
@ -12943,14 +12890,12 @@
|
|||
"balanced-match": {
|
||||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"brace-expansion": {
|
||||
"version": "1.1.11",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"balanced-match": "^1.0.0",
|
||||
"concat-map": "0.0.1"
|
||||
|
@ -12965,20 +12910,17 @@
|
|||
"code-point-at": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"concat-map": {
|
||||
"version": "0.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"console-control-strings": {
|
||||
"version": "1.1.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"core-util-is": {
|
||||
"version": "1.0.2",
|
||||
|
@ -13095,8 +13037,7 @@
|
|||
"inherits": {
|
||||
"version": "2.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"ini": {
|
||||
"version": "1.3.5",
|
||||
|
@ -13108,7 +13049,6 @@
|
|||
"version": "1.0.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"number-is-nan": "^1.0.0"
|
||||
}
|
||||
|
@ -13123,7 +13063,6 @@
|
|||
"version": "3.0.4",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"brace-expansion": "^1.1.7"
|
||||
}
|
||||
|
@ -13131,14 +13070,12 @@
|
|||
"minimist": {
|
||||
"version": "0.0.8",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"minipass": {
|
||||
"version": "2.3.5",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"safe-buffer": "^5.1.2",
|
||||
"yallist": "^3.0.0"
|
||||
|
@ -13157,7 +13094,6 @@
|
|||
"version": "0.5.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"minimist": "0.0.8"
|
||||
}
|
||||
|
@ -13238,8 +13174,7 @@
|
|||
"number-is-nan": {
|
||||
"version": "1.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"object-assign": {
|
||||
"version": "4.1.1",
|
||||
|
@ -13251,7 +13186,6 @@
|
|||
"version": "1.4.0",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"wrappy": "1"
|
||||
}
|
||||
|
@ -13337,8 +13271,7 @@
|
|||
"safe-buffer": {
|
||||
"version": "5.1.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"safer-buffer": {
|
||||
"version": "2.1.2",
|
||||
|
@ -13374,7 +13307,6 @@
|
|||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"code-point-at": "^1.0.0",
|
||||
"is-fullwidth-code-point": "^1.0.0",
|
||||
|
@ -13394,7 +13326,6 @@
|
|||
"version": "3.0.1",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-regex": "^2.0.0"
|
||||
}
|
||||
|
@ -13438,14 +13369,12 @@
|
|||
"wrappy": {
|
||||
"version": "1.0.2",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
"version": "3.0.3",
|
||||
"bundled": true,
|
||||
"dev": true,
|
||||
"optional": true
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
|
|
|
@ -113,6 +113,7 @@
|
|||
"ionic-angular": "3.9.3",
|
||||
"ionicons": "^3.0.0",
|
||||
"jszip": "^3.1.5",
|
||||
"mathjax": "2.7.2",
|
||||
"moment": "^2.22.2",
|
||||
"nl.kingsquare.cordova.background-audio": "^1.0.1",
|
||||
"phonegap-plugin-multidex": "^1.0.0",
|
||||
|
|
|
@ -245,8 +245,8 @@ export class AddonCalendarEditEventPage implements OnInit, OnDestroy {
|
|||
const subPromises = [];
|
||||
courses.forEach((course) => {
|
||||
subPromises.push(this.filterHelper.getFiltersAndFormatText(course.fullname, 'course', course.id)
|
||||
.then((text) => {
|
||||
course.fullname = text;
|
||||
.then((result) => {
|
||||
course.fullname = result.text;
|
||||
}).catch(() => {
|
||||
// Ignore errors.
|
||||
}));
|
||||
|
|
|
@ -20,6 +20,7 @@ import { AddonFilterDataModule } from './data/data.module';
|
|||
import { AddonFilterEmailProtectModule } from './emailprotect/emailprotect.module';
|
||||
import { AddonFilterEmoticonModule } from './emoticon/emoticon.module';
|
||||
import { AddonFilterGlossaryModule } from './glossary/glossary.module';
|
||||
import { AddonFilterMathJaxLoaderModule } from './mathjaxloader/mathjaxloader.module';
|
||||
import { AddonFilterMediaPluginModule } from './mediaplugin/mediaplugin.module';
|
||||
import { AddonFilterMultilangModule } from './multilang/multilang.module';
|
||||
import { AddonFilterTexModule } from './tex/tex.module';
|
||||
|
@ -36,6 +37,7 @@ import { AddonFilterUrlToLinkModule } from './urltolink/urltolink.module';
|
|||
AddonFilterEmailProtectModule,
|
||||
AddonFilterEmoticonModule,
|
||||
AddonFilterGlossaryModule,
|
||||
AddonFilterMathJaxLoaderModule,
|
||||
AddonFilterMediaPluginModule,
|
||||
AddonFilterMultilangModule,
|
||||
AddonFilterTexModule,
|
||||
|
|
|
@ -0,0 +1,34 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { NgModule } from '@angular/core';
|
||||
import { IonicModule } from 'ionic-angular';
|
||||
import { CoreFilterDelegate } from '@core/filter/providers/delegate';
|
||||
import { AddonFilterMathJaxLoaderHandler } from './providers/handler';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
],
|
||||
imports: [
|
||||
IonicModule
|
||||
],
|
||||
providers: [
|
||||
AddonFilterMathJaxLoaderHandler
|
||||
]
|
||||
})
|
||||
export class AddonFilterMathJaxLoaderModule {
|
||||
constructor(filterDelegate: CoreFilterDelegate, handler: AddonFilterMathJaxLoaderHandler) {
|
||||
filterDelegate.registerHandler(handler);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,371 @@
|
|||
// (C) Copyright 2015 Moodle Pty Ltd.
|
||||
//
|
||||
// Licensed under the Apache License, Version 2.0 (the "License");
|
||||
// you may not use this file except in compliance with the License.
|
||||
// You may obtain a copy of the License at
|
||||
//
|
||||
// http://www.apache.org/licenses/LICENSE-2.0
|
||||
//
|
||||
// Unless required by applicable law or agreed to in writing, software
|
||||
// distributed under the License is distributed on an "AS IS" BASIS,
|
||||
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
// See the License for the specific language governing permissions and
|
||||
// limitations under the License.
|
||||
|
||||
import { Injectable } from '@angular/core';
|
||||
import { CoreFilterDefaultHandler } from '@core/filter/providers/default-filter';
|
||||
import { CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreEventsProvider } from '@providers/events';
|
||||
import { CoreLangProvider } from '@providers/lang';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreTextUtilsProvider } from '@providers/utils/text';
|
||||
import { CoreUtilsProvider } from '@providers/utils/utils';
|
||||
import { CoreSite } from '@classes/site';
|
||||
|
||||
/**
|
||||
* Handler to support the MathJax filter.
|
||||
*/
|
||||
@Injectable()
|
||||
export class AddonFilterMathJaxLoaderHandler extends CoreFilterDefaultHandler {
|
||||
name = 'AddonFilterMathJaxLoaderHandler';
|
||||
filterName = 'mathjaxloader';
|
||||
|
||||
// Default values for MathJax config for sites where we cannot retrieve it.
|
||||
protected DEFAULT_URL = 'https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.2/MathJax.js';
|
||||
protected DEFAULT_CONFIG = 'MathJax.Hub.Config({' +
|
||||
'config: ["Accessible.js", "Safe.js"],' +
|
||||
'errorSettings: { message: ["!"] },' +
|
||||
'skipStartupTypeset: true,' +
|
||||
'messageStyle: "none"' +
|
||||
'});';
|
||||
|
||||
// List of language codes found in the MathJax/localization/ directory.
|
||||
protected MATHJAX_LANG_CODES = [
|
||||
'ar', 'ast', 'bcc', 'bg', 'br', 'ca', 'cdo', 'ce', 'cs', 'cy', 'da', 'de', 'diq', 'en', 'eo', 'es', 'fa',
|
||||
'fi', 'fr', 'gl', 'he', 'ia', 'it', 'ja', 'kn', 'ko', 'lb', 'lki', 'lt', 'mk', 'nl', 'oc', 'pl', 'pt',
|
||||
'pt-br', 'qqq', 'ru', 'scn', 'sco', 'sk', 'sl', 'sv', 'th', 'tr', 'uk', 'vi', 'zh-hans', 'zh-hant'
|
||||
];
|
||||
|
||||
// List of explicit mappings and known exceptions (moodle => mathjax).
|
||||
protected EXPLICIT_MAPPING = {
|
||||
'zh-tw': 'zh-hant',
|
||||
'zh-cn': 'zh-hans',
|
||||
};
|
||||
|
||||
protected window: any = window; // Convert the window to <any> to be able to use non-standard properties like MathJax.
|
||||
|
||||
constructor(eventsProvider: CoreEventsProvider,
|
||||
private langProvider: CoreLangProvider,
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
private textUtils: CoreTextUtilsProvider,
|
||||
private utils: CoreUtilsProvider) {
|
||||
super();
|
||||
|
||||
// Load the JS.
|
||||
this.loadJS();
|
||||
|
||||
// Get the current language.
|
||||
this.langProvider.getCurrentLanguage().then((lang) => {
|
||||
lang = this.mapLanguageCode(lang);
|
||||
|
||||
// Now call the configure function.
|
||||
this.window.M.filter_mathjaxloader.configure({
|
||||
mathjaxconfig: this.DEFAULT_CONFIG,
|
||||
lang: lang
|
||||
});
|
||||
});
|
||||
|
||||
// Update MathJax locale if app language changes.
|
||||
eventsProvider.on(CoreEventsProvider.LANGUAGE_CHANGED, (lang) => {
|
||||
if (typeof this.window.MathJax != 'undefined') {
|
||||
lang = this.mapLanguageCode(lang);
|
||||
|
||||
this.window.MathJax.Hub.Queue(() => {
|
||||
this.window.MathJax.Localization.setLocale(lang);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Filter some text.
|
||||
*
|
||||
* @param text The text to filter.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Filtered text (or promise resolved with the filtered text).
|
||||
*/
|
||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: string | Promise<string> {
|
||||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
// Don't apply this filter if Moodle is 3.7 or higher and the WS already filtered the content.
|
||||
if (!options.wsNotFiltered && site.isVersionGreaterEqualThan('3.7')) {
|
||||
return text;
|
||||
}
|
||||
|
||||
if (text.indexOf('class="filter_mathjaxloader_equation"') != -1) {
|
||||
// The content seems to have treated mathjax already, don't do it.
|
||||
return text;
|
||||
}
|
||||
|
||||
// We cannot get the filter settings, so we cannot know if it can be used as a replacement for the TeX filter.
|
||||
// Assume it cannot (default value).
|
||||
let hasDisplayOrInline = false;
|
||||
if (text.match(/\\[\[\(]/) || text.match(/\$\$/)) {
|
||||
// Only parse the text if there are mathjax symbols in it.
|
||||
// The recognized math environments are \[ \] and $$ $$ for display mathematics and \( \) for inline mathematics.
|
||||
// Wrap display and inline math environments in nolink spans.
|
||||
const result = this.wrapMathInNoLink(text);
|
||||
text = result.text;
|
||||
hasDisplayOrInline = result.changed;
|
||||
}
|
||||
|
||||
if (hasDisplayOrInline) {
|
||||
return '<span class="filter_mathjaxloader_equation">' + text + '</span>';
|
||||
}
|
||||
|
||||
return text;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle HTML. This function is called after "filter", and it will receive an HTMLElement containing the text that was
|
||||
* filtered.
|
||||
*
|
||||
* @param container The HTML container to handle.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return If async, promise resolved when done.
|
||||
*/
|
||||
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: void | Promise<void> {
|
||||
|
||||
return this.waitForReady().then(() => {
|
||||
this.window.M.filter_mathjaxloader.typeset(container);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Wrap a portion of the $text inside a no link span. The whole text is then returned.
|
||||
*
|
||||
* @param text The text to modify.
|
||||
* @param start The start index of the substring in text that should be wrapped in the span.
|
||||
* @param end The end index of the substring in text that should be wrapped in the span.
|
||||
* @return The whole text with the span inserted around the defined substring.
|
||||
*/
|
||||
protected insertSpan(text: string, start: number, end: number): string {
|
||||
return this.textUtils.substrReplace(text,
|
||||
'<span class="nolink">' + text.substr(start, end - start + 1) + '</span>',
|
||||
start,
|
||||
end - start + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the JS library has been loaded.
|
||||
*
|
||||
* @return Whether the library has been loaded.
|
||||
*/
|
||||
protected jsLoaded(): boolean {
|
||||
return this.window.M && this.window.M.filter_mathjaxloader;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load the JS to make MathJax work in the app. The JS loaded is extracted from Moodle filter's loader JS file.
|
||||
*/
|
||||
protected loadJS(): void {
|
||||
// tslint:disable: no-this-assignment
|
||||
const that = this;
|
||||
|
||||
this.window.M = this.window.M || {};
|
||||
this.window.M.filter_mathjaxloader = this.window.M.filter_mathjaxloader || {
|
||||
_lang: '',
|
||||
_configured: false,
|
||||
// Add the configuration to the head and set the lang.
|
||||
configure: function (params: any): void {
|
||||
// Add a js configuration object to the head.
|
||||
const script = document.createElement('script');
|
||||
script.type = 'text/x-mathjax-config';
|
||||
script.text = params.mathjaxconfig;
|
||||
document.head.appendChild(script);
|
||||
|
||||
// Save the lang config until MathJax is actually loaded.
|
||||
this._lang = params.lang;
|
||||
},
|
||||
// Set the correct language for the MathJax menus.
|
||||
_setLocale: function (): void {
|
||||
if (!this._configured) {
|
||||
const lang = this._lang;
|
||||
|
||||
if (typeof that.window.MathJax != 'undefined') {
|
||||
that.window.MathJax.Hub.Queue(() => {
|
||||
that.window.MathJax.Localization.setLocale(lang);
|
||||
});
|
||||
that.window.MathJax.Hub.Configured();
|
||||
this._configured = true;
|
||||
}
|
||||
}
|
||||
},
|
||||
// Called by the filter when an equation is found while rendering the page.
|
||||
typeset: function (container: HTMLElement): void {
|
||||
if (!this._configured) {
|
||||
this._setLocale();
|
||||
}
|
||||
|
||||
if (typeof that.window.MathJax != 'undefined') {
|
||||
const processDelay = that.window.MathJax.Hub.processSectionDelay;
|
||||
// Set the process section delay to 0 when updating the formula.
|
||||
that.window.MathJax.Hub.processSectionDelay = 0;
|
||||
|
||||
const equations = Array.from(container.querySelectorAll('.filter_mathjaxloader_equation'));
|
||||
equations.forEach((node) => {
|
||||
that.window.MathJax.Hub.Queue(['Typeset', that.window.MathJax.Hub, node]);
|
||||
});
|
||||
|
||||
// Set the delay back to normal after processing.
|
||||
that.window.MathJax.Hub.processSectionDelay = processDelay;
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
/**
|
||||
* Perform a mapping of the app language code to the equivalent for MathJax.
|
||||
*
|
||||
* @param langCode The app language code.
|
||||
* @return The MathJax language code.
|
||||
*/
|
||||
protected mapLanguageCode(langCode: string): string {
|
||||
|
||||
// If defined, explicit mapping takes the highest precedence.
|
||||
if (this.EXPLICIT_MAPPING[langCode]) {
|
||||
return this.EXPLICIT_MAPPING[langCode];
|
||||
}
|
||||
|
||||
// If there is exact match, it will be probably right.
|
||||
if (this.MATHJAX_LANG_CODES.indexOf(langCode) != -1) {
|
||||
return langCode;
|
||||
}
|
||||
|
||||
// Finally try to find the best matching mathjax pack.
|
||||
const parts = langCode.split('-');
|
||||
if (this.MATHJAX_LANG_CODES.indexOf(parts[0]) != -1) {
|
||||
return parts[0];
|
||||
}
|
||||
|
||||
// No more guessing, use default language.
|
||||
return this.langProvider.getDefaultLanguage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
* @param options Options.
|
||||
* @param site Site.
|
||||
* @return Whether filter should be applied.
|
||||
*/
|
||||
shouldBeApplied(options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
// Only apply the filter if logged in and we're filtering current site.
|
||||
return site && site.getId() == this.sitesProvider.getCurrentSiteId();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wait for the MathJax library and our JS object to be loaded.
|
||||
*
|
||||
* @param retries Number of times this has been retried.
|
||||
* @return Promise resolved when ready or if it took too long to load.
|
||||
*/
|
||||
protected waitForReady(retries: number = 0): Promise<any> {
|
||||
if ((this.window.MathJax && this.jsLoaded()) || retries >= 20) {
|
||||
// Loaded or too many retries, stop.
|
||||
return Promise.resolve();
|
||||
}
|
||||
|
||||
const deferred = this.utils.promiseDefer();
|
||||
|
||||
setTimeout(() => {
|
||||
return this.waitForReady(retries + 1).finally(() => {
|
||||
deferred.resolve();
|
||||
});
|
||||
}, 250);
|
||||
|
||||
return deferred.promise;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find math environments in the $text and wrap them in no link spans
|
||||
* (<span class="nolink"></span>). If math environments are nested, only
|
||||
* the outer environment is wrapped in the span.
|
||||
*
|
||||
* The recognized math environments are \[ \] and $$ $$ for display
|
||||
* mathematics and \( \) for inline mathematics.
|
||||
*
|
||||
* @param text The text to filter.
|
||||
* @return Object containing the potentially modified text and a boolean that is true if any changes were made to the text.
|
||||
*/
|
||||
protected wrapMathInNoLink(text: string): {text: string, changed: boolean} {
|
||||
let len = text.length,
|
||||
i = 1,
|
||||
displayStart = -1,
|
||||
displayBracket = false,
|
||||
displayDollar = false,
|
||||
inlineStart = -1,
|
||||
changesDone = false;
|
||||
|
||||
// Loop over the $text once.
|
||||
while (i < len) {
|
||||
if (displayStart === -1) {
|
||||
// No display math has started yet.
|
||||
if (text[i - 1] === '\\') {
|
||||
|
||||
if (text[i] === '[') {
|
||||
// Display mode \[ begins.
|
||||
displayStart = i - 1;
|
||||
displayBracket = true;
|
||||
} else if (text[i] === '(') {
|
||||
// Inline math \( begins, not nested inside display math.
|
||||
inlineStart = i - 1;
|
||||
} else if (text[i] === ')' && inlineStart > -1) {
|
||||
// Inline math ends, not nested inside display math. Wrap the span around it.
|
||||
text = this.insertSpan(text, inlineStart, i);
|
||||
|
||||
inlineStart = -1; // Reset.
|
||||
i += 28; // The text length changed due to the <span>.
|
||||
len += 28;
|
||||
changesDone = true;
|
||||
}
|
||||
|
||||
} else if (text[i - 1] === '$' && text[i] === '$') {
|
||||
// Display mode $$ begins.
|
||||
displayStart = i - 1;
|
||||
displayDollar = true;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Display math open.
|
||||
if ((text[i - 1] === '\\' && text[i] === ']' && displayBracket) ||
|
||||
(text[i - 1] === '$' && text[i] === '$' && displayDollar)) {
|
||||
// Display math ends, wrap the span around it.
|
||||
text = this.insertSpan(text, displayStart, i);
|
||||
|
||||
displayStart = -1; // Reset.
|
||||
displayBracket = false;
|
||||
displayDollar = false;
|
||||
i += 28; // The text length changed due to the <span>.
|
||||
len += 28;
|
||||
changesDone = true;
|
||||
}
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return {
|
||||
text: text,
|
||||
changed: changesDone
|
||||
};
|
||||
}
|
||||
}
|
|
@ -47,11 +47,6 @@ export class AddonFilterMultilangHandler extends CoreFilterDefaultHandler {
|
|||
|
||||
return this.sitesProvider.getSite(siteId).then((site) => {
|
||||
|
||||
// Don't apply this filter if Moodle is 3.7 or higher and the WS already filtered the content.
|
||||
if (!this.shouldBeApplied(options, site)) {
|
||||
return text;
|
||||
}
|
||||
|
||||
return this.langProvider.getCurrentLanguage().then((language) => {
|
||||
// Match the current language.
|
||||
const anyLangRegEx = /<(?:lang|span)[^>]+lang="[a-zA-Z0-9_-]+"[^>]*>(.*?)<\/(?:lang|span)>/g;
|
||||
|
|
|
@ -298,9 +298,9 @@ export class AddonMessagesMainMenuHandler implements CoreMainMenuHandler, CoreCr
|
|||
};
|
||||
|
||||
return this.filterHelper.getFiltersAndFormatText(message.text, 'system', 0, {clean: true, singleLine: true}).catch(() => {
|
||||
return message.text;
|
||||
}).then((formattedText) => {
|
||||
data['text'] = formattedText;
|
||||
return {text: message.text};
|
||||
}).then((result) => {
|
||||
data['text'] = result.text;
|
||||
|
||||
return data;
|
||||
});
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
import { Component, Input, Output, EventEmitter, OnInit } from '@angular/core';
|
||||
import { TranslateService } from '@ngx-translate/core';
|
||||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||
import { CoreFilterProvider } from '@core/filter/providers/filter';
|
||||
|
||||
/**
|
||||
* Component to display a site selector. It will display a select with the list of sites. If the selected site changes,
|
||||
|
@ -35,8 +35,9 @@ export class CoreSitePickerComponent implements OnInit {
|
|||
selectedSite: string;
|
||||
sites: any[];
|
||||
|
||||
constructor(private translate: TranslateService, private sitesProvider: CoreSitesProvider,
|
||||
private filterHelper: CoreFilterHelperProvider) {
|
||||
constructor(private translate: TranslateService,
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
private filterProvider: CoreFilterProvider) {
|
||||
this.siteSelected = new EventEmitter();
|
||||
}
|
||||
|
||||
|
@ -49,12 +50,12 @@ export class CoreSitePickerComponent implements OnInit {
|
|||
|
||||
sites.forEach((site: any) => {
|
||||
// Format the site name.
|
||||
promises.push(this.filterHelper.getFiltersAndFormatText(site.siteName, 'system', 0,
|
||||
{clean: true, singleLine: true}, site.getId()).catch(() => {
|
||||
promises.push(this.filterProvider.formatText(site.siteName, {clean: true, singleLine: true, filter: false}, [],
|
||||
site.getId()).catch(() => {
|
||||
return site.siteName;
|
||||
}).then((formatted) => {
|
||||
}).then((siteName) => {
|
||||
site.fullNameAndSiteName = this.translate.instant('core.fullnameandsitename',
|
||||
{ fullname: site.fullName, sitename: formatted });
|
||||
{ fullname: site.fullName, sitename: siteName });
|
||||
}));
|
||||
});
|
||||
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<img [src]="site.avatar" core-external-content [siteId]="site.id" alt="{{ 'core.pictureof' | translate:{$a: site.fullname} }}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<h2>{{site.fullName}}</h2>
|
||||
<p><core-format-text [text]="site.siteName" clean="true" [siteId]="site.id" contextLevel="system" [contextInstanceId]="0"></core-format-text></p>
|
||||
<p><core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text></p>
|
||||
<p>{{site.siteUrl}}</p>
|
||||
</a>
|
||||
<ion-item>
|
||||
|
|
|
@ -139,7 +139,7 @@ export class CoreCourseModuleCompletionComponent implements OnChanges {
|
|||
|
||||
if (moduleName) {
|
||||
this.filterHelper.getFiltersAndFormatText(moduleName, 'module', this.moduleId,
|
||||
{clean: true, singleLine: true, shortenLength: 50, courseId: this.completion.courseId}).then((modName) => {
|
||||
{clean: true, singleLine: true, shortenLength: 50, courseId: this.completion.courseId}).then((result) => {
|
||||
|
||||
let promise;
|
||||
|
||||
|
@ -150,11 +150,11 @@ export class CoreCourseModuleCompletionComponent implements OnChanges {
|
|||
(profile) => {
|
||||
return {
|
||||
overrideuser: profile.fullname,
|
||||
modname: modName
|
||||
modname: result.text
|
||||
};
|
||||
});
|
||||
} else {
|
||||
promise = Promise.resolve(modName);
|
||||
promise = Promise.resolve(result.text);
|
||||
}
|
||||
|
||||
return promise.then((translateParams) => {
|
||||
|
|
|
@ -264,8 +264,8 @@ export class CoreCourseSectionPage implements OnDestroy {
|
|||
// Format the name of each section and check if it has content.
|
||||
this.sections = sections.map((section) => {
|
||||
this.filterHelper.getFiltersAndFormatText(section.name.trim(), 'course', this.course.id,
|
||||
{clean: true, singleLine: true}).then((name) => {
|
||||
section.formattedName = name;
|
||||
{clean: true, singleLine: true}).then((result) => {
|
||||
section.formattedName = result.text;
|
||||
});
|
||||
section.hasContent = this.courseHelper.sectionHasContent(section);
|
||||
|
||||
|
|
|
@ -43,6 +43,21 @@ export class CoreFilterDefaultHandler implements CoreFilterHandler {
|
|||
return text;
|
||||
}
|
||||
|
||||
/**
|
||||
* Handle HTML. This function is called after "filter", and it will receive an HTMLElement containing the text that was
|
||||
* filtered.
|
||||
*
|
||||
* @param container The HTML container to handle.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return If async, promise resolved when done.
|
||||
*/
|
||||
handleHtml(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: void | Promise<void> {
|
||||
// To be overridden.
|
||||
}
|
||||
|
||||
/**
|
||||
* Whether or not the handler is enabled on a site level.
|
||||
*
|
||||
|
|
|
@ -41,6 +41,19 @@ export interface CoreFilterHandler extends CoreDelegateHandler {
|
|||
*/
|
||||
filter(text: string, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string): string | Promise<string>;
|
||||
|
||||
/**
|
||||
* Handle HTML. This function is called after "filter", and it will receive an HTMLElement containing the text that was
|
||||
* filtered.
|
||||
*
|
||||
* @param container The HTML container to handle.
|
||||
* @param filter The filter.
|
||||
* @param options Options passed to the filters.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return If async, promise resolved when done.
|
||||
*/
|
||||
handleHtml?(container: HTMLElement, filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, siteId?: string)
|
||||
: void | Promise<void>;
|
||||
|
||||
/**
|
||||
* Check if the filter should be applied in a certain site based on some filter options.
|
||||
*
|
||||
|
@ -61,6 +74,7 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
|
||||
constructor(loggerProvider: CoreLoggerProvider, protected sitesProvider: CoreSitesProvider, eventsProvider: CoreEventsProvider,
|
||||
protected defaultHandler: CoreFilterDefaultHandler) {
|
||||
|
||||
super('CoreFilterDelegate', loggerProvider, sitesProvider, eventsProvider);
|
||||
}
|
||||
|
||||
|
@ -79,19 +93,16 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
// Wait for filters to be initialized.
|
||||
return this.handlersInitPromise.then(() => {
|
||||
|
||||
return this.sitesProvider.getSite(siteId);
|
||||
}).then((site) => {
|
||||
|
||||
let promise: Promise<string> = Promise.resolve(text);
|
||||
|
||||
filters = filters || [];
|
||||
options = options || {};
|
||||
|
||||
filters.forEach((filter) => {
|
||||
if (skipFilters && skipFilters.indexOf(filter.filter) != -1) {
|
||||
// Skip this filter.
|
||||
return;
|
||||
}
|
||||
|
||||
if (filter.localstate == -1 || (filter.localstate == 0 && filter.inheritedstate == -1)) {
|
||||
// Filter is disabled, ignore it.
|
||||
if (!this.isEnabledAndShouldApply(filter, options, site, skipFilters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -140,6 +151,77 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
return filters;
|
||||
}
|
||||
|
||||
/**
|
||||
* Let filters handle an HTML element.
|
||||
*
|
||||
* @param container The HTML container to handle.
|
||||
* @param filters Filters to apply.
|
||||
* @param options Options passed to the filters.
|
||||
* @param skipFilters Names of filters that shouldn't be applied.
|
||||
* @param siteId Site ID. If not defined, current site.
|
||||
* @return Promise resolved when done.
|
||||
*/
|
||||
handleHtml(container: HTMLElement, filters: CoreFilterFilter[], options?: any, skipFilters?: string[], siteId?: string)
|
||||
: Promise<any> {
|
||||
|
||||
// Wait for filters to be initialized.
|
||||
return this.handlersInitPromise.then(() => {
|
||||
|
||||
return this.sitesProvider.getSite(siteId);
|
||||
}).then((site) => {
|
||||
|
||||
let promise: Promise<any> = Promise.resolve();
|
||||
|
||||
filters = filters || [];
|
||||
options = options || {};
|
||||
|
||||
filters.forEach((filter) => {
|
||||
if (!this.isEnabledAndShouldApply(filter, options, site, skipFilters)) {
|
||||
return;
|
||||
}
|
||||
|
||||
promise = promise.then(() => {
|
||||
return Promise.resolve(this.executeFunctionOnEnabled(filter.filter, 'handleHtml',
|
||||
[container, filter, options, siteId])).catch((error) => {
|
||||
this.logger.error('Error handling HTML' + filter.filter, error);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
return promise;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if a filter is enabled and should be applied.
|
||||
*
|
||||
* @param filters Filters to apply.
|
||||
* @param options Options passed to the filters.
|
||||
* @param site Site.
|
||||
* @param skipFilters Names of filters that shouldn't be applied.
|
||||
* @return Whether the filter is enabled and should be applied.
|
||||
*/
|
||||
isEnabledAndShouldApply(filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, site: CoreSite,
|
||||
skipFilters?: string[]): boolean {
|
||||
|
||||
if (filter.localstate == -1 || (filter.localstate == 0 && filter.inheritedstate == -1)) {
|
||||
// Filter is disabled, ignore it.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (!this.shouldFilterBeApplied(filter, options, site)) {
|
||||
// Filter shouldn't be applied.
|
||||
return false;
|
||||
}
|
||||
|
||||
if (skipFilters && skipFilters.indexOf(filter.filter) != -1) {
|
||||
// Skip this filter.
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if at least 1 filter should be applied in a certain site and with certain options.
|
||||
*
|
||||
|
@ -151,20 +233,11 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
shouldBeApplied(filters: CoreFilterFilter[], options: CoreFilterFormatTextOptions, site?: CoreSite): Promise<boolean> {
|
||||
// Wait for filters to be initialized.
|
||||
return this.handlersInitPromise.then(() => {
|
||||
const promises = [];
|
||||
let shouldBeApplied = false;
|
||||
|
||||
filters.forEach((filter) => {
|
||||
promises.push(this.shouldFilterBeApplied(filter, options, site).then((applied) => {
|
||||
if (applied) {
|
||||
shouldBeApplied = applied;
|
||||
}
|
||||
}));
|
||||
});
|
||||
|
||||
return Promise.all(promises).then(() => {
|
||||
return shouldBeApplied;
|
||||
});
|
||||
for (let i = 0; i < filters.length; i++) {
|
||||
if (this.shouldFilterBeApplied(filters[i], options, site)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
@ -174,15 +247,14 @@ export class CoreFilterDelegate extends CoreDelegate {
|
|||
* @param filter Filter to check.
|
||||
* @param options Options passed to the filters.
|
||||
* @param site Site. If not defined, current site.
|
||||
* @return {Promise<boolean>} Promise resolved with true: whether the filter should be applied.
|
||||
* @return Whether the filter should be applied.
|
||||
*/
|
||||
protected shouldFilterBeApplied(filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, site?: CoreSite)
|
||||
: Promise<boolean> {
|
||||
protected shouldFilterBeApplied(filter: CoreFilterFilter, options: CoreFilterFormatTextOptions, site?: CoreSite): boolean {
|
||||
|
||||
if (!this.hasHandler(filter.filter, true)) {
|
||||
return Promise.resolve(false);
|
||||
return false;
|
||||
}
|
||||
|
||||
return Promise.resolve(this.executeFunctionOnEnabled(filter.filter, 'shouldBeApplied', [options, site]));
|
||||
return this.executeFunctionOnEnabled(filter.filter, 'shouldBeApplied', [options, site]);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -71,7 +71,7 @@ export class CoreFilterHelperProvider {
|
|||
*/
|
||||
getCourseModulesContexts(courseId: number, siteId?: string): Promise<{contextlevel: string, instanceid: number}[]> {
|
||||
|
||||
return this.courseProvider.getSections(courseId, false, true, {omitExpires: true}, siteId).then((sections) => {
|
||||
return this.courseProvider.getSections(courseId, false, true, undefined, siteId).then((sections) => {
|
||||
const contexts: {contextlevel: string, instanceid: number}[] = [];
|
||||
|
||||
sections.forEach((section) => {
|
||||
|
@ -178,10 +178,12 @@ export class CoreFilterHelperProvider {
|
|||
* @return Promise resolved with the formatted text.
|
||||
*/
|
||||
getFiltersAndFormatText(text: string, contextLevel: string, instanceId: number, options?: CoreFilterFormatTextOptions,
|
||||
siteId?: string): Promise<string> {
|
||||
siteId?: string): Promise<{text: string, filters: CoreFilterFilter[]}> {
|
||||
|
||||
return this.getFilters(contextLevel, instanceId, options, siteId).then((filters) => {
|
||||
return this.filterProvider.formatText(text, options, filters, siteId);
|
||||
return this.filterProvider.formatText(text, options, filters, siteId).then((text) => {
|
||||
return {text: text, filters: filters};
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -19,7 +19,7 @@
|
|||
<img [src]="site.avatar" core-external-content [siteId]="site.id" alt="{{ 'core.pictureof' | translate:{$a: site.fullname} }}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<h2>{{site.fullName}}</h2>
|
||||
<p><core-format-text [text]="site.siteName" clean="true" [siteId]="site.id" contextLevel="system" [contextInstanceId]="0"></core-format-text></p>
|
||||
<p><core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text></p>
|
||||
<p>{{site.siteUrl}}</p>
|
||||
<ion-badge item-end *ngIf="!showDelete && site.badge">{{site.badge}}</ion-badge>
|
||||
<button *ngIf="showDelete" item-end ion-button icon-only clear color="danger" (click)="deleteSite($event, idx)" [attr.aria-label]="'core.delete' | translate">
|
||||
|
|
|
@ -20,7 +20,7 @@ import { CoreSitesProvider, CoreSiteBasicInfo } from '@providers/sites';
|
|||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CorePushNotificationsProvider } from '@core/pushnotifications/providers/pushnotifications';
|
||||
import { CoreLoginHelperProvider } from '../../providers/helper';
|
||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||
import { CoreFilterProvider } from '@core/filter/providers/filter';
|
||||
|
||||
/**
|
||||
* Page that displays the list of stored sites.
|
||||
|
@ -35,9 +35,13 @@ export class CoreLoginSitesPage {
|
|||
showDelete: boolean;
|
||||
protected logger;
|
||||
|
||||
constructor(private domUtils: CoreDomUtilsProvider, private filterHelper: CoreFilterHelperProvider,
|
||||
private sitesProvider: CoreSitesProvider, private loginHelper: CoreLoginHelperProvider, logger: CoreLoggerProvider,
|
||||
private translate: TranslateService, private pushNotificationsProvider: CorePushNotificationsProvider) {
|
||||
constructor(private domUtils: CoreDomUtilsProvider,
|
||||
private filterProvider: CoreFilterProvider,
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
private loginHelper: CoreLoginHelperProvider,
|
||||
logger: CoreLoggerProvider,
|
||||
private translate: TranslateService,
|
||||
private pushNotificationsProvider: CorePushNotificationsProvider) {
|
||||
this.logger = logger.getInstance('CoreLoginSitesPage');
|
||||
}
|
||||
|
||||
|
@ -86,8 +90,7 @@ export class CoreLoginSitesPage {
|
|||
const site = this.sites[index],
|
||||
siteName = site.siteName;
|
||||
|
||||
this.filterHelper.getFiltersAndFormatText(siteName, 'system', 0, {clean: true, singleLine: true}, site.id)
|
||||
.then((siteName) => {
|
||||
this.filterProvider.formatText(siteName, {clean: true, singleLine: true, filter: false}, [], site.id).then((siteName) => {
|
||||
|
||||
this.domUtils.showConfirm(this.translate.instant('core.login.confirmdeletesite', { sitename: siteName })).then(() => {
|
||||
this.sitesProvider.deleteSite(site.id).then(() => {
|
||||
|
|
|
@ -133,7 +133,7 @@ export class CoreSettingsGeneralPage {
|
|||
*/
|
||||
languageChanged(): void {
|
||||
this.langProvider.changeCurrentLanguage(this.selectedLanguage).finally(() => {
|
||||
this.eventsProvider.trigger(CoreEventsProvider.LANGUAGE_CHANGED);
|
||||
this.eventsProvider.trigger(CoreEventsProvider.LANGUAGE_CHANGED, this.selectedLanguage);
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
</ion-refresher>
|
||||
<core-loading [hideUntil]="usageLoaded">
|
||||
<ion-item *ngFor="let site of sites" [class.core-primary-selected-item]="site.id == currentSiteId">
|
||||
<h2 text-wrap><core-format-text [text]="site.siteName" contextLevel="system" [contextInstanceId]="0"></core-format-text></h2>
|
||||
<h2 text-wrap><core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text></h2>
|
||||
<p text-wrap>{{ site.fullName }}</p>
|
||||
<div item-end>
|
||||
<p>{{ site.spaceUsage | coreBytesToSize }}</p>
|
||||
|
|
|
@ -21,7 +21,7 @@ import { CoreFilepoolProvider } from '@providers/filepool';
|
|||
import { CoreSitesProvider } from '@providers/sites';
|
||||
import { CoreDomUtilsProvider } from '@providers/utils/dom';
|
||||
import { CoreCourseProvider } from '@core/course/providers/course';
|
||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||
import { CoreFilterProvider } from '@core/filter/providers/filter';
|
||||
|
||||
/**
|
||||
* Page that displays the space usage settings.
|
||||
|
@ -42,7 +42,7 @@ export class CoreSettingsSpaceUsagePage {
|
|||
constructor(private filePoolProvider: CoreFilepoolProvider,
|
||||
private eventsProvider: CoreEventsProvider,
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
private filterHelper: CoreFilterHelperProvider,
|
||||
private filterProvider: CoreFilterProvider,
|
||||
private translate: TranslateService,
|
||||
private domUtils: CoreDomUtilsProvider,
|
||||
appProvider: CoreAppProvider,
|
||||
|
@ -167,8 +167,8 @@ export class CoreSettingsSpaceUsagePage {
|
|||
* @param siteData Site object with space usage.
|
||||
*/
|
||||
deleteSiteStorage(siteData: any): void {
|
||||
this.filterHelper.getFiltersAndFormatText(siteData.siteName, 'system', 0,
|
||||
{clean: true, singleLine: true}, siteData.id).then((siteName) => {
|
||||
this.filterProvider.formatText(siteData.siteName, {clean: true, singleLine: true, filter: false}, [], siteData.id)
|
||||
.then((siteName) => {
|
||||
|
||||
const title = this.translate.instant('core.settings.deletesitefilestitle');
|
||||
const message = this.translate.instant('core.settings.deletesitefiles', {sitename: siteName});
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
<p>{{ 'core.settings.sites' | translate }}</p>
|
||||
</ion-item-divider>
|
||||
<ion-item *ngFor="let site of sites" [class.core-primary-selected-item]="site.id == currentSiteId" text-wrap>
|
||||
<h2><core-format-text [text]="site.siteName" contextLevel="system" [contextInstanceId]="0"></core-format-text></h2>
|
||||
<h2><core-format-text [text]="site.siteName" clean="true" [siteId]="site.id"></core-format-text></h2>
|
||||
<p>{{ site.fullName }}</p>
|
||||
<p>{{ site.siteUrl }}</p>
|
||||
<button ion-button icon-only clear item-end *ngIf="!isSynchronizing(site.id)" (click)="synchronize(site.id)" [title]="site.siteName" [attr.aria-label]="'core.settings.synchronizenow' | translate">
|
||||
|
|
|
@ -15,7 +15,7 @@
|
|||
<img [src]="site.avatar" core-external-content [siteId]="site.id" alt="{{ 'core.pictureof' | translate:{$a: site.fullname} }}" role="presentation" onError="this.src='assets/img/user-avatar.png'">
|
||||
</ion-avatar>
|
||||
<h2>{{site.fullName}}</h2>
|
||||
<p><core-format-text clean="true" [text]="site.siteName" [siteId]="site.id" contextLevel="system" [contextInstanceId]="0"></core-format-text></p>
|
||||
<p><core-format-text clean="true" [text]="site.siteName" [siteId]="site.id"></core-format-text></p>
|
||||
<p>{{site.siteUrl}}</p>
|
||||
</a>
|
||||
</ion-list>
|
||||
|
|
|
@ -30,8 +30,9 @@ import { CoreLinkDirective } from '../directives/link';
|
|||
import { CoreExternalContentDirective } from '../directives/external-content';
|
||||
import { CoreContentLinksHelperProvider } from '@core/contentlinks/providers/helper';
|
||||
import { CoreSplitViewComponent } from '@components/split-view/split-view';
|
||||
import { CoreFilterProvider } from '@core/filter/providers/filter';
|
||||
import { CoreFilterProvider, CoreFilterFilter, CoreFilterFormatTextOptions } from '@core/filter/providers/filter';
|
||||
import { CoreFilterHelperProvider } from '@core/filter/providers/helper';
|
||||
import { CoreFilterDelegate } from '@core/filter/providers/delegate';
|
||||
|
||||
/**
|
||||
* Directive to format text rendered. It renders the HTML and treats all links and media, using CoreLinkDirective
|
||||
|
@ -70,14 +71,27 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
protected showMoreDisplayed: boolean;
|
||||
protected loadingChangedListener;
|
||||
|
||||
constructor(element: ElementRef, private sitesProvider: CoreSitesProvider, private domUtils: CoreDomUtilsProvider,
|
||||
private textUtils: CoreTextUtilsProvider, private translate: TranslateService, private platform: Platform,
|
||||
private utils: CoreUtilsProvider, private urlUtils: CoreUrlUtilsProvider, private loggerProvider: CoreLoggerProvider,
|
||||
private filepoolProvider: CoreFilepoolProvider, private appProvider: CoreAppProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider, @Optional() private navCtrl: NavController,
|
||||
@Optional() private content: Content, @Optional() private svComponent: CoreSplitViewComponent,
|
||||
private iframeUtils: CoreIframeUtilsProvider, private eventsProvider: CoreEventsProvider,
|
||||
private filterProvider: CoreFilterProvider, private filterHelper: CoreFilterHelperProvider) {
|
||||
constructor(element: ElementRef,
|
||||
private sitesProvider: CoreSitesProvider,
|
||||
private domUtils: CoreDomUtilsProvider,
|
||||
private textUtils: CoreTextUtilsProvider,
|
||||
private translate: TranslateService,
|
||||
private platform: Platform,
|
||||
private utils: CoreUtilsProvider,
|
||||
private urlUtils: CoreUrlUtilsProvider,
|
||||
private loggerProvider: CoreLoggerProvider,
|
||||
private filepoolProvider: CoreFilepoolProvider,
|
||||
private appProvider: CoreAppProvider,
|
||||
private contentLinksHelper: CoreContentLinksHelperProvider,
|
||||
@Optional() private navCtrl: NavController,
|
||||
@Optional() private content: Content, @Optional()
|
||||
private svComponent: CoreSplitViewComponent,
|
||||
private iframeUtils: CoreIframeUtilsProvider,
|
||||
private eventsProvider: CoreEventsProvider,
|
||||
private filterProvider: CoreFilterProvider,
|
||||
private filterHelper: CoreFilterHelperProvider,
|
||||
private filterDelegate: CoreFilterDelegate) {
|
||||
|
||||
this.element = element.nativeElement;
|
||||
this.element.classList.add('opacity-hide'); // Hide contents until they're treated.
|
||||
this.afterRender = new EventEmitter();
|
||||
|
@ -323,15 +337,15 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
|
||||
this.text = this.text ? this.text.trim() : '';
|
||||
|
||||
this.formatContents().then((div: HTMLElement) => {
|
||||
this.formatContents().then((result) => {
|
||||
// Disable media adapt to correctly calculate the height.
|
||||
this.element.classList.add('core-disable-media-adapt');
|
||||
|
||||
this.element.innerHTML = ''; // Remove current contents.
|
||||
if (this.maxHeight && div.innerHTML != '') {
|
||||
if (this.maxHeight && result.div.innerHTML != '') {
|
||||
|
||||
// Move the children to the current element to be able to calculate the height.
|
||||
this.domUtils.moveChildren(div, this.element);
|
||||
this.domUtils.moveChildren(result.div, this.element);
|
||||
|
||||
// Calculate the height now.
|
||||
this.calculateHeight();
|
||||
|
@ -349,12 +363,17 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
});
|
||||
}
|
||||
} else {
|
||||
this.domUtils.moveChildren(div, this.element);
|
||||
this.domUtils.moveChildren(result.div, this.element);
|
||||
|
||||
// Add magnifying glasses to images.
|
||||
this.addMagnifyingGlasses();
|
||||
}
|
||||
|
||||
if (result.options.filter) {
|
||||
// Let filters hnadle HTML. We do it here because we don't want them to block the render of the text.
|
||||
this.filterDelegate.handleHtml(this.element, result.filters, result.options, [], result.siteId);
|
||||
}
|
||||
|
||||
this.element.classList.remove('core-disable-media-adapt');
|
||||
this.finishRender();
|
||||
});
|
||||
|
@ -365,8 +384,15 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
*
|
||||
* @return Promise resolved with a div element containing the code.
|
||||
*/
|
||||
protected formatContents(): Promise<HTMLElement> {
|
||||
protected formatContents(): Promise<{div: HTMLElement, filters: CoreFilterFilter[], options: CoreFilterFormatTextOptions,
|
||||
siteId: string}> {
|
||||
|
||||
const result = {
|
||||
div: <HTMLElement> null,
|
||||
filters: <CoreFilterFilter[]> [],
|
||||
options: <CoreFilterFormatTextOptions> {},
|
||||
siteId: this.siteId
|
||||
};
|
||||
let site: CoreSite;
|
||||
|
||||
// Retrieve the site since it might be needed later.
|
||||
|
@ -374,6 +400,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
// Error getting the site. This probably means that there is no current site and no siteId was supplied.
|
||||
}).then((siteInstance: CoreSite) => {
|
||||
site = siteInstance;
|
||||
result.siteId = site.getId();
|
||||
|
||||
if (this.contextLevel == 'course' && this.contextInstanceId <= 0) {
|
||||
this.contextInstanceId = site.getSiteHomeId();
|
||||
|
@ -381,7 +408,7 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
|
||||
this.filter = typeof this.filter == 'undefined' ? !!(this.contextLevel && this.contextInstanceId) : !!this.filter;
|
||||
|
||||
const options = {
|
||||
result.options = {
|
||||
clean: this.utils.isTrueOrOne(this.clean),
|
||||
singleLine: this.utils.isTrueOrOne(this.singleLine),
|
||||
highlight: this.highlight,
|
||||
|
@ -390,10 +417,15 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
};
|
||||
|
||||
if (this.filter) {
|
||||
return this.filterHelper.getFiltersAndFormatText(this.text, this.contextLevel, this.contextInstanceId, options,
|
||||
site.getId());
|
||||
return this.filterHelper.getFiltersAndFormatText(this.text, this.contextLevel, this.contextInstanceId,
|
||||
result.options, site.getId()).then((res) => {
|
||||
|
||||
result.filters = res.filters;
|
||||
|
||||
return res.text;
|
||||
});
|
||||
} else {
|
||||
return this.filterProvider.formatText(this.text, options);
|
||||
return this.filterProvider.formatText(this.text, result.options, [], site.getId());
|
||||
}
|
||||
|
||||
}).then((formatted) => {
|
||||
|
@ -517,7 +549,9 @@ export class CoreFormatTextDirective implements OnChanges {
|
|||
return promise.catch(() => {
|
||||
// Ignore errors. So content gets always shown.
|
||||
}).then(() => {
|
||||
return div;
|
||||
result.div = div;
|
||||
|
||||
return result;
|
||||
});
|
||||
});
|
||||
}
|
||||
|
|
|
@ -58,6 +58,8 @@
|
|||
|
||||
<link href="build/main.css" rel="stylesheet">
|
||||
|
||||
<script src="lib/mathjax/MathJax.js?delayStartupUntil=configured"></script>
|
||||
|
||||
</head>
|
||||
<body>
|
||||
|
||||
|
|
|
@ -735,6 +735,36 @@ export class CoreTextUtilsProvider {
|
|||
return stripped;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace text within a portion of a string. Equivalent to PHP's substr_replace.
|
||||
* Credits to http://locutus.io/php/strings/substr_replace/
|
||||
*
|
||||
* @param str The string to treat.
|
||||
* @param replace The value to put inside the string.
|
||||
* @param start The index where to start putting the new string. If negative, it will count from the end of the string.
|
||||
* @param length Length of the portion of string which is to be replaced. If negative, it represents the number of characters
|
||||
* from the end of string at which to stop replacing. If not provided, replace until the end of the string.
|
||||
* @return Treated string.
|
||||
*/
|
||||
substrReplace(str: string, replace: string, start: number, length?: number): string {
|
||||
length = typeof length != 'undefined' ? length : str.length;
|
||||
|
||||
if (start < 0) {
|
||||
start = start + str.length;
|
||||
}
|
||||
|
||||
if (length < 0) {
|
||||
length = length + str.length - start;
|
||||
}
|
||||
|
||||
return [
|
||||
str.slice(0, start),
|
||||
replace.substr(0, length),
|
||||
replace.slice(length),
|
||||
str.slice(start + length)
|
||||
].join('');
|
||||
}
|
||||
|
||||
/**
|
||||
* Treat the list of disabled features, replacing old nomenclature with the new one.
|
||||
*
|
||||
|
|
|
@ -44,6 +44,29 @@ export class CoreUrlUtilsProvider {
|
|||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Add params to a URL.
|
||||
*
|
||||
* @param url URL to add the params to.
|
||||
* @param params Object with the params to add.
|
||||
* @return URL with params.
|
||||
*/
|
||||
addParamsToUrl(url: string, params: {[key: string]: any}): string {
|
||||
let separator = url.indexOf('?') != -1 ? '&' : '?';
|
||||
|
||||
for (const key in params) {
|
||||
const value = params[key];
|
||||
|
||||
// Ignore objects.
|
||||
if (typeof value != 'object') {
|
||||
url += separator + key + '=' + value;
|
||||
separator = '&';
|
||||
}
|
||||
}
|
||||
|
||||
return url;
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a URL and a text, return an HTML link.
|
||||
*
|
||||
|
|
Loading…
Reference in New Issue