replacement rule to pull independent expression outside of Integrate

I'm trying to write a fairly general replacement rule that will pull expressions independent of the variable of integration outside of Integrate, since Simplify and FullSimplify do not seem to do this.

So as an example I try

Integrate[f[x] Log[y], {x, r, s}] /.
Integrate[q_*r_, {v_, l_, h_}] /; FreeQ[r, v] ->
r*Integrate[q, {v, l, h}]


and that returns

(* (-r f[x] + s f[x]) Log[y] *)


Trace shows it correctly recognized the Log as independent of z and pulled it outside but then, even though it recognizes that f[x] depends on x, it incorrectly does the integration and finally assembles the result.

If f[x] is previously defined, say Sin[x], then this problem does not appear.

Is there a way to write this rule that would be correct in all circumstances?

The problem there is that you are using an immediate rule instead of a delayed rule. So, even before looking at your expression, Mathematica evaluates

r*Integrate[q, {v, l, h}]


to

(h - l) q r


The replacement it is doing is actually

Integrate[q_*r_, {v_, l_, h_}] /; FreeQ[r, v] -> (h - l) q r


Try

Integrate[f[x] Log[y], {x, r, s}] /.
Integrate[q_*r_, {v_, l_, h_}] /; FreeQ[r, v] :>
r*Integrate[q, {v, l, h}]


and you get

(* Integrate[f[x], {x, r, s}]*Log[y] *)