Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

feat(location): add configurable attr to force html5mode link rewriting #14976

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 14 additions & 3 deletions docs/content/guide/$location.ngdoc
Original file line number Diff line number Diff line change
Expand Up @@ -95,6 +95,8 @@ To configure the `$location` service, retrieve the
`true` or `enabled:true` - see HTML5 mode<br />
`false` or `enabled:false` - see Hashbang mode<br />
`requireBase:true` - see Relative links<br />
`rewriteLinks:true` - see Html link rewriting<br />
`rewriteLinks:'string'` - see Html link rewriting<br />
default: `enabled:false`

- **hashPrefix(prefix)**: {string}<br />
Expand Down Expand Up @@ -326,6 +328,18 @@ reload to the original link.
- Links starting with '/' that lead to a different base path<br>
Example: `<a href="/not-my-base/link">link</a>`

If `html5Mode.rewriteLinks` is set to `false` in the html5Mode definition object passed to
`$locationProvider.html5Mode()`, the browser will perform a full page reload for every link.
`html5Mode.rewriteLinks` can also be set to a string, which will enable link re-writing only on
links that have the given attribute.

For example, if `html5Mode.rewriteLinks` is set to "internal-link":
- `<a href="/some/path" internal-link>link</a>` will be rewritten
- `<a href="/some/path">link</a>` will perform a full page reload

Note that attribute name (de)normalization does not apply here, so "internalLink" is different from
"internal-link".


### Relative links

Expand Down Expand Up @@ -853,6 +867,3 @@ angular.module('locationExample', [])
# Related API

* {@link ng.$location `$location` API}



15 changes: 11 additions & 4 deletions src/ng/location.js
Original file line number Diff line number Diff line change
Expand Up @@ -750,8 +750,12 @@ function $LocationProvider() {
* whether or not a <base> tag is required to be present. If `enabled` and `requireBase` are
* true, and a base tag is not present, an error will be thrown when `$location` is injected.
* See the {@link guide/$location $location guide for more information}
* - **rewriteLinks** - `{boolean}` - (default: `true`) When html5Mode is enabled,
* enables/disables url rewriting for relative links.
* - **rewriteLinks** - `{boolean|String}` - (default: `true`) When html5Mode is enabled,
* enables/disables url rewriting for relative links. If set to a string, url rewriting will
* only happen on links with an attribute that matches the given string. For example, if set
* to "internal-link", then the URL will only be rewritten for `<a internal-link>` links. Note
* that attribute name (de)normalization is not happening here. So "internal-link" is
* different from "internalLink".
*
* @returns {Object} html5Mode object if used as getter or itself (chaining) if used as setter
*/
Expand All @@ -769,7 +773,7 @@ function $LocationProvider() {
html5Mode.requireBase = mode.requireBase;
}

if (isBoolean(mode.rewriteLinks)) {
if (isBoolean(mode.rewriteLinks) || isString(mode.rewriteLinks)) {
html5Mode.rewriteLinks = mode.rewriteLinks;
}

Expand Down Expand Up @@ -866,10 +870,11 @@ function $LocationProvider() {
}

$rootElement.on('click', function(event) {
var rewriteLinks = html5Mode.rewriteLinks;
// TODO(vojta): rewrite link when opening in new tab/window (in legacy browser)
// currently we open nice url link and redirect then

if (!html5Mode.rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which === 2 || event.button === 2) return;
if (!rewriteLinks || event.ctrlKey || event.metaKey || event.shiftKey || event.which === 2 || event.button === 2) return;

var elm = jqLite(event.target);

Expand All @@ -879,6 +884,8 @@ function $LocationProvider() {
if (elm[0] === $rootElement[0] || !(elm = elm.parent())[0]) return;
}

if (isString(rewriteLinks) && isUndefined(elm.attr(rewriteLinks))) return;

var absHref = elm.prop('href');
// get the actual href attribute - see
// http://msdn.microsoft.com/en-us/library/ie/dd347148(v=vs.85).aspx
Expand Down
49 changes: 45 additions & 4 deletions test/ng/locationSpec.js
Original file line number Diff line number Diff line change
Expand Up @@ -1588,7 +1588,7 @@ describe('$location', function() {


it('should not rewrite links when rewriting links is disabled', function() {
configureTestLink({linkHref: 'link?a#b', html5Mode: {enabled: true, rewriteLinks:false}, supportHist: true});
configureTestLink({linkHref: 'link?a#b'});
initService({html5Mode:{enabled: true, rewriteLinks:false},supportHistory:true});
inject(
initBrowser({ url: 'http://host.com/base/index.html', basePath: '/base/index.html' }),
Expand All @@ -1601,6 +1601,34 @@ describe('$location', function() {
});


it('should rewrite links when the specified rewriteLinks attr is detected', function() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We need another test (or entend this test if possible), that verifies that the URL is not rewritten if the link doesn't have the correct attribute. (I.e. I think this test would pass even before the PR.)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done

configureTestLink({linkHref: 'link?a#b', attrs: 'force-rewrite'});
initService({html5Mode:{enabled: true, rewriteLinks:'force-rewrite'},supportHistory:true});
inject(
initBrowser({ url: 'http://host.com/base/index.html', basePath: '/base/index.html' }),
setupRewriteChecks(),
function($browser) {
browserTrigger(link, 'click');
expectRewriteTo($browser, 'http://host.com/base/link?a#b');
}
);
});


it('should not rewrite links when the specified rewriteLinks attr is not detected', function() {
configureTestLink({linkHref: 'link?a#b'});
initService({html5Mode:{enabled: true, rewriteLinks:'yes-rewrite'},supportHistory:true});
inject(
initBrowser({ url: 'http://host.com/base/index.html', basePath: '/base/index.html' }),
setupRewriteChecks(),
function($browser) {
browserTrigger(link, 'click');
expectNoRewrite($browser);
}
);
});


it('should rewrite full url links to same domain and base path', function() {
configureTestLink({linkHref: 'http://host.com/base/new'});
initService({html5Mode:true,supportHistory:false,hashPrefix:'!'});
Expand Down Expand Up @@ -1692,7 +1720,7 @@ describe('$location', function() {

it('should not rewrite when full link to different base path when history enabled on old browser',
function() {
configureTestLink({linkHref: 'http://host.com/other_base/link', html5Mode: true, supportHist: false});
configureTestLink({linkHref: 'http://host.com/other_base/link'});
inject(
initBrowser({ url: 'http://host.com/base/index.html', basePath: '/base/index.html' }),
setupRewriteChecks(),
Expand Down Expand Up @@ -2357,12 +2385,12 @@ describe('$location', function() {
});


it('should only overwrite existing properties if values are boolean', function() {
it('should only overwrite existing properties if values are the correct type', function() {
module(function($locationProvider) {
$locationProvider.html5Mode({
enabled: 'duh',
requireBase: 'probably',
rewriteLinks: 'nope'
rewriteLinks: 500
});

expect($locationProvider.html5Mode()).toEqual({
Expand All @@ -2376,6 +2404,19 @@ describe('$location', function() {
});


it('should allow rewriteLinks config to be set to a string', function() {
module(function($locationProvider) {
$locationProvider.html5Mode({
rewriteLinks: 'yes-rewrite'
});

expect($locationProvider.html5Mode().rewriteLinks).toEqual('yes-rewrite');
});

inject(function() {});
});


it('should not set unknown input properties to html5Mode object', function() {
module(function($locationProvider) {
$locationProvider.html5Mode({
Expand Down